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