• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 //
5 // Review notes:
6 //
7 // - The use of macros in these inline functions may seem superfluous
8 // but it is absolutely needed to make sure gcc generates optimal
9 // code. gcc is not happy when attempting to inline too deep.
10 //
11 
12 #ifndef V8_OBJECTS_OBJECTS_INL_H_
13 #define V8_OBJECTS_OBJECTS_INL_H_
14 
15 #include "src/base/bits.h"
16 #include "src/base/memory.h"
17 #include "src/builtins/builtins.h"
18 #include "src/common/external-pointer-inl.h"
19 #include "src/handles/handles-inl.h"
20 #include "src/heap/factory.h"
21 #include "src/heap/heap-write-barrier-inl.h"
22 #include "src/heap/read-only-heap-inl.h"
23 #include "src/numbers/conversions.h"
24 #include "src/numbers/double.h"
25 #include "src/objects/bigint.h"
26 #include "src/objects/heap-number-inl.h"
27 #include "src/objects/heap-object.h"
28 #include "src/objects/js-proxy-inl.h"  // TODO(jkummerow): Drop.
29 #include "src/objects/keys.h"
30 #include "src/objects/literal-objects.h"
31 #include "src/objects/lookup-inl.h"  // TODO(jkummerow): Drop.
32 #include "src/objects/objects.h"
33 #include "src/objects/oddball.h"
34 #include "src/objects/property-details.h"
35 #include "src/objects/property.h"
36 #include "src/objects/regexp-match-info.h"
37 #include "src/objects/scope-info.h"
38 #include "src/objects/shared-function-info.h"
39 #include "src/objects/slots-inl.h"
40 #include "src/objects/smi-inl.h"
41 #include "src/objects/tagged-field-inl.h"
42 #include "src/objects/tagged-impl-inl.h"
43 #include "src/objects/tagged-index.h"
44 #include "src/objects/templates.h"
45 #include "src/sanitizer/tsan.h"
46 
47 // Has to be the last include (doesn't have include guards):
48 #include "src/objects/object-macros.h"
49 
50 namespace v8 {
51 namespace internal {
52 
PropertyDetails(Smi smi)53 PropertyDetails::PropertyDetails(Smi smi) { value_ = smi.value(); }
54 
AsSmi()55 Smi PropertyDetails::AsSmi() const {
56   // Ensure the upper 2 bits have the same value by sign extending it. This is
57   // necessary to be able to use the 31st bit of the property details.
58   int value = value_ << 1;
59   return Smi::FromInt(value >> 1);
60 }
61 
field_width_in_words()62 int PropertyDetails::field_width_in_words() const {
63   DCHECK_EQ(location(), kField);
64   if (!FLAG_unbox_double_fields) return 1;
65   if (kDoubleSize == kTaggedSize) return 1;
66   return representation().IsDouble() ? kDoubleSize / kTaggedSize : 1;
67 }
68 
DEF_GETTER(HeapObject,IsClassBoilerplate,bool)69 DEF_GETTER(HeapObject, IsClassBoilerplate, bool) {
70   return IsFixedArrayExact(isolate);
71 }
72 
IsTaggedIndex()73 bool Object::IsTaggedIndex() const {
74   return IsSmi() && TaggedIndex::IsValid(TaggedIndex(ptr()).value());
75 }
76 
77 #define IS_TYPE_FUNCTION_DEF(type_)                                      \
78   bool Object::Is##type_() const {                                       \
79     return IsHeapObject() && HeapObject::cast(*this).Is##type_();        \
80   }                                                                      \
81   bool Object::Is##type_(IsolateRoot isolate) const {                    \
82     return IsHeapObject() && HeapObject::cast(*this).Is##type_(isolate); \
83   }
84 HEAP_OBJECT_TYPE_LIST(IS_TYPE_FUNCTION_DEF)
IS_TYPE_FUNCTION_DEF(HashTableBase)85 IS_TYPE_FUNCTION_DEF(HashTableBase)
86 IS_TYPE_FUNCTION_DEF(SmallOrderedHashTable)
87 #undef IS_TYPE_FUNCTION_DEF
88 
89 #define IS_TYPE_FUNCTION_DEF(Type, Value)                        \
90   bool Object::Is##Type(Isolate* isolate) const {                \
91     return Is##Type(ReadOnlyRoots(isolate));                     \
92   }                                                              \
93   bool Object::Is##Type(LocalIsolate* isolate) const {           \
94     return Is##Type(ReadOnlyRoots(isolate));                     \
95   }                                                              \
96   bool Object::Is##Type(ReadOnlyRoots roots) const {             \
97     return *this == roots.Value();                               \
98   }                                                              \
99   bool Object::Is##Type() const {                                \
100     return IsHeapObject() && HeapObject::cast(*this).Is##Type(); \
101   }                                                              \
102   bool HeapObject::Is##Type(Isolate* isolate) const {            \
103     return Object::Is##Type(isolate);                            \
104   }                                                              \
105   bool HeapObject::Is##Type(LocalIsolate* isolate) const {       \
106     return Object::Is##Type(isolate);                            \
107   }                                                              \
108   bool HeapObject::Is##Type(ReadOnlyRoots roots) const {         \
109     return Object::Is##Type(roots);                              \
110   }                                                              \
111   bool HeapObject::Is##Type() const { return Is##Type(GetReadOnlyRoots()); }
112 ODDBALL_LIST(IS_TYPE_FUNCTION_DEF)
113 #undef IS_TYPE_FUNCTION_DEF
114 
115 bool Object::IsNullOrUndefined(Isolate* isolate) const {
116   return IsNullOrUndefined(ReadOnlyRoots(isolate));
117 }
118 
IsNullOrUndefined(ReadOnlyRoots roots)119 bool Object::IsNullOrUndefined(ReadOnlyRoots roots) const {
120   return IsNull(roots) || IsUndefined(roots);
121 }
122 
IsNullOrUndefined()123 bool Object::IsNullOrUndefined() const {
124   return IsHeapObject() && HeapObject::cast(*this).IsNullOrUndefined();
125 }
126 
IsZero()127 bool Object::IsZero() const { return *this == Smi::zero(); }
128 
IsPublicSymbol()129 bool Object::IsPublicSymbol() const {
130   return IsSymbol() && !Symbol::cast(*this).is_private();
131 }
IsPrivateSymbol()132 bool Object::IsPrivateSymbol() const {
133   return IsSymbol() && Symbol::cast(*this).is_private();
134 }
135 
IsNoSharedNameSentinel()136 bool Object::IsNoSharedNameSentinel() const {
137   return *this == SharedFunctionInfo::kNoSharedNameSentinel;
138 }
139 
IsNullOrUndefined(Isolate * isolate)140 bool HeapObject::IsNullOrUndefined(Isolate* isolate) const {
141   return IsNullOrUndefined(ReadOnlyRoots(isolate));
142 }
143 
IsNullOrUndefined(ReadOnlyRoots roots)144 bool HeapObject::IsNullOrUndefined(ReadOnlyRoots roots) const {
145   return Object::IsNullOrUndefined(roots);
146 }
147 
IsNullOrUndefined()148 bool HeapObject::IsNullOrUndefined() const {
149   return IsNullOrUndefined(GetReadOnlyRoots());
150 }
151 
DEF_GETTER(HeapObject,IsUniqueName,bool)152 DEF_GETTER(HeapObject, IsUniqueName, bool) {
153   return IsInternalizedString(isolate) || IsSymbol(isolate);
154 }
155 
DEF_GETTER(HeapObject,IsFunction,bool)156 DEF_GETTER(HeapObject, IsFunction, bool) {
157   STATIC_ASSERT(LAST_FUNCTION_TYPE == LAST_TYPE);
158   return map(isolate).instance_type() >= FIRST_FUNCTION_TYPE;
159 }
160 
DEF_GETTER(HeapObject,IsCallable,bool)161 DEF_GETTER(HeapObject, IsCallable, bool) { return map(isolate).is_callable(); }
162 
DEF_GETTER(HeapObject,IsCallableJSProxy,bool)163 DEF_GETTER(HeapObject, IsCallableJSProxy, bool) {
164   return IsCallable(isolate) && IsJSProxy(isolate);
165 }
166 
DEF_GETTER(HeapObject,IsCallableApiObject,bool)167 DEF_GETTER(HeapObject, IsCallableApiObject, bool) {
168   InstanceType type = map(isolate).instance_type();
169   return IsCallable(isolate) &&
170          (type == JS_API_OBJECT_TYPE || type == JS_SPECIAL_API_OBJECT_TYPE);
171 }
172 
DEF_GETTER(HeapObject,IsNonNullForeign,bool)173 DEF_GETTER(HeapObject, IsNonNullForeign, bool) {
174   return IsForeign(isolate) &&
175          Foreign::cast(*this).foreign_address() != kNullAddress;
176 }
177 
DEF_GETTER(HeapObject,IsConstructor,bool)178 DEF_GETTER(HeapObject, IsConstructor, bool) {
179   return map(isolate).is_constructor();
180 }
181 
DEF_GETTER(HeapObject,IsSourceTextModuleInfo,bool)182 DEF_GETTER(HeapObject, IsSourceTextModuleInfo, bool) {
183   // Can't use ReadOnlyRoots(isolate) as this isolate could be produced by
184   // i::GetIsolateForPtrCompr(HeapObject).
185   return map(isolate) == GetReadOnlyRoots(isolate).module_info_map();
186 }
187 
DEF_GETTER(HeapObject,IsConsString,bool)188 DEF_GETTER(HeapObject, IsConsString, bool) {
189   if (!IsString(isolate)) return false;
190   return StringShape(String::cast(*this).map(isolate)).IsCons();
191 }
192 
DEF_GETTER(HeapObject,IsThinString,bool)193 DEF_GETTER(HeapObject, IsThinString, bool) {
194   if (!IsString(isolate)) return false;
195   return StringShape(String::cast(*this).map(isolate)).IsThin();
196 }
197 
DEF_GETTER(HeapObject,IsSlicedString,bool)198 DEF_GETTER(HeapObject, IsSlicedString, bool) {
199   if (!IsString(isolate)) return false;
200   return StringShape(String::cast(*this).map(isolate)).IsSliced();
201 }
202 
DEF_GETTER(HeapObject,IsSeqString,bool)203 DEF_GETTER(HeapObject, IsSeqString, bool) {
204   if (!IsString(isolate)) return false;
205   return StringShape(String::cast(*this).map(isolate)).IsSequential();
206 }
207 
DEF_GETTER(HeapObject,IsSeqOneByteString,bool)208 DEF_GETTER(HeapObject, IsSeqOneByteString, bool) {
209   if (!IsString(isolate)) return false;
210   return StringShape(String::cast(*this).map(isolate)).IsSequential() &&
211          String::cast(*this).IsOneByteRepresentation(isolate);
212 }
213 
DEF_GETTER(HeapObject,IsSeqTwoByteString,bool)214 DEF_GETTER(HeapObject, IsSeqTwoByteString, bool) {
215   if (!IsString(isolate)) return false;
216   return StringShape(String::cast(*this).map(isolate)).IsSequential() &&
217          String::cast(*this).IsTwoByteRepresentation(isolate);
218 }
219 
DEF_GETTER(HeapObject,IsExternalOneByteString,bool)220 DEF_GETTER(HeapObject, IsExternalOneByteString, bool) {
221   if (!IsString(isolate)) return false;
222   return StringShape(String::cast(*this).map(isolate)).IsExternal() &&
223          String::cast(*this).IsOneByteRepresentation(isolate);
224 }
225 
DEF_GETTER(HeapObject,IsExternalTwoByteString,bool)226 DEF_GETTER(HeapObject, IsExternalTwoByteString, bool) {
227   if (!IsString(isolate)) return false;
228   return StringShape(String::cast(*this).map(isolate)).IsExternal() &&
229          String::cast(*this).IsTwoByteRepresentation(isolate);
230 }
231 
IsNumber()232 bool Object::IsNumber() const {
233   if (IsSmi()) return true;
234   HeapObject this_heap_object = HeapObject::cast(*this);
235   IsolateRoot isolate = GetIsolateForPtrCompr(this_heap_object);
236   return this_heap_object.IsHeapNumber(isolate);
237 }
238 
IsNumber(IsolateRoot isolate)239 bool Object::IsNumber(IsolateRoot isolate) const {
240   return IsSmi() || IsHeapNumber(isolate);
241 }
242 
IsNumeric()243 bool Object::IsNumeric() const {
244   if (IsSmi()) return true;
245   HeapObject this_heap_object = HeapObject::cast(*this);
246   IsolateRoot isolate = GetIsolateForPtrCompr(this_heap_object);
247   return this_heap_object.IsHeapNumber(isolate) ||
248          this_heap_object.IsBigInt(isolate);
249 }
250 
IsNumeric(IsolateRoot isolate)251 bool Object::IsNumeric(IsolateRoot isolate) const {
252   return IsNumber(isolate) || IsBigInt(isolate);
253 }
254 
DEF_GETTER(HeapObject,IsFreeSpaceOrFiller,bool)255 DEF_GETTER(HeapObject, IsFreeSpaceOrFiller, bool) {
256   InstanceType instance_type = map(isolate).instance_type();
257   return instance_type == FREE_SPACE_TYPE || instance_type == FILLER_TYPE;
258 }
259 
DEF_GETTER(HeapObject,IsFrameArray,bool)260 DEF_GETTER(HeapObject, IsFrameArray, bool) {
261   return IsFixedArrayExact(isolate);
262 }
263 
DEF_GETTER(HeapObject,IsArrayList,bool)264 DEF_GETTER(HeapObject, IsArrayList, bool) {
265   // Can't use ReadOnlyRoots(isolate) as this isolate could be produced by
266   // i::GetIsolateForPtrCompr(HeapObject).
267   ReadOnlyRoots roots = GetReadOnlyRoots(isolate);
268   return *this == roots.empty_fixed_array() ||
269          map(isolate) == roots.array_list_map();
270 }
271 
DEF_GETTER(HeapObject,IsRegExpMatchInfo,bool)272 DEF_GETTER(HeapObject, IsRegExpMatchInfo, bool) {
273   return IsFixedArrayExact(isolate);
274 }
275 
IsLayoutDescriptor()276 bool Object::IsLayoutDescriptor() const {
277   if (IsSmi()) return true;
278   HeapObject this_heap_object = HeapObject::cast(*this);
279   IsolateRoot isolate = GetIsolateForPtrCompr(this_heap_object);
280   return this_heap_object.IsByteArray(isolate);
281 }
282 
IsLayoutDescriptor(IsolateRoot isolate)283 bool Object::IsLayoutDescriptor(IsolateRoot isolate) const {
284   return IsSmi() || IsByteArray(isolate);
285 }
286 
DEF_GETTER(HeapObject,IsDeoptimizationData,bool)287 DEF_GETTER(HeapObject, IsDeoptimizationData, bool) {
288   // Must be a fixed array.
289   if (!IsFixedArrayExact(isolate)) return false;
290 
291   // There's no sure way to detect the difference between a fixed array and
292   // a deoptimization data array.  Since this is used for asserts we can
293   // check that the length is zero or else the fixed size plus a multiple of
294   // the entry size.
295   int length = FixedArray::cast(*this).length();
296   if (length == 0) return true;
297 
298   length -= DeoptimizationData::kFirstDeoptEntryIndex;
299   return length >= 0 && length % DeoptimizationData::kDeoptEntrySize == 0;
300 }
301 
DEF_GETTER(HeapObject,IsHandlerTable,bool)302 DEF_GETTER(HeapObject, IsHandlerTable, bool) {
303   if (!IsFixedArrayExact(isolate)) return false;
304   // There's actually no way to see the difference between a fixed array and
305   // a handler table array.
306   return true;
307 }
308 
DEF_GETTER(HeapObject,IsTemplateList,bool)309 DEF_GETTER(HeapObject, IsTemplateList, bool) {
310   if (!IsFixedArrayExact(isolate)) return false;
311   // There's actually no way to see the difference between a fixed array and
312   // a template list.
313   if (FixedArray::cast(*this).length() < 1) return false;
314   return true;
315 }
316 
DEF_GETTER(HeapObject,IsDependentCode,bool)317 DEF_GETTER(HeapObject, IsDependentCode, bool) {
318   if (!IsWeakFixedArray(isolate)) return false;
319   // There's actually no way to see the difference between a weak fixed array
320   // and a dependent codes array.
321   return true;
322 }
323 
DEF_GETTER(HeapObject,IsOSROptimizedCodeCache,bool)324 DEF_GETTER(HeapObject, IsOSROptimizedCodeCache, bool) {
325   if (!IsWeakFixedArray(isolate)) return false;
326   // There's actually no way to see the difference between a weak fixed array
327   // and a osr optimized code cache.
328   return true;
329 }
330 
DEF_GETTER(HeapObject,IsAbstractCode,bool)331 DEF_GETTER(HeapObject, IsAbstractCode, bool) {
332   return IsBytecodeArray(isolate) || IsCode(isolate);
333 }
334 
DEF_GETTER(HeapObject,IsStringWrapper,bool)335 DEF_GETTER(HeapObject, IsStringWrapper, bool) {
336   return IsJSPrimitiveWrapper(isolate) &&
337          JSPrimitiveWrapper::cast(*this).value().IsString(isolate);
338 }
339 
DEF_GETTER(HeapObject,IsBooleanWrapper,bool)340 DEF_GETTER(HeapObject, IsBooleanWrapper, bool) {
341   return IsJSPrimitiveWrapper(isolate) &&
342          JSPrimitiveWrapper::cast(*this).value().IsBoolean(isolate);
343 }
344 
DEF_GETTER(HeapObject,IsScriptWrapper,bool)345 DEF_GETTER(HeapObject, IsScriptWrapper, bool) {
346   return IsJSPrimitiveWrapper(isolate) &&
347          JSPrimitiveWrapper::cast(*this).value().IsScript(isolate);
348 }
349 
DEF_GETTER(HeapObject,IsNumberWrapper,bool)350 DEF_GETTER(HeapObject, IsNumberWrapper, bool) {
351   return IsJSPrimitiveWrapper(isolate) &&
352          JSPrimitiveWrapper::cast(*this).value().IsNumber(isolate);
353 }
354 
DEF_GETTER(HeapObject,IsBigIntWrapper,bool)355 DEF_GETTER(HeapObject, IsBigIntWrapper, bool) {
356   return IsJSPrimitiveWrapper(isolate) &&
357          JSPrimitiveWrapper::cast(*this).value().IsBigInt(isolate);
358 }
359 
DEF_GETTER(HeapObject,IsSymbolWrapper,bool)360 DEF_GETTER(HeapObject, IsSymbolWrapper, bool) {
361   return IsJSPrimitiveWrapper(isolate) &&
362          JSPrimitiveWrapper::cast(*this).value().IsSymbol(isolate);
363 }
364 
DEF_GETTER(HeapObject,IsStringSet,bool)365 DEF_GETTER(HeapObject, IsStringSet, bool) { return IsHashTable(isolate); }
366 
DEF_GETTER(HeapObject,IsObjectHashSet,bool)367 DEF_GETTER(HeapObject, IsObjectHashSet, bool) { return IsHashTable(isolate); }
368 
DEF_GETTER(HeapObject,IsCompilationCacheTable,bool)369 DEF_GETTER(HeapObject, IsCompilationCacheTable, bool) {
370   return IsHashTable(isolate);
371 }
372 
DEF_GETTER(HeapObject,IsMapCache,bool)373 DEF_GETTER(HeapObject, IsMapCache, bool) { return IsHashTable(isolate); }
374 
DEF_GETTER(HeapObject,IsObjectHashTable,bool)375 DEF_GETTER(HeapObject, IsObjectHashTable, bool) { return IsHashTable(isolate); }
376 
DEF_GETTER(HeapObject,IsHashTableBase,bool)377 DEF_GETTER(HeapObject, IsHashTableBase, bool) { return IsHashTable(isolate); }
378 
DEF_GETTER(HeapObject,IsWasmExceptionPackage,bool)379 DEF_GETTER(HeapObject, IsWasmExceptionPackage, bool) {
380   // It is not possible to check for the existence of certain properties on the
381   // underlying {JSReceiver} here because that requires calling handlified code.
382   return IsJSReceiver(isolate);
383 }
384 
IsPrimitive()385 bool Object::IsPrimitive() const {
386   if (IsSmi()) return true;
387   HeapObject this_heap_object = HeapObject::cast(*this);
388   IsolateRoot isolate = GetIsolateForPtrCompr(this_heap_object);
389   return this_heap_object.map(isolate).IsPrimitiveMap();
390 }
391 
IsPrimitive(IsolateRoot isolate)392 bool Object::IsPrimitive(IsolateRoot isolate) const {
393   return IsSmi() || HeapObject::cast(*this).map(isolate).IsPrimitiveMap();
394 }
395 
396 // static
IsArray(Handle<Object> object)397 Maybe<bool> Object::IsArray(Handle<Object> object) {
398   if (object->IsSmi()) return Just(false);
399   Handle<HeapObject> heap_object = Handle<HeapObject>::cast(object);
400   if (heap_object->IsJSArray()) return Just(true);
401   if (!heap_object->IsJSProxy()) return Just(false);
402   return JSProxy::IsArray(Handle<JSProxy>::cast(object));
403 }
404 
DEF_GETTER(HeapObject,IsUndetectable,bool)405 DEF_GETTER(HeapObject, IsUndetectable, bool) {
406   return map(isolate).is_undetectable();
407 }
408 
DEF_GETTER(HeapObject,IsAccessCheckNeeded,bool)409 DEF_GETTER(HeapObject, IsAccessCheckNeeded, bool) {
410   if (IsJSGlobalProxy(isolate)) {
411     const JSGlobalProxy proxy = JSGlobalProxy::cast(*this);
412     JSGlobalObject global = proxy.GetIsolate()->context().global_object();
413     return proxy.IsDetachedFrom(global);
414   }
415   return map(isolate).is_access_check_needed();
416 }
417 
418 #define MAKE_STRUCT_PREDICATE(NAME, Name, name)                         \
419   bool Object::Is##Name() const {                                       \
420     return IsHeapObject() && HeapObject::cast(*this).Is##Name();        \
421   }                                                                     \
422   bool Object::Is##Name(IsolateRoot isolate) const {                    \
423     return IsHeapObject() && HeapObject::cast(*this).Is##Name(isolate); \
424   }
STRUCT_LIST(MAKE_STRUCT_PREDICATE)425 STRUCT_LIST(MAKE_STRUCT_PREDICATE)
426 #undef MAKE_STRUCT_PREDICATE
427 
428 double Object::Number() const {
429   DCHECK(IsNumber());
430   return IsSmi() ? static_cast<double>(Smi(this->ptr()).value())
431                  : HeapNumber::unchecked_cast(*this).value();
432 }
433 
434 // static
SameNumberValue(double value1,double value2)435 bool Object::SameNumberValue(double value1, double value2) {
436   // SameNumberValue(NaN, NaN) is true.
437   if (value1 != value2) {
438     return std::isnan(value1) && std::isnan(value2);
439   }
440   // SameNumberValue(0.0, -0.0) is false.
441   return (std::signbit(value1) == std::signbit(value2));
442 }
443 
IsNaN()444 bool Object::IsNaN() const {
445   return this->IsHeapNumber() && std::isnan(HeapNumber::cast(*this).value());
446 }
447 
IsMinusZero()448 bool Object::IsMinusZero() const {
449   return this->IsHeapNumber() &&
450          i::IsMinusZero(HeapNumber::cast(*this).value());
451 }
452 
OBJECT_CONSTRUCTORS_IMPL(RegExpMatchInfo,FixedArray)453 OBJECT_CONSTRUCTORS_IMPL(RegExpMatchInfo, FixedArray)
454 OBJECT_CONSTRUCTORS_IMPL(ScopeInfo, FixedArray)
455 OBJECT_CONSTRUCTORS_IMPL(BigIntBase, PrimitiveHeapObject)
456 OBJECT_CONSTRUCTORS_IMPL(BigInt, BigIntBase)
457 OBJECT_CONSTRUCTORS_IMPL(FreshlyAllocatedBigInt, BigIntBase)
458 
459 // ------------------------------------
460 // Cast operations
461 
462 CAST_ACCESSOR(BigIntBase)
463 CAST_ACCESSOR(BigInt)
464 CAST_ACCESSOR(RegExpMatchInfo)
465 CAST_ACCESSOR(ScopeInfo)
466 
467 bool Object::HasValidElements() {
468   // Dictionary is covered under FixedArray. ByteArray is used
469   // for the JSTypedArray backing stores.
470   return IsFixedArray() || IsFixedDoubleArray() || IsByteArray();
471 }
472 
FilterKey(PropertyFilter filter)473 bool Object::FilterKey(PropertyFilter filter) {
474   DCHECK(!IsPropertyCell());
475   if (filter == PRIVATE_NAMES_ONLY) {
476     if (!IsSymbol()) return true;
477     return !Symbol::cast(*this).is_private_name();
478   } else if (IsSymbol()) {
479     if (filter & SKIP_SYMBOLS) return true;
480 
481     if (Symbol::cast(*this).is_private()) return true;
482   } else {
483     if (filter & SKIP_STRINGS) return true;
484   }
485   return false;
486 }
487 
OptimalRepresentation(IsolateRoot isolate)488 Representation Object::OptimalRepresentation(IsolateRoot isolate) const {
489   if (!FLAG_track_fields) return Representation::Tagged();
490   if (IsSmi()) {
491     return Representation::Smi();
492   }
493   HeapObject heap_object = HeapObject::cast(*this);
494   if (FLAG_track_double_fields && heap_object.IsHeapNumber(isolate)) {
495     return Representation::Double();
496   } else if (FLAG_track_computed_fields &&
497              heap_object.IsUninitialized(
498                  heap_object.GetReadOnlyRoots(isolate))) {
499     return Representation::None();
500   } else if (FLAG_track_heap_object_fields) {
501     return Representation::HeapObject();
502   } else {
503     return Representation::Tagged();
504   }
505 }
506 
OptimalElementsKind(IsolateRoot isolate)507 ElementsKind Object::OptimalElementsKind(IsolateRoot isolate) const {
508   if (IsSmi()) return PACKED_SMI_ELEMENTS;
509   if (IsNumber(isolate)) return PACKED_DOUBLE_ELEMENTS;
510   return PACKED_ELEMENTS;
511 }
512 
FitsRepresentation(Representation representation)513 bool Object::FitsRepresentation(Representation representation) {
514   if (FLAG_track_fields && representation.IsSmi()) {
515     return IsSmi();
516   } else if (FLAG_track_double_fields && representation.IsDouble()) {
517     return IsNumber();
518   } else if (FLAG_track_heap_object_fields && representation.IsHeapObject()) {
519     return IsHeapObject();
520   } else if (FLAG_track_fields && representation.IsNone()) {
521     return false;
522   }
523   return true;
524 }
525 
ToUint32(uint32_t * value)526 bool Object::ToUint32(uint32_t* value) const {
527   if (IsSmi()) {
528     int num = Smi::ToInt(*this);
529     if (num < 0) return false;
530     *value = static_cast<uint32_t>(num);
531     return true;
532   }
533   if (IsHeapNumber()) {
534     double num = HeapNumber::cast(*this).value();
535     return DoubleToUint32IfEqualToSelf(num, value);
536   }
537   return false;
538 }
539 
540 // static
ToObject(Isolate * isolate,Handle<Object> object,const char * method_name)541 MaybeHandle<JSReceiver> Object::ToObject(Isolate* isolate,
542                                          Handle<Object> object,
543                                          const char* method_name) {
544   if (object->IsJSReceiver()) return Handle<JSReceiver>::cast(object);
545   return ToObjectImpl(isolate, object, method_name);
546 }
547 
548 // static
ToName(Isolate * isolate,Handle<Object> input)549 MaybeHandle<Name> Object::ToName(Isolate* isolate, Handle<Object> input) {
550   if (input->IsName()) return Handle<Name>::cast(input);
551   return ConvertToName(isolate, input);
552 }
553 
554 // static
ToPropertyKey(Isolate * isolate,Handle<Object> value)555 MaybeHandle<Object> Object::ToPropertyKey(Isolate* isolate,
556                                           Handle<Object> value) {
557   if (value->IsSmi() || HeapObject::cast(*value).IsName()) return value;
558   return ConvertToPropertyKey(isolate, value);
559 }
560 
561 // static
ToPrimitive(Handle<Object> input,ToPrimitiveHint hint)562 MaybeHandle<Object> Object::ToPrimitive(Handle<Object> input,
563                                         ToPrimitiveHint hint) {
564   if (input->IsPrimitive()) return input;
565   return JSReceiver::ToPrimitive(Handle<JSReceiver>::cast(input), hint);
566 }
567 
568 // static
ToNumber(Isolate * isolate,Handle<Object> input)569 MaybeHandle<Object> Object::ToNumber(Isolate* isolate, Handle<Object> input) {
570   if (input->IsNumber()) return input;  // Shortcut.
571   return ConvertToNumberOrNumeric(isolate, input, Conversion::kToNumber);
572 }
573 
574 // static
ToNumeric(Isolate * isolate,Handle<Object> input)575 MaybeHandle<Object> Object::ToNumeric(Isolate* isolate, Handle<Object> input) {
576   if (input->IsNumber() || input->IsBigInt()) return input;  // Shortcut.
577   return ConvertToNumberOrNumeric(isolate, input, Conversion::kToNumeric);
578 }
579 
580 // static
ToInteger(Isolate * isolate,Handle<Object> input)581 MaybeHandle<Object> Object::ToInteger(Isolate* isolate, Handle<Object> input) {
582   if (input->IsSmi()) return input;
583   return ConvertToInteger(isolate, input);
584 }
585 
586 // static
ToInt32(Isolate * isolate,Handle<Object> input)587 MaybeHandle<Object> Object::ToInt32(Isolate* isolate, Handle<Object> input) {
588   if (input->IsSmi()) return input;
589   return ConvertToInt32(isolate, input);
590 }
591 
592 // static
ToUint32(Isolate * isolate,Handle<Object> input)593 MaybeHandle<Object> Object::ToUint32(Isolate* isolate, Handle<Object> input) {
594   if (input->IsSmi()) return handle(Smi::cast(*input).ToUint32Smi(), isolate);
595   return ConvertToUint32(isolate, input);
596 }
597 
598 // static
ToString(Isolate * isolate,Handle<Object> input)599 MaybeHandle<String> Object::ToString(Isolate* isolate, Handle<Object> input) {
600   if (input->IsString()) return Handle<String>::cast(input);
601   return ConvertToString(isolate, input);
602 }
603 
604 // static
ToLength(Isolate * isolate,Handle<Object> input)605 MaybeHandle<Object> Object::ToLength(Isolate* isolate, Handle<Object> input) {
606   if (input->IsSmi()) {
607     int value = std::max(Smi::ToInt(*input), 0);
608     return handle(Smi::FromInt(value), isolate);
609   }
610   return ConvertToLength(isolate, input);
611 }
612 
613 // static
ToIndex(Isolate * isolate,Handle<Object> input,MessageTemplate error_index)614 MaybeHandle<Object> Object::ToIndex(Isolate* isolate, Handle<Object> input,
615                                     MessageTemplate error_index) {
616   if (input->IsSmi() && Smi::ToInt(*input) >= 0) return input;
617   return ConvertToIndex(isolate, input, error_index);
618 }
619 
GetProperty(Isolate * isolate,Handle<Object> object,Handle<Name> name)620 MaybeHandle<Object> Object::GetProperty(Isolate* isolate, Handle<Object> object,
621                                         Handle<Name> name) {
622   LookupIterator it(isolate, object, name);
623   if (!it.IsFound()) return it.factory()->undefined_value();
624   return GetProperty(&it);
625 }
626 
GetElement(Isolate * isolate,Handle<Object> object,uint32_t index)627 MaybeHandle<Object> Object::GetElement(Isolate* isolate, Handle<Object> object,
628                                        uint32_t index) {
629   LookupIterator it(isolate, object, index);
630   if (!it.IsFound()) return it.factory()->undefined_value();
631   return GetProperty(&it);
632 }
633 
SetElement(Isolate * isolate,Handle<Object> object,uint32_t index,Handle<Object> value,ShouldThrow should_throw)634 MaybeHandle<Object> Object::SetElement(Isolate* isolate, Handle<Object> object,
635                                        uint32_t index, Handle<Object> value,
636                                        ShouldThrow should_throw) {
637   LookupIterator it(isolate, object, index);
638   MAYBE_RETURN_NULL(
639       SetProperty(&it, value, StoreOrigin::kMaybeKeyed, Just(should_throw)));
640   return value;
641 }
642 
InitExternalPointerField(size_t offset,Isolate * isolate)643 void Object::InitExternalPointerField(size_t offset, Isolate* isolate) {
644   i::InitExternalPointerField(field_address(offset), isolate);
645 }
646 
InitExternalPointerField(size_t offset,Isolate * isolate,Address value,ExternalPointerTag tag)647 void Object::InitExternalPointerField(size_t offset, Isolate* isolate,
648                                       Address value, ExternalPointerTag tag) {
649   i::InitExternalPointerField(field_address(offset), isolate, value, tag);
650 }
651 
ReadExternalPointerField(size_t offset,IsolateRoot isolate,ExternalPointerTag tag)652 Address Object::ReadExternalPointerField(size_t offset, IsolateRoot isolate,
653                                          ExternalPointerTag tag) const {
654   return i::ReadExternalPointerField(field_address(offset), isolate, tag);
655 }
656 
WriteExternalPointerField(size_t offset,Isolate * isolate,Address value,ExternalPointerTag tag)657 void Object::WriteExternalPointerField(size_t offset, Isolate* isolate,
658                                        Address value, ExternalPointerTag tag) {
659   i::WriteExternalPointerField(field_address(offset), isolate, value, tag);
660 }
661 
RawField(int byte_offset)662 ObjectSlot HeapObject::RawField(int byte_offset) const {
663   return ObjectSlot(field_address(byte_offset));
664 }
665 
RawMaybeWeakField(int byte_offset)666 MaybeObjectSlot HeapObject::RawMaybeWeakField(int byte_offset) const {
667   return MaybeObjectSlot(field_address(byte_offset));
668 }
669 
FromMap(const Map map)670 MapWord MapWord::FromMap(const Map map) { return MapWord(map.ptr()); }
671 
ToMap()672 Map MapWord::ToMap() const { return Map::unchecked_cast(Object(value_)); }
673 
IsForwardingAddress()674 bool MapWord::IsForwardingAddress() const { return HAS_SMI_TAG(value_); }
675 
FromForwardingAddress(HeapObject object)676 MapWord MapWord::FromForwardingAddress(HeapObject object) {
677   return MapWord(object.ptr() - kHeapObjectTag);
678 }
679 
ToForwardingAddress()680 HeapObject MapWord::ToForwardingAddress() {
681   DCHECK(IsForwardingAddress());
682   return HeapObject::FromAddress(value_);
683 }
684 
685 #ifdef VERIFY_HEAP
VerifyObjectField(Isolate * isolate,int offset)686 void HeapObject::VerifyObjectField(Isolate* isolate, int offset) {
687   VerifyPointer(isolate, TaggedField<Object>::load(isolate, *this, offset));
688   STATIC_ASSERT(!COMPRESS_POINTERS_BOOL || kTaggedSize == kInt32Size);
689 }
690 
VerifyMaybeObjectField(Isolate * isolate,int offset)691 void HeapObject::VerifyMaybeObjectField(Isolate* isolate, int offset) {
692   MaybeObject::VerifyMaybeObjectPointer(
693       isolate, TaggedField<MaybeObject>::load(isolate, *this, offset));
694   STATIC_ASSERT(!COMPRESS_POINTERS_BOOL || kTaggedSize == kInt32Size);
695 }
696 
VerifySmiField(int offset)697 void HeapObject::VerifySmiField(int offset) {
698   CHECK(TaggedField<Object>::load(*this, offset).IsSmi());
699   STATIC_ASSERT(!COMPRESS_POINTERS_BOOL || kTaggedSize == kInt32Size);
700 }
701 
702 #endif
703 
GetReadOnlyRoots()704 ReadOnlyRoots HeapObject::GetReadOnlyRoots() const {
705   return ReadOnlyHeap::GetReadOnlyRoots(*this);
706 }
707 
GetReadOnlyRoots(IsolateRoot isolate)708 ReadOnlyRoots HeapObject::GetReadOnlyRoots(IsolateRoot isolate) const {
709 #ifdef V8_COMPRESS_POINTERS
710   DCHECK_NE(isolate.address(), 0);
711   return ReadOnlyRoots(Isolate::FromRootAddress(isolate.address()));
712 #else
713   return GetReadOnlyRoots();
714 #endif
715 }
716 
DEF_GETTER(HeapObject,map,Map)717 DEF_GETTER(HeapObject, map, Map) { return map_word(isolate).ToMap(); }
718 
set_map(Map value)719 void HeapObject::set_map(Map value) {
720 #ifdef VERIFY_HEAP
721   if (FLAG_verify_heap && !value.is_null()) {
722     GetHeapFromWritableObject(*this)->VerifyObjectLayoutChange(*this, value);
723   }
724 #endif
725   set_map_word(MapWord::FromMap(value));
726 #ifndef V8_DISABLE_WRITE_BARRIERS
727   if (!value.is_null()) {
728     // TODO(1600) We are passing kNullAddress as a slot because maps can never
729     // be on an evacuation candidate.
730     WriteBarrier::Marking(*this, ObjectSlot(kNullAddress), value);
731   }
732 #endif
733 }
734 
DEF_GETTER(HeapObject,synchronized_map,Map)735 DEF_GETTER(HeapObject, synchronized_map, Map) {
736   return synchronized_map_word(isolate).ToMap();
737 }
738 
synchronized_set_map(Map value)739 void HeapObject::synchronized_set_map(Map value) {
740 #ifdef VERIFY_HEAP
741   if (FLAG_verify_heap && !value.is_null()) {
742     GetHeapFromWritableObject(*this)->VerifyObjectLayoutChange(*this, value);
743   }
744 #endif
745   synchronized_set_map_word(MapWord::FromMap(value));
746 #ifndef V8_DISABLE_WRITE_BARRIERS
747   if (!value.is_null()) {
748     // TODO(1600) We are passing kNullAddress as a slot because maps can never
749     // be on an evacuation candidate.
750     WriteBarrier::Marking(*this, ObjectSlot(kNullAddress), value);
751   }
752 #endif
753 }
754 
755 // Unsafe accessor omitting write barrier.
set_map_no_write_barrier(Map value)756 void HeapObject::set_map_no_write_barrier(Map value) {
757 #ifdef VERIFY_HEAP
758   if (FLAG_verify_heap && !value.is_null()) {
759     GetHeapFromWritableObject(*this)->VerifyObjectLayoutChange(*this, value);
760   }
761 #endif
762   set_map_word(MapWord::FromMap(value));
763 }
764 
set_map_after_allocation(Map value,WriteBarrierMode mode)765 void HeapObject::set_map_after_allocation(Map value, WriteBarrierMode mode) {
766   set_map_word(MapWord::FromMap(value));
767 #ifndef V8_DISABLE_WRITE_BARRIERS
768   if (mode != SKIP_WRITE_BARRIER) {
769     DCHECK(!value.is_null());
770     // TODO(1600) We are passing kNullAddress as a slot because maps can never
771     // be on an evacuation candidate.
772     WriteBarrier::Marking(*this, ObjectSlot(kNullAddress), value);
773   }
774 #endif
775 }
776 
map_slot()777 ObjectSlot HeapObject::map_slot() const {
778   return ObjectSlot(MapField::address(*this));
779 }
780 
DEF_GETTER(HeapObject,map_word,MapWord)781 DEF_GETTER(HeapObject, map_word, MapWord) {
782   return MapField::Relaxed_Load(isolate, *this);
783 }
784 
set_map_word(MapWord map_word)785 void HeapObject::set_map_word(MapWord map_word) {
786   MapField::Relaxed_Store(*this, map_word);
787 }
788 
DEF_GETTER(HeapObject,synchronized_map_word,MapWord)789 DEF_GETTER(HeapObject, synchronized_map_word, MapWord) {
790   return MapField::Acquire_Load(isolate, *this);
791 }
792 
synchronized_set_map_word(MapWord map_word)793 void HeapObject::synchronized_set_map_word(MapWord map_word) {
794   MapField::Release_Store(*this, map_word);
795 }
796 
release_compare_and_swap_map_word(MapWord old_map_word,MapWord new_map_word)797 bool HeapObject::release_compare_and_swap_map_word(MapWord old_map_word,
798                                                    MapWord new_map_word) {
799   Tagged_t result =
800       MapField::Release_CompareAndSwap(*this, old_map_word, new_map_word);
801   return result == static_cast<Tagged_t>(old_map_word.ptr());
802 }
803 
Size()804 int HeapObject::Size() const { return SizeFromMap(map()); }
805 
IsSpecialReceiverInstanceType(InstanceType instance_type)806 inline bool IsSpecialReceiverInstanceType(InstanceType instance_type) {
807   return instance_type <= LAST_SPECIAL_RECEIVER_TYPE;
808 }
809 
810 // This should be in objects/map-inl.h, but can't, because of a cyclic
811 // dependency.
IsSpecialReceiverMap()812 bool Map::IsSpecialReceiverMap() const {
813   bool result = IsSpecialReceiverInstanceType(instance_type());
814   DCHECK_IMPLIES(!result,
815                  !has_named_interceptor() && !is_access_check_needed());
816   return result;
817 }
818 
IsCustomElementsReceiverInstanceType(InstanceType instance_type)819 inline bool IsCustomElementsReceiverInstanceType(InstanceType instance_type) {
820   return instance_type <= LAST_CUSTOM_ELEMENTS_RECEIVER;
821 }
822 
823 // This should be in objects/map-inl.h, but can't, because of a cyclic
824 // dependency.
IsCustomElementsReceiverMap()825 bool Map::IsCustomElementsReceiverMap() const {
826   return IsCustomElementsReceiverInstanceType(instance_type());
827 }
828 
ToArrayLength(uint32_t * index)829 bool Object::ToArrayLength(uint32_t* index) const {
830   return Object::ToUint32(index);
831 }
832 
ToArrayIndex(uint32_t * index)833 bool Object::ToArrayIndex(uint32_t* index) const {
834   return Object::ToUint32(index) && *index != kMaxUInt32;
835 }
836 
ToIntegerIndex(size_t * index)837 bool Object::ToIntegerIndex(size_t* index) const {
838   if (IsSmi()) {
839     int num = Smi::ToInt(*this);
840     if (num < 0) return false;
841     *index = static_cast<size_t>(num);
842     return true;
843   }
844   if (IsHeapNumber()) {
845     double num = HeapNumber::cast(*this).value();
846     if (!(num >= 0)) return false;  // Negation to catch NaNs.
847     constexpr double max =
848         std::min(kMaxSafeInteger,
849                  // The maximum size_t is reserved as "invalid" sentinel.
850                  static_cast<double>(std::numeric_limits<size_t>::max() - 1));
851     if (num > max) return false;
852     size_t result = static_cast<size_t>(num);
853     if (num != result) return false;  // Conversion lost fractional precision.
854     *index = result;
855     return true;
856   }
857   return false;
858 }
859 
NumberOfCaptureRegisters()860 int RegExpMatchInfo::NumberOfCaptureRegisters() {
861   DCHECK_GE(length(), kLastMatchOverhead);
862   Object obj = get(kNumberOfCapturesIndex);
863   return Smi::ToInt(obj);
864 }
865 
SetNumberOfCaptureRegisters(int value)866 void RegExpMatchInfo::SetNumberOfCaptureRegisters(int value) {
867   DCHECK_GE(length(), kLastMatchOverhead);
868   set(kNumberOfCapturesIndex, Smi::FromInt(value));
869 }
870 
LastSubject()871 String RegExpMatchInfo::LastSubject() {
872   DCHECK_GE(length(), kLastMatchOverhead);
873   return String::cast(get(kLastSubjectIndex));
874 }
875 
SetLastSubject(String value)876 void RegExpMatchInfo::SetLastSubject(String value) {
877   DCHECK_GE(length(), kLastMatchOverhead);
878   set(kLastSubjectIndex, value);
879 }
880 
LastInput()881 Object RegExpMatchInfo::LastInput() {
882   DCHECK_GE(length(), kLastMatchOverhead);
883   return get(kLastInputIndex);
884 }
885 
SetLastInput(Object value)886 void RegExpMatchInfo::SetLastInput(Object value) {
887   DCHECK_GE(length(), kLastMatchOverhead);
888   set(kLastInputIndex, value);
889 }
890 
Capture(int i)891 int RegExpMatchInfo::Capture(int i) {
892   DCHECK_LT(i, NumberOfCaptureRegisters());
893   Object obj = get(kFirstCaptureIndex + i);
894   return Smi::ToInt(obj);
895 }
896 
SetCapture(int i,int value)897 void RegExpMatchInfo::SetCapture(int i, int value) {
898   DCHECK_LT(i, NumberOfCaptureRegisters());
899   set(kFirstCaptureIndex + i, Smi::FromInt(value));
900 }
901 
GetWriteBarrierMode(const DisallowHeapAllocation & promise)902 WriteBarrierMode HeapObject::GetWriteBarrierMode(
903     const DisallowHeapAllocation& promise) {
904   return GetWriteBarrierModeForObject(*this, &promise);
905 }
906 
907 // static
RequiredAlignment(Map map)908 AllocationAlignment HeapObject::RequiredAlignment(Map map) {
909   // TODO(bmeurer, v8:4153): We should think about requiring double alignment
910   // in general for ByteArray, since they are used as backing store for typed
911   // arrays now.
912 #ifdef V8_COMPRESS_POINTERS
913   // TODO(ishell, v8:8875): Consider using aligned allocations once the
914   // allocation alignment inconsistency is fixed. For now we keep using
915   // unaligned access since both x64 and arm64 architectures (where pointer
916   // compression is supported) allow unaligned access to doubles and full words.
917 #endif  // V8_COMPRESS_POINTERS
918 #ifdef V8_HOST_ARCH_32_BIT
919   int instance_type = map.instance_type();
920   if (instance_type == FIXED_DOUBLE_ARRAY_TYPE) return kDoubleAligned;
921   if (instance_type == HEAP_NUMBER_TYPE) return kDoubleUnaligned;
922 #endif  // V8_HOST_ARCH_32_BIT
923   return kWordAligned;
924 }
925 
GetFieldAddress(int field_offset)926 Address HeapObject::GetFieldAddress(int field_offset) const {
927   return field_address(field_offset);
928 }
929 
930 // static
GreaterThan(Isolate * isolate,Handle<Object> x,Handle<Object> y)931 Maybe<bool> Object::GreaterThan(Isolate* isolate, Handle<Object> x,
932                                 Handle<Object> y) {
933   Maybe<ComparisonResult> result = Compare(isolate, x, y);
934   if (result.IsJust()) {
935     switch (result.FromJust()) {
936       case ComparisonResult::kGreaterThan:
937         return Just(true);
938       case ComparisonResult::kLessThan:
939       case ComparisonResult::kEqual:
940       case ComparisonResult::kUndefined:
941         return Just(false);
942     }
943   }
944   return Nothing<bool>();
945 }
946 
947 // static
GreaterThanOrEqual(Isolate * isolate,Handle<Object> x,Handle<Object> y)948 Maybe<bool> Object::GreaterThanOrEqual(Isolate* isolate, Handle<Object> x,
949                                        Handle<Object> y) {
950   Maybe<ComparisonResult> result = Compare(isolate, x, y);
951   if (result.IsJust()) {
952     switch (result.FromJust()) {
953       case ComparisonResult::kEqual:
954       case ComparisonResult::kGreaterThan:
955         return Just(true);
956       case ComparisonResult::kLessThan:
957       case ComparisonResult::kUndefined:
958         return Just(false);
959     }
960   }
961   return Nothing<bool>();
962 }
963 
964 // static
LessThan(Isolate * isolate,Handle<Object> x,Handle<Object> y)965 Maybe<bool> Object::LessThan(Isolate* isolate, Handle<Object> x,
966                              Handle<Object> y) {
967   Maybe<ComparisonResult> result = Compare(isolate, x, y);
968   if (result.IsJust()) {
969     switch (result.FromJust()) {
970       case ComparisonResult::kLessThan:
971         return Just(true);
972       case ComparisonResult::kEqual:
973       case ComparisonResult::kGreaterThan:
974       case ComparisonResult::kUndefined:
975         return Just(false);
976     }
977   }
978   return Nothing<bool>();
979 }
980 
981 // static
LessThanOrEqual(Isolate * isolate,Handle<Object> x,Handle<Object> y)982 Maybe<bool> Object::LessThanOrEqual(Isolate* isolate, Handle<Object> x,
983                                     Handle<Object> y) {
984   Maybe<ComparisonResult> result = Compare(isolate, x, y);
985   if (result.IsJust()) {
986     switch (result.FromJust()) {
987       case ComparisonResult::kEqual:
988       case ComparisonResult::kLessThan:
989         return Just(true);
990       case ComparisonResult::kGreaterThan:
991       case ComparisonResult::kUndefined:
992         return Just(false);
993     }
994   }
995   return Nothing<bool>();
996 }
997 
GetPropertyOrElement(Isolate * isolate,Handle<Object> object,Handle<Name> name)998 MaybeHandle<Object> Object::GetPropertyOrElement(Isolate* isolate,
999                                                  Handle<Object> object,
1000                                                  Handle<Name> name) {
1001   LookupIterator::Key key(isolate, name);
1002   LookupIterator it(isolate, object, key);
1003   return GetProperty(&it);
1004 }
1005 
SetPropertyOrElement(Isolate * isolate,Handle<Object> object,Handle<Name> name,Handle<Object> value,Maybe<ShouldThrow> should_throw,StoreOrigin store_origin)1006 MaybeHandle<Object> Object::SetPropertyOrElement(
1007     Isolate* isolate, Handle<Object> object, Handle<Name> name,
1008     Handle<Object> value, Maybe<ShouldThrow> should_throw,
1009     StoreOrigin store_origin) {
1010   LookupIterator::Key key(isolate, name);
1011   LookupIterator it(isolate, object, key);
1012   MAYBE_RETURN_NULL(SetProperty(&it, value, store_origin, should_throw));
1013   return value;
1014 }
1015 
GetPropertyOrElement(Handle<Object> receiver,Handle<Name> name,Handle<JSReceiver> holder)1016 MaybeHandle<Object> Object::GetPropertyOrElement(Handle<Object> receiver,
1017                                                  Handle<Name> name,
1018                                                  Handle<JSReceiver> holder) {
1019   Isolate* isolate = holder->GetIsolate();
1020   LookupIterator::Key key(isolate, name);
1021   LookupIterator it(isolate, receiver, key, holder);
1022   return GetProperty(&it);
1023 }
1024 
1025 // static
GetSimpleHash(Object object)1026 Object Object::GetSimpleHash(Object object) {
1027   DisallowHeapAllocation no_gc;
1028   if (object.IsSmi()) {
1029     uint32_t hash = ComputeUnseededHash(Smi::ToInt(object));
1030     return Smi::FromInt(hash & Smi::kMaxValue);
1031   }
1032   if (object.IsHeapNumber()) {
1033     double num = HeapNumber::cast(object).value();
1034     if (std::isnan(num)) return Smi::FromInt(Smi::kMaxValue);
1035     // Use ComputeUnseededHash for all values in Signed32 range, including -0,
1036     // which is considered equal to 0 because collections use SameValueZero.
1037     uint32_t hash;
1038     // Check range before conversion to avoid undefined behavior.
1039     if (num >= kMinInt && num <= kMaxInt && FastI2D(FastD2I(num)) == num) {
1040       hash = ComputeUnseededHash(FastD2I(num));
1041     } else {
1042       hash = ComputeLongHash(double_to_uint64(num));
1043     }
1044     return Smi::FromInt(hash & Smi::kMaxValue);
1045   }
1046   if (object.IsName()) {
1047     uint32_t hash = Name::cast(object).Hash();
1048     return Smi::FromInt(hash);
1049   }
1050   if (object.IsOddball()) {
1051     uint32_t hash = Oddball::cast(object).to_string().Hash();
1052     return Smi::FromInt(hash);
1053   }
1054   if (object.IsBigInt()) {
1055     uint32_t hash = BigInt::cast(object).Hash();
1056     return Smi::FromInt(hash & Smi::kMaxValue);
1057   }
1058   if (object.IsSharedFunctionInfo()) {
1059     uint32_t hash = SharedFunctionInfo::cast(object).Hash();
1060     return Smi::FromInt(hash & Smi::kMaxValue);
1061   }
1062   DCHECK(object.IsJSReceiver());
1063   return object;
1064 }
1065 
GetHash()1066 Object Object::GetHash() {
1067   DisallowHeapAllocation no_gc;
1068   Object hash = GetSimpleHash(*this);
1069   if (hash.IsSmi()) return hash;
1070 
1071   DCHECK(IsJSReceiver());
1072   JSReceiver receiver = JSReceiver::cast(*this);
1073   return receiver.GetIdentityHash();
1074 }
1075 
AsHandle(Handle<Object> key)1076 Handle<Object> ObjectHashTableShape::AsHandle(Handle<Object> key) {
1077   return key;
1078 }
1079 
Relocatable(Isolate * isolate)1080 Relocatable::Relocatable(Isolate* isolate) {
1081   isolate_ = isolate;
1082   prev_ = isolate->relocatable_top();
1083   isolate->set_relocatable_top(this);
1084 }
1085 
~Relocatable()1086 Relocatable::~Relocatable() {
1087   DCHECK_EQ(isolate_->relocatable_top(), this);
1088   isolate_->set_relocatable_top(prev_);
1089 }
1090 
1091 // Predictably converts HeapObject or Address to uint32 by calculating
1092 // offset of the address in respective MemoryChunk.
ObjectAddressForHashing(Address object)1093 static inline uint32_t ObjectAddressForHashing(Address object) {
1094   uint32_t value = static_cast<uint32_t>(object);
1095   return value & kPageAlignmentMask;
1096 }
1097 
MakeEntryPair(Isolate * isolate,size_t index,Handle<Object> value)1098 static inline Handle<Object> MakeEntryPair(Isolate* isolate, size_t index,
1099                                            Handle<Object> value) {
1100   Handle<Object> key = isolate->factory()->SizeToString(index);
1101   Handle<FixedArray> entry_storage =
1102       isolate->factory()->NewUninitializedFixedArray(2);
1103   {
1104     entry_storage->set(0, *key, SKIP_WRITE_BARRIER);
1105     entry_storage->set(1, *value, SKIP_WRITE_BARRIER);
1106   }
1107   return isolate->factory()->NewJSArrayWithElements(entry_storage,
1108                                                     PACKED_ELEMENTS, 2);
1109 }
1110 
MakeEntryPair(Isolate * isolate,Handle<Object> key,Handle<Object> value)1111 static inline Handle<Object> MakeEntryPair(Isolate* isolate, Handle<Object> key,
1112                                            Handle<Object> value) {
1113   Handle<FixedArray> entry_storage =
1114       isolate->factory()->NewUninitializedFixedArray(2);
1115   {
1116     entry_storage->set(0, *key, SKIP_WRITE_BARRIER);
1117     entry_storage->set(1, *value, SKIP_WRITE_BARRIER);
1118   }
1119   return isolate->factory()->NewJSArrayWithElements(entry_storage,
1120                                                     PACKED_ELEMENTS, 2);
1121 }
1122 
IsAsmModule()1123 bool ScopeInfo::IsAsmModule() const { return IsAsmModuleBit::decode(Flags()); }
1124 
HasSimpleParameters()1125 bool ScopeInfo::HasSimpleParameters() const {
1126   return HasSimpleParametersBit::decode(Flags());
1127 }
1128 
1129 #define FIELD_ACCESSORS(name)                                                 \
1130   void ScopeInfo::Set##name(int value) { set(k##name, Smi::FromInt(value)); } \
1131   int ScopeInfo::name() const {                                               \
1132     if (length() > 0) {                                                       \
1133       return Smi::ToInt(get(k##name));                                        \
1134     } else {                                                                  \
1135       return 0;                                                               \
1136     }                                                                         \
1137   }
FOR_EACH_SCOPE_INFO_NUMERIC_FIELD(FIELD_ACCESSORS)1138 FOR_EACH_SCOPE_INFO_NUMERIC_FIELD(FIELD_ACCESSORS)
1139 #undef FIELD_ACCESSORS
1140 
1141 FreshlyAllocatedBigInt FreshlyAllocatedBigInt::cast(Object object) {
1142   SLOW_DCHECK(object.IsBigInt());
1143   return FreshlyAllocatedBigInt(object.ptr());
1144 }
1145 
1146 }  // namespace internal
1147 }  // namespace v8
1148 
1149 #include "src/objects/object-macros-undef.h"
1150 
1151 #endif  // V8_OBJECTS_OBJECTS_INL_H_
1152