V8 API Reference, 7.2.502.16 (for Deno 0.2.4)
objects-inl.h
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_INL_H_
13 #define V8_OBJECTS_INL_H_
14 
15 #include "src/objects.h"
16 
17 #include "src/base/bits.h"
18 #include "src/base/tsan.h"
19 #include "src/builtins/builtins.h"
20 #include "src/contexts-inl.h"
21 #include "src/conversions-inl.h"
22 #include "src/feedback-vector-inl.h"
23 #include "src/field-index-inl.h"
24 #include "src/handles-inl.h"
25 #include "src/heap/factory.h"
26 #include "src/heap/heap-inl.h" // crbug.com/v8/8499
27 #include "src/isolate-inl.h"
28 #include "src/keys.h"
29 #include "src/layout-descriptor-inl.h"
30 #include "src/lookup-cache-inl.h"
31 #include "src/lookup-inl.h"
32 #include "src/maybe-handles-inl.h"
33 #include "src/objects/bigint.h"
34 #include "src/objects/descriptor-array.h"
35 #include "src/objects/embedder-data-array-inl.h"
36 #include "src/objects/js-proxy-inl.h"
37 #include "src/objects/literal-objects.h"
38 #include "src/objects/maybe-object-inl.h"
39 #include "src/objects/regexp-match-info.h"
40 #include "src/objects/scope-info.h"
41 #include "src/objects/slots-inl.h"
42 #include "src/objects/smi-inl.h"
43 #include "src/objects/template-objects.h"
44 #include "src/objects/templates.h"
45 #include "src/property-details.h"
46 #include "src/property.h"
47 #include "src/prototype-inl.h"
48 #include "src/roots-inl.h"
49 #include "src/transitions-inl.h"
50 #include "src/v8memory.h"
51 
52 // Has to be the last include (doesn't have include guards):
53 #include "src/objects/object-macros.h"
54 
55 namespace v8 {
56 namespace internal {
57 
58 PropertyDetails::PropertyDetails(Smi smi) { value_ = smi->value(); }
59 
60 Smi PropertyDetails::AsSmi() const {
61  // Ensure the upper 2 bits have the same value by sign extending it. This is
62  // necessary to be able to use the 31st bit of the property details.
63  int value = value_ << 1;
64  return Smi::FromInt(value >> 1);
65 }
66 
67 
68 int PropertyDetails::field_width_in_words() const {
69  DCHECK_EQ(location(), kField);
70  if (!FLAG_unbox_double_fields) return 1;
71  if (kDoubleSize == kPointerSize) return 1;
72  return representation().IsDouble() ? kDoubleSize / kPointerSize : 1;
73 }
74 
75 bool HeapObject::IsUncompiledData() const {
76  return IsUncompiledDataWithoutPreParsedScope() ||
77  IsUncompiledDataWithPreParsedScope();
78 }
79 
80 bool HeapObject::IsSloppyArgumentsElements() const {
81  return IsFixedArrayExact();
82 }
83 
84 bool HeapObject::IsJSSloppyArgumentsObject() const {
85  return IsJSArgumentsObject();
86 }
87 
88 bool HeapObject::IsJSGeneratorObject() const {
89  return map()->instance_type() == JS_GENERATOR_OBJECT_TYPE ||
90  IsJSAsyncFunctionObject() || IsJSAsyncGeneratorObject();
91 }
92 
93 bool HeapObject::IsDataHandler() const {
94  return IsLoadHandler() || IsStoreHandler();
95 }
96 
97 bool HeapObject::IsClassBoilerplate() const { return IsFixedArrayExact(); }
98 
99 bool HeapObject::IsExternal(Isolate* isolate) const {
100  return map()->FindRootMap(isolate) == isolate->heap()->external_map();
101 }
102 
103 #define IS_TYPE_FUNCTION_DEF(type_) \
104  bool Object::Is##type_() const { \
105  return IsHeapObject() && HeapObject::cast(this)->Is##type_(); \
106  }
107 HEAP_OBJECT_TYPE_LIST(IS_TYPE_FUNCTION_DEF)
108 #undef IS_TYPE_FUNCTION_DEF
109 
110 #define IS_TYPE_FUNCTION_DEF(Type, Value) \
111  bool Object::Is##Type(Isolate* isolate) const { \
112  return Is##Type(ReadOnlyRoots(isolate->heap())); \
113  } \
114  bool Object::Is##Type(ReadOnlyRoots roots) const { \
115  return this == roots.Value(); \
116  } \
117  bool Object::Is##Type() const { \
118  return IsHeapObject() && HeapObject::cast(this)->Is##Type(); \
119  } \
120  bool HeapObject::Is##Type(Isolate* isolate) const { \
121  return Object::Is##Type(isolate); \
122  } \
123  bool HeapObject::Is##Type(ReadOnlyRoots roots) const { \
124  return Object::Is##Type(roots); \
125  } \
126  bool HeapObject::Is##Type() const { return Is##Type(GetReadOnlyRoots()); }
127 ODDBALL_LIST(IS_TYPE_FUNCTION_DEF)
128 #undef IS_TYPE_FUNCTION_DEF
129 
130 bool Object::IsNullOrUndefined(Isolate* isolate) const {
131  return IsNullOrUndefined(ReadOnlyRoots(isolate));
132 }
133 
134 bool Object::IsNullOrUndefined(ReadOnlyRoots roots) const {
135  return IsNull(roots) || IsUndefined(roots);
136 }
137 
138 bool Object::IsNullOrUndefined() const {
139  return IsHeapObject() && HeapObject::cast(this)->IsNullOrUndefined();
140 }
141 
142 bool HeapObject::IsNullOrUndefined(Isolate* isolate) const {
143  return Object::IsNullOrUndefined(isolate);
144 }
145 
146 bool HeapObject::IsNullOrUndefined(ReadOnlyRoots roots) const {
147  return Object::IsNullOrUndefined(roots);
148 }
149 
150 bool HeapObject::IsNullOrUndefined() const {
151  return IsNullOrUndefined(GetReadOnlyRoots());
152 }
153 
154 bool HeapObject::IsUniqueName() const {
155  return IsInternalizedString() || IsSymbol();
156 }
157 
158 bool HeapObject::IsFunction() const {
159  STATIC_ASSERT(LAST_FUNCTION_TYPE == LAST_TYPE);
160  return map()->instance_type() >= FIRST_FUNCTION_TYPE;
161 }
162 
163 bool HeapObject::IsCallable() const { return map()->is_callable(); }
164 
165 bool HeapObject::IsConstructor() const { return map()->is_constructor(); }
166 
167 bool HeapObject::IsModuleInfo() const {
168  return map() == GetReadOnlyRoots().module_info_map();
169 }
170 
171 bool HeapObject::IsTemplateInfo() const {
172  return IsObjectTemplateInfo() || IsFunctionTemplateInfo();
173 }
174 
175 bool HeapObject::IsConsString() const {
176  if (!IsString()) return false;
177  return StringShape(String::cast(this)).IsCons();
178 }
179 
180 bool HeapObject::IsThinString() const {
181  if (!IsString()) return false;
182  return StringShape(String::cast(this)).IsThin();
183 }
184 
185 bool HeapObject::IsSlicedString() const {
186  if (!IsString()) return false;
187  return StringShape(String::cast(this)).IsSliced();
188 }
189 
190 bool HeapObject::IsSeqString() const {
191  if (!IsString()) return false;
192  return StringShape(String::cast(this)).IsSequential();
193 }
194 
195 bool HeapObject::IsSeqOneByteString() const {
196  if (!IsString()) return false;
197  return StringShape(String::cast(this)).IsSequential() &&
198  String::cast(this)->IsOneByteRepresentation();
199 }
200 
201 bool HeapObject::IsSeqTwoByteString() const {
202  if (!IsString()) return false;
203  return StringShape(String::cast(this)).IsSequential() &&
204  String::cast(this)->IsTwoByteRepresentation();
205 }
206 
207 bool HeapObject::IsExternalString() const {
208  if (!IsString()) return false;
209  return StringShape(String::cast(this)).IsExternal();
210 }
211 
212 bool HeapObject::IsExternalOneByteString() const {
213  if (!IsString()) return false;
214  return StringShape(String::cast(this)).IsExternal() &&
215  String::cast(this)->IsOneByteRepresentation();
216 }
217 
218 bool HeapObject::IsExternalTwoByteString() const {
219  if (!IsString()) return false;
220  return StringShape(String::cast(this)).IsExternal() &&
221  String::cast(this)->IsTwoByteRepresentation();
222 }
223 
224 bool Object::IsNumber() const { return IsSmi() || IsHeapNumber(); }
225 
226 bool Object::IsNumeric() const { return IsNumber() || IsBigInt(); }
227 
228 bool HeapObject::IsFiller() const {
229  InstanceType instance_type = map()->instance_type();
230  return instance_type == FREE_SPACE_TYPE || instance_type == FILLER_TYPE;
231 }
232 
233 bool HeapObject::IsJSWeakCollection() const {
234  return IsJSWeakMap() || IsJSWeakSet();
235 }
236 
237 bool HeapObject::IsJSCollection() const { return IsJSMap() || IsJSSet(); }
238 
239 bool HeapObject::IsPromiseReactionJobTask() const {
240  return IsPromiseFulfillReactionJobTask() || IsPromiseRejectReactionJobTask();
241 }
242 
243 bool HeapObject::IsEnumCache() const { return IsTuple2(); }
244 
245 bool HeapObject::IsFrameArray() const { return IsFixedArrayExact(); }
246 
247 bool HeapObject::IsArrayList() const {
248  return map() == GetReadOnlyRoots().array_list_map() ||
249  this == GetReadOnlyRoots().empty_fixed_array();
250 }
251 
252 bool HeapObject::IsRegExpMatchInfo() const { return IsFixedArrayExact(); }
253 
254 bool Object::IsLayoutDescriptor() const { return IsSmi() || IsByteArray(); }
255 
256 bool HeapObject::IsDeoptimizationData() const {
257  // Must be a fixed array.
258  if (!IsFixedArrayExact()) return false;
259 
260  // There's no sure way to detect the difference between a fixed array and
261  // a deoptimization data array. Since this is used for asserts we can
262  // check that the length is zero or else the fixed size plus a multiple of
263  // the entry size.
264  int length = FixedArray::cast(this)->length();
265  if (length == 0) return true;
266 
267  length -= DeoptimizationData::kFirstDeoptEntryIndex;
268  return length >= 0 && length % DeoptimizationData::kDeoptEntrySize == 0;
269 }
270 
271 bool HeapObject::IsHandlerTable() const {
272  if (!IsFixedArrayExact()) return false;
273  // There's actually no way to see the difference between a fixed array and
274  // a handler table array.
275  return true;
276 }
277 
278 bool HeapObject::IsTemplateList() const {
279  if (!IsFixedArrayExact()) return false;
280  // There's actually no way to see the difference between a fixed array and
281  // a template list.
282  if (FixedArray::cast(this)->length() < 1) return false;
283  return true;
284 }
285 
286 bool HeapObject::IsDependentCode() const {
287  if (!IsWeakFixedArray()) return false;
288  // There's actually no way to see the difference between a weak fixed array
289  // and a dependent codes array.
290  return true;
291 }
292 
293 bool HeapObject::IsAbstractCode() const {
294  return IsBytecodeArray() || IsCode();
295 }
296 
297 bool HeapObject::IsStringWrapper() const {
298  return IsJSValue() && JSValue::cast(this)->value()->IsString();
299 }
300 
301 bool HeapObject::IsBooleanWrapper() const {
302  return IsJSValue() && JSValue::cast(this)->value()->IsBoolean();
303 }
304 
305 bool HeapObject::IsScriptWrapper() const {
306  return IsJSValue() && JSValue::cast(this)->value()->IsScript();
307 }
308 
309 bool HeapObject::IsNumberWrapper() const {
310  return IsJSValue() && JSValue::cast(this)->value()->IsNumber();
311 }
312 
313 bool HeapObject::IsBigIntWrapper() const {
314  return IsJSValue() && JSValue::cast(this)->value()->IsBigInt();
315 }
316 
317 bool HeapObject::IsSymbolWrapper() const {
318  return IsJSValue() && JSValue::cast(this)->value()->IsSymbol();
319 }
320 
321 bool HeapObject::IsBoolean() const {
322  return IsOddball() &&
323  ((Oddball::cast(this)->kind() & Oddball::kNotBooleanMask) == 0);
324 }
325 
326 bool HeapObject::IsJSArrayBufferView() const {
327  return IsJSDataView() || IsJSTypedArray();
328 }
329 
330 bool HeapObject::IsStringSet() const { return IsHashTable(); }
331 
332 bool HeapObject::IsObjectHashSet() const { return IsHashTable(); }
333 
334 bool HeapObject::IsNormalizedMapCache() const {
335  return NormalizedMapCache::IsNormalizedMapCache(this);
336 }
337 
338 bool HeapObject::IsCompilationCacheTable() const { return IsHashTable(); }
339 
340 bool HeapObject::IsMapCache() const { return IsHashTable(); }
341 
342 bool HeapObject::IsObjectHashTable() const { return IsHashTable(); }
343 
344 bool Object::IsSmallOrderedHashTable() const {
345  return IsSmallOrderedHashSet() || IsSmallOrderedHashMap() ||
346  IsSmallOrderedNameDictionary();
347 }
348 
349 bool Object::IsPrimitive() const {
350  return IsSmi() || HeapObject::cast(this)->map()->IsPrimitiveMap();
351 }
352 
353 // static
354 Maybe<bool> Object::IsArray(Handle<Object> object) {
355  if (object->IsSmi()) return Just(false);
356  Handle<HeapObject> heap_object = Handle<HeapObject>::cast(object);
357  if (heap_object->IsJSArray()) return Just(true);
358  if (!heap_object->IsJSProxy()) return Just(false);
359  return JSProxy::IsArray(Handle<JSProxy>::cast(object));
360 }
361 
362 bool HeapObject::IsUndetectable() const { return map()->is_undetectable(); }
363 
364 bool HeapObject::IsAccessCheckNeeded() const {
365  if (IsJSGlobalProxy()) {
366  const JSGlobalProxy* proxy = JSGlobalProxy::cast(this);
367  JSGlobalObject* global = proxy->GetIsolate()->context()->global_object();
368  return proxy->IsDetachedFrom(global);
369  }
370  return map()->is_access_check_needed();
371 }
372 
373 bool HeapObject::IsStruct() const {
374  switch (map()->instance_type()) {
375 #define MAKE_STRUCT_CASE(TYPE, Name, name) \
376  case TYPE: \
377  return true;
378  STRUCT_LIST(MAKE_STRUCT_CASE)
379 #undef MAKE_STRUCT_CASE
380  default:
381  return false;
382  }
383 }
384 
385 #define MAKE_STRUCT_PREDICATE(NAME, Name, name) \
386  bool Object::Is##Name() const { \
387  return IsHeapObject() && HeapObject::cast(this)->Is##Name(); \
388  } \
389  TYPE_CHECKER(Name)
390 STRUCT_LIST(MAKE_STRUCT_PREDICATE)
391 #undef MAKE_STRUCT_PREDICATE
392 
393 double Object::Number() const {
394  DCHECK(IsNumber());
395  return IsSmi() ? static_cast<double>(Smi(this->ptr())->value())
396  : reinterpret_cast<const HeapNumber*>(this)->value();
397 }
398 
399 bool Object::IsNaN() const {
400  return this->IsHeapNumber() && std::isnan(HeapNumber::cast(this)->value());
401 }
402 
403 bool Object::IsMinusZero() const {
404  return this->IsHeapNumber() &&
405  i::IsMinusZero(HeapNumber::cast(this)->value());
406 }
407 
408 OBJECT_CONSTRUCTORS_IMPL(HashTableBase, FixedArray)
409 
410 template <typename Derived, typename Shape>
411 HashTable<Derived, Shape>::HashTable(Address ptr) : HashTableBase(ptr) {
412  SLOW_DCHECK(IsHashTable());
413 }
414 
415 template <typename Derived, typename Shape>
416 ObjectHashTableBase<Derived, Shape>::ObjectHashTableBase(Address ptr)
417  : HashTable<Derived, Shape>(ptr) {}
418 
419 ObjectHashTable::ObjectHashTable(Address ptr)
420  : ObjectHashTableBase<ObjectHashTable, ObjectHashTableShape>(ptr) {
421  SLOW_DCHECK(IsObjectHashTable());
422 }
423 
424 EphemeronHashTable::EphemeronHashTable(Address ptr)
425  : ObjectHashTableBase<EphemeronHashTable, EphemeronHashTableShape>(ptr) {
426  SLOW_DCHECK(IsEphemeronHashTable());
427 }
428 
429 ObjectHashSet::ObjectHashSet(Address ptr)
430  : HashTable<ObjectHashSet, ObjectHashSetShape>(ptr) {
431  SLOW_DCHECK(IsObjectHashSet());
432 }
433 
434 template <typename Derived, typename Shape>
435 Dictionary<Derived, Shape>::Dictionary(Address ptr)
436  : HashTable<Derived, Shape>(ptr) {}
437 
438 template <typename Derived, typename Shape>
439 BaseNameDictionary<Derived, Shape>::BaseNameDictionary(Address ptr)
440  : Dictionary<Derived, Shape>(ptr) {}
441 
442 GlobalDictionary::GlobalDictionary(Address ptr)
443  : BaseNameDictionary<GlobalDictionary, GlobalDictionaryShape>(ptr) {
444  SLOW_DCHECK(IsGlobalDictionary());
445 }
446 
447 NameDictionary::NameDictionary(Address ptr)
448  : BaseNameDictionary<NameDictionary, NameDictionaryShape>(ptr) {
449  SLOW_DCHECK(IsNameDictionary());
450 }
451 
452 NumberDictionary::NumberDictionary(Address ptr)
453  : Dictionary<NumberDictionary, NumberDictionaryShape>(ptr) {
454  SLOW_DCHECK(IsNumberDictionary());
455 }
456 
457 SimpleNumberDictionary::SimpleNumberDictionary(Address ptr)
458  : Dictionary<SimpleNumberDictionary, SimpleNumberDictionaryShape>(ptr) {
459  SLOW_DCHECK(IsSimpleNumberDictionary());
460 }
461 
462 StringTable::StringTable(Address ptr)
463  : HashTable<StringTable, StringTableShape>(ptr) {
464  SLOW_DCHECK(IsStringTable());
465 }
466 
467 StringSet::StringSet(Address ptr) : HashTable<StringSet, StringSetShape>(ptr) {
468  SLOW_DCHECK(IsStringSet());
469 }
470 
471 template <class Derived, int entrysize>
472 OrderedHashTable<Derived, entrysize>::OrderedHashTable(Address ptr)
473  : FixedArray(ptr) {}
474 
475 OrderedHashSet::OrderedHashSet(Address ptr)
476  : OrderedHashTable<OrderedHashSet, 1>(ptr) {
477  SLOW_DCHECK(IsOrderedHashSet());
478 }
479 
480 OrderedHashMap::OrderedHashMap(Address ptr)
481  : OrderedHashTable<OrderedHashMap, 2>(ptr) {
482  SLOW_DCHECK(IsOrderedHashMap());
483 }
484 
485 OrderedNameDictionary::OrderedNameDictionary(Address ptr)
486  : OrderedHashTable<OrderedNameDictionary, 3>(ptr) {
487  SLOW_DCHECK(IsOrderedNameDictionary());
488 }
489 
490 template <class Derived>
491 SmallOrderedHashTable<Derived>::SmallOrderedHashTable(Address ptr)
492  : HeapObjectPtr(ptr) {}
493 
494 OBJECT_CONSTRUCTORS_IMPL(SmallOrderedHashSet,
495  SmallOrderedHashTable<SmallOrderedHashSet>)
496 OBJECT_CONSTRUCTORS_IMPL(SmallOrderedHashMap,
497  SmallOrderedHashTable<SmallOrderedHashMap>)
498 OBJECT_CONSTRUCTORS_IMPL(SmallOrderedNameDictionary,
499  SmallOrderedHashTable<SmallOrderedNameDictionary>)
500 
501 OBJECT_CONSTRUCTORS_IMPL(RegExpMatchInfo, FixedArray)
502 OBJECT_CONSTRUCTORS_IMPL(ScopeInfo, FixedArray)
503 
504 // ------------------------------------
505 // Cast operations
506 
507 CAST_ACCESSOR(AccessorPair)
508 CAST_ACCESSOR(BigInt)
509 CAST_ACCESSOR2(ObjectBoilerplateDescription)
510 CAST_ACCESSOR(Cell)
511 CAST_ACCESSOR(ArrayBoilerplateDescription)
512 CAST_ACCESSOR(DataHandler)
513 CAST_ACCESSOR(DescriptorArray)
514 CAST_ACCESSOR2(EphemeronHashTable)
515 CAST_ACCESSOR(EnumCache)
516 CAST_ACCESSOR(FeedbackCell)
517 CAST_ACCESSOR(Foreign)
518 CAST_ACCESSOR2(GlobalDictionary)
519 CAST_ACCESSOR(HeapObject)
520 CAST_ACCESSOR(HeapNumber)
521 CAST_ACCESSOR(MutableHeapNumber)
522 CAST_ACCESSOR2(OrderedNameDictionary)
523 CAST_ACCESSOR2(NameDictionary)
524 CAST_ACCESSOR(NormalizedMapCache)
525 CAST_ACCESSOR2(NumberDictionary)
526 CAST_ACCESSOR(Object)
527 CAST_ACCESSOR2(ObjectHashSet)
528 CAST_ACCESSOR2(ObjectHashTable)
529 CAST_ACCESSOR(Oddball)
530 CAST_ACCESSOR2(OrderedHashMap)
531 CAST_ACCESSOR2(OrderedHashSet)
532 CAST_ACCESSOR(PropertyCell)
533 CAST_ACCESSOR2(RegExpMatchInfo)
534 CAST_ACCESSOR2(ScopeInfo)
535 CAST_ACCESSOR2(SimpleNumberDictionary)
536 CAST_ACCESSOR2(SmallOrderedHashMap)
537 CAST_ACCESSOR2(SmallOrderedHashSet)
538 CAST_ACCESSOR2(SmallOrderedNameDictionary)
539 CAST_ACCESSOR2(StringSet)
540 CAST_ACCESSOR2(StringTable)
541 CAST_ACCESSOR(Struct)
542 CAST_ACCESSOR(TemplateObjectDescription)
543 CAST_ACCESSOR(Tuple2)
544 CAST_ACCESSOR(Tuple3)
545 
546 bool Object::HasValidElements() {
547  // Dictionary is covered under FixedArray.
548  return IsFixedArray() || IsFixedDoubleArray() || IsFixedTypedArrayBase();
549 }
550 
551 bool Object::KeyEquals(Object* second) {
552  Object* first = this;
553  if (second->IsNumber()) {
554  if (first->IsNumber()) return first->Number() == second->Number();
555  Object* temp = first;
556  first = second;
557  second = temp;
558  }
559  if (first->IsNumber()) {
560  DCHECK_LE(0, first->Number());
561  uint32_t expected = static_cast<uint32_t>(first->Number());
562  uint32_t index;
563  return Name::cast(second)->AsArrayIndex(&index) && index == expected;
564  }
565  return Name::cast(first)->Equals(Name::cast(second));
566 }
567 
568 bool Object::FilterKey(PropertyFilter filter) {
569  DCHECK(!IsPropertyCell());
570  if (IsSymbol()) {
571  if (filter & SKIP_SYMBOLS) return true;
572  if (Symbol::cast(this)->is_private()) return true;
573  } else {
574  if (filter & SKIP_STRINGS) return true;
575  }
576  return false;
577 }
578 
579 Handle<Object> Object::NewStorageFor(Isolate* isolate, Handle<Object> object,
580  Representation representation) {
581  if (!representation.IsDouble()) return object;
582  auto result = isolate->factory()->NewMutableHeapNumberWithHoleNaN();
583  if (object->IsUninitialized(isolate)) {
584  result->set_value_as_bits(kHoleNanInt64);
585  } else if (object->IsMutableHeapNumber()) {
586  // Ensure that all bits of the double value are preserved.
587  result->set_value_as_bits(
588  MutableHeapNumber::cast(*object)->value_as_bits());
589  } else {
590  result->set_value(object->Number());
591  }
592  return result;
593 }
594 
595 Handle<Object> Object::WrapForRead(Isolate* isolate, Handle<Object> object,
596  Representation representation) {
597  DCHECK(!object->IsUninitialized(isolate));
598  if (!representation.IsDouble()) {
599  DCHECK(object->FitsRepresentation(representation));
600  return object;
601  }
602  return isolate->factory()->NewHeapNumber(
603  MutableHeapNumber::cast(*object)->value());
604 }
605 
606 Representation Object::OptimalRepresentation() {
607  if (!FLAG_track_fields) return Representation::Tagged();
608  if (IsSmi()) {
609  return Representation::Smi();
610  } else if (FLAG_track_double_fields && IsHeapNumber()) {
611  return Representation::Double();
612  } else if (FLAG_track_computed_fields && IsUninitialized()) {
613  return Representation::None();
614  } else if (FLAG_track_heap_object_fields) {
615  DCHECK(IsHeapObject());
616  return Representation::HeapObject();
617  } else {
618  return Representation::Tagged();
619  }
620 }
621 
622 
623 ElementsKind Object::OptimalElementsKind() {
624  if (IsSmi()) return PACKED_SMI_ELEMENTS;
625  if (IsNumber()) return PACKED_DOUBLE_ELEMENTS;
626  return PACKED_ELEMENTS;
627 }
628 
629 
630 bool Object::FitsRepresentation(Representation representation) {
631  if (FLAG_track_fields && representation.IsSmi()) {
632  return IsSmi();
633  } else if (FLAG_track_double_fields && representation.IsDouble()) {
634  return IsMutableHeapNumber() || IsNumber();
635  } else if (FLAG_track_heap_object_fields && representation.IsHeapObject()) {
636  return IsHeapObject();
637  } else if (FLAG_track_fields && representation.IsNone()) {
638  return false;
639  }
640  return true;
641 }
642 
643 bool Object::ToUint32(uint32_t* value) const {
644  if (IsSmi()) {
645  int num = Smi::ToInt(this);
646  if (num < 0) return false;
647  *value = static_cast<uint32_t>(num);
648  return true;
649  }
650  if (IsHeapNumber()) {
651  double num = HeapNumber::cast(this)->value();
652  return DoubleToUint32IfEqualToSelf(num, value);
653  }
654  return false;
655 }
656 
657 // static
658 MaybeHandle<JSReceiver> Object::ToObject(Isolate* isolate,
659  Handle<Object> object,
660  const char* method_name) {
661  if (object->IsJSReceiver()) return Handle<JSReceiver>::cast(object);
662  return ToObject(isolate, object, isolate->native_context(), method_name);
663 }
664 
665 
666 // static
667 MaybeHandle<Name> Object::ToName(Isolate* isolate, Handle<Object> input) {
668  if (input->IsName()) return Handle<Name>::cast(input);
669  return ConvertToName(isolate, input);
670 }
671 
672 // static
673 MaybeHandle<Object> Object::ToPropertyKey(Isolate* isolate,
674  Handle<Object> value) {
675  if (value->IsSmi() || HeapObject::cast(*value)->IsName()) return value;
676  return ConvertToPropertyKey(isolate, value);
677 }
678 
679 // static
680 MaybeHandle<Object> Object::ToPrimitive(Handle<Object> input,
681  ToPrimitiveHint hint) {
682  if (input->IsPrimitive()) return input;
683  return JSReceiver::ToPrimitive(Handle<JSReceiver>::cast(input), hint);
684 }
685 
686 // static
687 MaybeHandle<Object> Object::ToNumber(Isolate* isolate, Handle<Object> input) {
688  if (input->IsNumber()) return input; // Shortcut.
689  return ConvertToNumberOrNumeric(isolate, input, Conversion::kToNumber);
690 }
691 
692 // static
693 MaybeHandle<Object> Object::ToNumeric(Isolate* isolate, Handle<Object> input) {
694  if (input->IsNumber() || input->IsBigInt()) return input; // Shortcut.
695  return ConvertToNumberOrNumeric(isolate, input, Conversion::kToNumeric);
696 }
697 
698 // static
699 MaybeHandle<Object> Object::ToInteger(Isolate* isolate, Handle<Object> input) {
700  if (input->IsSmi()) return input;
701  return ConvertToInteger(isolate, input);
702 }
703 
704 // static
705 MaybeHandle<Object> Object::ToInt32(Isolate* isolate, Handle<Object> input) {
706  if (input->IsSmi()) return input;
707  return ConvertToInt32(isolate, input);
708 }
709 
710 // static
711 MaybeHandle<Object> Object::ToUint32(Isolate* isolate, Handle<Object> input) {
712  if (input->IsSmi()) return handle(Smi::cast(*input)->ToUint32Smi(), isolate);
713  return ConvertToUint32(isolate, input);
714 }
715 
716 // static
717 MaybeHandle<String> Object::ToString(Isolate* isolate, Handle<Object> input) {
718  if (input->IsString()) return Handle<String>::cast(input);
719  return ConvertToString(isolate, input);
720 }
721 
722 // static
723 MaybeHandle<Object> Object::ToLength(Isolate* isolate, Handle<Object> input) {
724  if (input->IsSmi()) {
725  int value = std::max(Smi::ToInt(*input), 0);
726  return handle(Smi::FromInt(value), isolate);
727  }
728  return ConvertToLength(isolate, input);
729 }
730 
731 // static
732 MaybeHandle<Object> Object::ToIndex(Isolate* isolate, Handle<Object> input,
733  MessageTemplate error_index) {
734  if (input->IsSmi() && Smi::ToInt(*input) >= 0) return input;
735  return ConvertToIndex(isolate, input, error_index);
736 }
737 
738 MaybeHandle<Object> Object::GetProperty(Isolate* isolate, Handle<Object> object,
739  Handle<Name> name) {
740  LookupIterator it(isolate, object, name);
741  if (!it.IsFound()) return it.factory()->undefined_value();
742  return GetProperty(&it);
743 }
744 
745 MaybeHandle<Object> Object::GetElement(Isolate* isolate, Handle<Object> object,
746  uint32_t index) {
747  LookupIterator it(isolate, object, index);
748  if (!it.IsFound()) return it.factory()->undefined_value();
749  return GetProperty(&it);
750 }
751 
752 MaybeHandle<Object> Object::SetElement(Isolate* isolate, Handle<Object> object,
753  uint32_t index, Handle<Object> value,
754  LanguageMode language_mode) {
755  LookupIterator it(isolate, object, index);
756  MAYBE_RETURN_NULL(
757  SetProperty(&it, value, language_mode, StoreOrigin::kMaybeKeyed));
758  return value;
759 }
760 
761 ObjectSlot HeapObject::RawField(int byte_offset) const {
762  return ObjectSlot(FIELD_ADDR(this, byte_offset));
763 }
764 
765 ObjectSlot HeapObject::RawField(const HeapObject* obj, int byte_offset) {
766  return ObjectSlot(FIELD_ADDR(obj, byte_offset));
767 }
768 
769 MaybeObjectSlot HeapObject::RawMaybeWeakField(int byte_offset) const {
770  return MaybeObjectSlot(FIELD_ADDR(this, byte_offset));
771 }
772 
773 MaybeObjectSlot HeapObject::RawMaybeWeakField(HeapObject* obj,
774  int byte_offset) {
775  return MaybeObjectSlot(FIELD_ADDR(obj, byte_offset));
776 }
777 
778 MapWord MapWord::FromMap(const Map map) { return MapWord(map.ptr()); }
779 
780 Map MapWord::ToMap() const { return Map::unchecked_cast(ObjectPtr(value_)); }
781 
782 bool MapWord::IsForwardingAddress() const { return HAS_SMI_TAG(value_); }
783 
784 MapWord MapWord::FromForwardingAddress(HeapObject* object) {
785  return MapWord(object->ptr() - kHeapObjectTag);
786 }
787 
788 
789 HeapObject* MapWord::ToForwardingAddress() {
790  DCHECK(IsForwardingAddress());
791  return HeapObject::FromAddress(value_);
792 }
793 
794 
795 #ifdef VERIFY_HEAP
796 void HeapObject::VerifyObjectField(Isolate* isolate, int offset) {
797  VerifyPointer(isolate, READ_FIELD(this, offset));
798 }
799 
800 void HeapObject::VerifyMaybeObjectField(Isolate* isolate, int offset) {
801  MaybeObject::VerifyMaybeObjectPointer(isolate, READ_WEAK_FIELD(this, offset));
802 }
803 
804 void HeapObject::VerifySmiField(int offset) {
805  CHECK(READ_FIELD(this, offset)->IsSmi());
806 }
807 
808 void HeapObjectPtr::VerifyObjectField(Isolate* isolate, int offset) {
809  Object::VerifyPointer(isolate, READ_FIELD(this, offset));
810 }
811 
812 void HeapObjectPtr::VerifyMaybeObjectField(Isolate* isolate, int offset) {
813  MaybeObject::VerifyMaybeObjectPointer(isolate, READ_WEAK_FIELD(this, offset));
814 }
815 
816 void HeapObjectPtr::VerifySmiField(int offset) {
817  CHECK(READ_FIELD(this, offset)->IsSmi());
818 }
819 
820 #endif
821 
822 ReadOnlyRoots HeapObject::GetReadOnlyRoots() const {
823  // TODO(v8:7464): When RO_SPACE is embedded, this will access a global
824  // variable instead.
825  return ReadOnlyRoots(MemoryChunk::FromHeapObject(this)->heap());
826 }
827 
828 Heap* NeverReadOnlySpaceObject::GetHeap() const {
829  MemoryChunk* chunk =
830  MemoryChunk::FromAddress(reinterpret_cast<Address>(this));
831  // Make sure we are not accessing an object in RO space.
832  SLOW_DCHECK(chunk->owner()->identity() != RO_SPACE);
833  Heap* heap = chunk->heap();
834  SLOW_DCHECK(heap != nullptr);
835  return heap;
836 }
837 
838 Isolate* NeverReadOnlySpaceObject::GetIsolate() const {
839  return GetHeap()->isolate();
840 }
841 
842 Map HeapObject::map() const { return map_word().ToMap(); }
843 
844 void HeapObject::set_map(Map value) {
845  if (!value.is_null()) {
846 #ifdef VERIFY_HEAP
847  Heap::FromWritableHeapObject(this)->VerifyObjectLayoutChange(this, value);
848 #endif
849  }
850  set_map_word(MapWord::FromMap(value));
851  if (!value.is_null()) {
852  // TODO(1600) We are passing kNullAddress as a slot because maps can never
853  // be on an evacuation candidate.
854  MarkingBarrier(this, ObjectSlot(kNullAddress), value);
855  }
856 }
857 
858 Map HeapObject::synchronized_map() const {
859  return synchronized_map_word().ToMap();
860 }
861 
862 void HeapObject::synchronized_set_map(Map value) {
863  if (!value.is_null()) {
864 #ifdef VERIFY_HEAP
865  Heap::FromWritableHeapObject(this)->VerifyObjectLayoutChange(this, value);
866 #endif
867  }
868  synchronized_set_map_word(MapWord::FromMap(value));
869  if (!value.is_null()) {
870  // TODO(1600) We are passing kNullAddress as a slot because maps can never
871  // be on an evacuation candidate.
872  MarkingBarrier(this, ObjectSlot(kNullAddress), value);
873  }
874 }
875 
876 
877 // Unsafe accessor omitting write barrier.
878 void HeapObject::set_map_no_write_barrier(Map value) {
879  if (!value.is_null()) {
880 #ifdef VERIFY_HEAP
881  Heap::FromWritableHeapObject(this)->VerifyObjectLayoutChange(this, value);
882 #endif
883  }
884  set_map_word(MapWord::FromMap(value));
885 }
886 
887 void HeapObject::set_map_after_allocation(Map value, WriteBarrierMode mode) {
888  set_map_word(MapWord::FromMap(value));
889  if (mode != SKIP_WRITE_BARRIER) {
890  DCHECK(!value.is_null());
891  // TODO(1600) We are passing kNullAddress as a slot because maps can never
892  // be on an evacuation candidate.
893  MarkingBarrier(this, ObjectSlot(kNullAddress), value);
894  }
895 }
896 
897 ObjectSlot HeapObject::map_slot() {
898  return ObjectSlot(FIELD_ADDR(this, kMapOffset));
899 }
900 
901 MapWord HeapObject::map_word() const {
902  return MapWord(RELAXED_READ_FIELD(this, kMapOffset).ptr());
903 }
904 
905 void HeapObject::set_map_word(MapWord map_word) {
906  RELAXED_WRITE_FIELD(this, kMapOffset,
907  reinterpret_cast<Object*>(map_word.value_));
908 }
909 
910 
911 MapWord HeapObject::synchronized_map_word() const {
912  return MapWord(
913  reinterpret_cast<Address>(ACQUIRE_READ_FIELD(this, kMapOffset)));
914 }
915 
916 
917 void HeapObject::synchronized_set_map_word(MapWord map_word) {
918  RELEASE_WRITE_FIELD(
919  this, kMapOffset, reinterpret_cast<Object*>(map_word.value_));
920 }
921 
922 int HeapObject::Size() const { return SizeFromMap(map()); }
923 
924 double HeapNumberBase::value() const {
925  return READ_DOUBLE_FIELD(this, kValueOffset);
926 }
927 
928 void HeapNumberBase::set_value(double value) {
929  WRITE_DOUBLE_FIELD(this, kValueOffset, value);
930 }
931 
932 uint64_t HeapNumberBase::value_as_bits() const {
933  return READ_UINT64_FIELD(this, kValueOffset);
934 }
935 
936 void HeapNumberBase::set_value_as_bits(uint64_t bits) {
937  WRITE_UINT64_FIELD(this, kValueOffset, bits);
938 }
939 
940 int HeapNumberBase::get_exponent() {
941  return ((READ_INT_FIELD(this, kExponentOffset) & kExponentMask) >>
942  kExponentShift) - kExponentBias;
943 }
944 
945 int HeapNumberBase::get_sign() {
946  return READ_INT_FIELD(this, kExponentOffset) & kSignMask;
947 }
948 
949 double Oddball::to_number_raw() const {
950  return READ_DOUBLE_FIELD(this, kToNumberRawOffset);
951 }
952 
953 void Oddball::set_to_number_raw(double value) {
954  WRITE_DOUBLE_FIELD(this, kToNumberRawOffset, value);
955 }
956 
957 void Oddball::set_to_number_raw_as_bits(uint64_t bits) {
958  WRITE_UINT64_FIELD(this, kToNumberRawOffset, bits);
959 }
960 
961 ACCESSORS2(Oddball, to_string, String, kToStringOffset)
962 ACCESSORS(Oddball, to_number, Object, kToNumberOffset)
963 ACCESSORS2(Oddball, type_of, String, kTypeOfOffset)
964 
965 byte Oddball::kind() const { return Smi::ToInt(READ_FIELD(this, kKindOffset)); }
966 
967 void Oddball::set_kind(byte value) {
968  WRITE_FIELD(this, kKindOffset, Smi::FromInt(value));
969 }
970 
971 
972 // static
973 Handle<Object> Oddball::ToNumber(Isolate* isolate, Handle<Oddball> input) {
974  return handle(input->to_number(), isolate);
975 }
976 
977 
978 ACCESSORS(Cell, value, Object, kValueOffset)
979 ACCESSORS(FeedbackCell, value, HeapObject, kValueOffset)
980 ACCESSORS(PropertyCell, dependent_code, DependentCode, kDependentCodeOffset)
981 ACCESSORS2(PropertyCell, name, Name, kNameOffset)
982 ACCESSORS(PropertyCell, value, Object, kValueOffset)
983 ACCESSORS(PropertyCell, property_details_raw, Object, kDetailsOffset)
984 
985 PropertyDetails PropertyCell::property_details() const {
986  return PropertyDetails(Smi::cast(property_details_raw()));
987 }
988 
989 
990 void PropertyCell::set_property_details(PropertyDetails details) {
991  set_property_details_raw(details.AsSmi());
992 }
993 
994 inline bool IsSpecialReceiverInstanceType(InstanceType instance_type) {
995  return instance_type <= LAST_SPECIAL_RECEIVER_TYPE;
996 }
997 
998 // This should be in objects/map-inl.h, but can't, because of a cyclic
999 // dependency.
1000 bool Map::IsSpecialReceiverMap() const {
1001  bool result = IsSpecialReceiverInstanceType(instance_type());
1002  DCHECK_IMPLIES(!result,
1003  !has_named_interceptor() && !is_access_check_needed());
1004  return result;
1005 }
1006 
1007 inline bool IsCustomElementsReceiverInstanceType(InstanceType instance_type) {
1008  return instance_type <= LAST_CUSTOM_ELEMENTS_RECEIVER;
1009 }
1010 
1011 // This should be in objects/map-inl.h, but can't, because of a cyclic
1012 // dependency.
1013 bool Map::IsCustomElementsReceiverMap() const {
1014  return IsCustomElementsReceiverInstanceType(instance_type());
1015 }
1016 
1017 void Struct::InitializeBody(int object_size) {
1018  Object* value = GetReadOnlyRoots().undefined_value();
1019  for (int offset = kHeaderSize; offset < object_size; offset += kPointerSize) {
1020  WRITE_FIELD(this, offset, value);
1021  }
1022 }
1023 
1024 bool Object::ToArrayLength(uint32_t* index) const {
1025  return Object::ToUint32(index);
1026 }
1027 
1028 bool Object::ToArrayIndex(uint32_t* index) const {
1029  return Object::ToUint32(index) && *index != kMaxUInt32;
1030 }
1031 
1032 
1033 void Object::VerifyApiCallResultType() {
1034 #if DEBUG
1035  if (IsSmi()) return;
1036  DCHECK(IsHeapObject());
1037  if (!(IsString() || IsSymbol() || IsJSReceiver() || IsHeapNumber() ||
1038  IsBigInt() || IsUndefined() || IsTrue() || IsFalse() || IsNull())) {
1039  FATAL("API call returned invalid object");
1040  }
1041 #endif // DEBUG
1042 }
1043 
1044 int RegExpMatchInfo::NumberOfCaptureRegisters() {
1045  DCHECK_GE(length(), kLastMatchOverhead);
1046  Object* obj = get(kNumberOfCapturesIndex);
1047  return Smi::ToInt(obj);
1048 }
1049 
1050 void RegExpMatchInfo::SetNumberOfCaptureRegisters(int value) {
1051  DCHECK_GE(length(), kLastMatchOverhead);
1052  set(kNumberOfCapturesIndex, Smi::FromInt(value));
1053 }
1054 
1055 String RegExpMatchInfo::LastSubject() {
1056  DCHECK_GE(length(), kLastMatchOverhead);
1057  return String::cast(get(kLastSubjectIndex));
1058 }
1059 
1060 void RegExpMatchInfo::SetLastSubject(String value) {
1061  DCHECK_GE(length(), kLastMatchOverhead);
1062  set(kLastSubjectIndex, value);
1063 }
1064 
1065 Object* RegExpMatchInfo::LastInput() {
1066  DCHECK_GE(length(), kLastMatchOverhead);
1067  return get(kLastInputIndex);
1068 }
1069 
1070 void RegExpMatchInfo::SetLastInput(Object* value) {
1071  DCHECK_GE(length(), kLastMatchOverhead);
1072  set(kLastInputIndex, value);
1073 }
1074 
1075 int RegExpMatchInfo::Capture(int i) {
1076  DCHECK_LT(i, NumberOfCaptureRegisters());
1077  Object* obj = get(kFirstCaptureIndex + i);
1078  return Smi::ToInt(obj);
1079 }
1080 
1081 void RegExpMatchInfo::SetCapture(int i, int value) {
1082  DCHECK_LT(i, NumberOfCaptureRegisters());
1083  set(kFirstCaptureIndex + i, Smi::FromInt(value));
1084 }
1085 
1086 WriteBarrierMode HeapObject::GetWriteBarrierMode(
1087  const DisallowHeapAllocation& promise) {
1088  Heap* heap = Heap::FromWritableHeapObject(this);
1089  if (heap->incremental_marking()->IsMarking()) return UPDATE_WRITE_BARRIER;
1090  if (Heap::InNewSpace(this)) return SKIP_WRITE_BARRIER;
1091  return UPDATE_WRITE_BARRIER;
1092 }
1093 
1094 AllocationAlignment HeapObject::RequiredAlignment(Map map) {
1095 #ifdef V8_HOST_ARCH_32_BIT
1096  int instance_type = map->instance_type();
1097  if (instance_type == FIXED_FLOAT64_ARRAY_TYPE ||
1098  instance_type == FIXED_DOUBLE_ARRAY_TYPE) {
1099  return kDoubleAligned;
1100  }
1101  if (instance_type == HEAP_NUMBER_TYPE) return kDoubleUnaligned;
1102 #endif // V8_HOST_ARCH_32_BIT
1103  return kWordAligned;
1104 }
1105 
1106 bool HeapObject::NeedsRehashing() const {
1107  switch (map()->instance_type()) {
1108  case DESCRIPTOR_ARRAY_TYPE:
1109  return DescriptorArray::cast(this)->number_of_descriptors() > 1;
1110  case TRANSITION_ARRAY_TYPE:
1111  return TransitionArray::cast(this)->number_of_entries() > 1;
1112  case ORDERED_HASH_MAP_TYPE:
1113  return OrderedHashMap::cast(this)->NumberOfElements() > 0;
1114  case ORDERED_HASH_SET_TYPE:
1115  return OrderedHashSet::cast(this)->NumberOfElements() > 0;
1116  case NAME_DICTIONARY_TYPE:
1117  case GLOBAL_DICTIONARY_TYPE:
1118  case NUMBER_DICTIONARY_TYPE:
1119  case SIMPLE_NUMBER_DICTIONARY_TYPE:
1120  case STRING_TABLE_TYPE:
1121  case HASH_TABLE_TYPE:
1122  case SMALL_ORDERED_HASH_MAP_TYPE:
1123  case SMALL_ORDERED_HASH_SET_TYPE:
1124  case SMALL_ORDERED_NAME_DICTIONARY_TYPE:
1125  return true;
1126  default:
1127  return false;
1128  }
1129 }
1130 
1131 Address HeapObject::GetFieldAddress(int field_offset) const {
1132  return FIELD_ADDR(this, field_offset);
1133 }
1134 
1135 ACCESSORS2(EnumCache, keys, FixedArray, kKeysOffset)
1136 ACCESSORS2(EnumCache, indices, FixedArray, kIndicesOffset)
1137 
1138 ACCESSORS(DescriptorArray, enum_cache, EnumCache, kEnumCacheOffset)
1139 RELAXED_INT16_ACCESSORS(DescriptorArray, number_of_all_descriptors,
1140  kNumberOfAllDescriptorsOffset)
1141 RELAXED_INT16_ACCESSORS(DescriptorArray, number_of_descriptors,
1142  kNumberOfDescriptorsOffset)
1143 RELAXED_INT16_ACCESSORS(DescriptorArray, number_of_marked_descriptors,
1144  kNumberOfMarkedDescriptorsOffset)
1145 RELAXED_INT16_ACCESSORS(DescriptorArray, filler16bits, kFiller16BitsOffset)
1146 
1147 inline int16_t DescriptorArray::number_of_slack_descriptors() const {
1148  return number_of_all_descriptors() - number_of_descriptors();
1149 }
1150 
1151 inline int DescriptorArray::number_of_entries() const {
1152  return number_of_descriptors();
1153 }
1154 
1155 void DescriptorArray::CopyEnumCacheFrom(DescriptorArray* array) {
1156  set_enum_cache(array->enum_cache());
1157 }
1158 
1159 // Perform a binary search in a fixed array.
1160 template <SearchMode search_mode, typename T>
1161 int BinarySearch(T* array, Name name, int valid_entries,
1162  int* out_insertion_index) {
1163  DCHECK(search_mode == ALL_ENTRIES || out_insertion_index == nullptr);
1164  int low = 0;
1165  int high = array->number_of_entries() - 1;
1166  uint32_t hash = name->hash_field();
1167  int limit = high;
1168 
1169  DCHECK(low <= high);
1170 
1171  while (low != high) {
1172  int mid = low + (high - low) / 2;
1173  Name mid_name = array->GetSortedKey(mid);
1174  uint32_t mid_hash = mid_name->hash_field();
1175 
1176  if (mid_hash >= hash) {
1177  high = mid;
1178  } else {
1179  low = mid + 1;
1180  }
1181  }
1182 
1183  for (; low <= limit; ++low) {
1184  int sort_index = array->GetSortedKeyIndex(low);
1185  Name entry = array->GetKey(sort_index);
1186  uint32_t current_hash = entry->hash_field();
1187  if (current_hash != hash) {
1188  if (search_mode == ALL_ENTRIES && out_insertion_index != nullptr) {
1189  *out_insertion_index = sort_index + (current_hash > hash ? 0 : 1);
1190  }
1191  return T::kNotFound;
1192  }
1193  if (entry == name) {
1194  if (search_mode == ALL_ENTRIES || sort_index < valid_entries) {
1195  return sort_index;
1196  }
1197  return T::kNotFound;
1198  }
1199  }
1200 
1201  if (search_mode == ALL_ENTRIES && out_insertion_index != nullptr) {
1202  *out_insertion_index = limit + 1;
1203  }
1204  return T::kNotFound;
1205 }
1206 
1207 // Perform a linear search in this fixed array. len is the number of entry
1208 // indices that are valid.
1209 template <SearchMode search_mode, typename T>
1210 int LinearSearch(T* array, Name name, int valid_entries,
1211  int* out_insertion_index) {
1212  if (search_mode == ALL_ENTRIES && out_insertion_index != nullptr) {
1213  uint32_t hash = name->hash_field();
1214  int len = array->number_of_entries();
1215  for (int number = 0; number < len; number++) {
1216  int sorted_index = array->GetSortedKeyIndex(number);
1217  Name entry = array->GetKey(sorted_index);
1218  uint32_t current_hash = entry->hash_field();
1219  if (current_hash > hash) {
1220  *out_insertion_index = sorted_index;
1221  return T::kNotFound;
1222  }
1223  if (entry == name) return sorted_index;
1224  }
1225  *out_insertion_index = len;
1226  return T::kNotFound;
1227  } else {
1228  DCHECK_LE(valid_entries, array->number_of_entries());
1229  DCHECK_NULL(out_insertion_index); // Not supported here.
1230  for (int number = 0; number < valid_entries; number++) {
1231  if (array->GetKey(number) == name) return number;
1232  }
1233  return T::kNotFound;
1234  }
1235 }
1236 
1237 template <SearchMode search_mode, typename T>
1238 int Search(T* array, Name name, int valid_entries, int* out_insertion_index) {
1239  SLOW_DCHECK(array->IsSortedNoDuplicates());
1240 
1241  if (valid_entries == 0) {
1242  if (search_mode == ALL_ENTRIES && out_insertion_index != nullptr) {
1243  *out_insertion_index = 0;
1244  }
1245  return T::kNotFound;
1246  }
1247 
1248  // Fast case: do linear search for small arrays.
1249  const int kMaxElementsForLinearSearch = 8;
1250  if (valid_entries <= kMaxElementsForLinearSearch) {
1251  return LinearSearch<search_mode>(array, name, valid_entries,
1252  out_insertion_index);
1253  }
1254 
1255  // Slow case: perform binary search.
1256  return BinarySearch<search_mode>(array, name, valid_entries,
1257  out_insertion_index);
1258 }
1259 
1260 int DescriptorArray::Search(Name name, int valid_descriptors) {
1261  DCHECK(name->IsUniqueName());
1262  return internal::Search<VALID_ENTRIES>(this, name, valid_descriptors,
1263  nullptr);
1264 }
1265 
1266 int DescriptorArray::Search(Name name, Map map) {
1267  DCHECK(name->IsUniqueName());
1268  int number_of_own_descriptors = map->NumberOfOwnDescriptors();
1269  if (number_of_own_descriptors == 0) return kNotFound;
1270  return Search(name, number_of_own_descriptors);
1271 }
1272 
1273 int DescriptorArray::SearchWithCache(Isolate* isolate, Name name, Map map) {
1274  DCHECK(name->IsUniqueName());
1275  int number_of_own_descriptors = map->NumberOfOwnDescriptors();
1276  if (number_of_own_descriptors == 0) return kNotFound;
1277 
1278  DescriptorLookupCache* cache = isolate->descriptor_lookup_cache();
1279  int number = cache->Lookup(map, name);
1280 
1281  if (number == DescriptorLookupCache::kAbsent) {
1282  number = Search(name, number_of_own_descriptors);
1283  cache->Update(map, name, number);
1284  }
1285 
1286  return number;
1287 }
1288 
1289 ObjectSlot DescriptorArray::GetFirstPointerSlot() {
1290  return ObjectSlot(
1291  HeapObject::RawField(this, DescriptorArray::kPointersStartOffset));
1292 }
1293 
1294 ObjectSlot DescriptorArray::GetDescriptorSlot(int descriptor) {
1295  // Allow descriptor == number_of_all_descriptors() for computing the slot
1296  // address that comes after the last descriptor (for iterating).
1297  DCHECK_LE(descriptor, number_of_all_descriptors());
1298  return HeapObject::RawField(this, OffsetOfDescriptorAt(descriptor));
1299 }
1300 
1301 ObjectSlot DescriptorArray::GetKeySlot(int descriptor) {
1302  DCHECK_LE(descriptor, number_of_all_descriptors());
1303  ObjectSlot slot = GetDescriptorSlot(descriptor) + kEntryKeyIndex;
1304  DCHECK((*slot)->IsObject());
1305  return slot;
1306 }
1307 
1308 Name DescriptorArray::GetKey(int descriptor_number) {
1309  DCHECK(descriptor_number < number_of_descriptors());
1310  return Name::cast(
1311  get(ToKeyIndex(descriptor_number))->GetHeapObjectAssumeStrong());
1312 }
1313 
1314 int DescriptorArray::GetSortedKeyIndex(int descriptor_number) {
1315  return GetDetails(descriptor_number).pointer();
1316 }
1317 
1318 Name DescriptorArray::GetSortedKey(int descriptor_number) {
1319  return GetKey(GetSortedKeyIndex(descriptor_number));
1320 }
1321 
1322 void DescriptorArray::SetSortedKey(int descriptor_index, int pointer) {
1323  PropertyDetails details = GetDetails(descriptor_index);
1324  set(ToDetailsIndex(descriptor_index),
1325  MaybeObject::FromObject(details.set_pointer(pointer).AsSmi()));
1326 }
1327 
1328 MaybeObjectSlot DescriptorArray::GetValueSlot(int descriptor) {
1329  DCHECK_LT(descriptor, number_of_descriptors());
1330  return MaybeObjectSlot(GetDescriptorSlot(descriptor) + kEntryValueIndex);
1331 }
1332 
1333 Object* DescriptorArray::GetStrongValue(int descriptor_number) {
1334  DCHECK(descriptor_number < number_of_descriptors());
1335  return get(ToValueIndex(descriptor_number))->cast<Object>();
1336 }
1337 
1338 void DescriptorArray::SetValue(int descriptor_index, Object* value) {
1339  set(ToValueIndex(descriptor_index), MaybeObject::FromObject(value));
1340 }
1341 
1342 MaybeObject DescriptorArray::GetValue(int descriptor_number) {
1343  DCHECK_LT(descriptor_number, number_of_descriptors());
1344  return get(ToValueIndex(descriptor_number));
1345 }
1346 
1347 PropertyDetails DescriptorArray::GetDetails(int descriptor_number) {
1348  DCHECK(descriptor_number < number_of_descriptors());
1349  MaybeObject details = get(ToDetailsIndex(descriptor_number));
1350  return PropertyDetails(details->ToSmi());
1351 }
1352 
1353 int DescriptorArray::GetFieldIndex(int descriptor_number) {
1354  DCHECK_EQ(GetDetails(descriptor_number).location(), kField);
1355  return GetDetails(descriptor_number).field_index();
1356 }
1357 
1358 FieldType DescriptorArray::GetFieldType(int descriptor_number) {
1359  DCHECK_EQ(GetDetails(descriptor_number).location(), kField);
1360  MaybeObject wrapped_type = GetValue(descriptor_number);
1361  return Map::UnwrapFieldType(wrapped_type);
1362 }
1363 
1364 void DescriptorArray::Set(int descriptor_number, Name key, MaybeObject value,
1365  PropertyDetails details) {
1366  // Range check.
1367  DCHECK(descriptor_number < number_of_descriptors());
1368  set(ToKeyIndex(descriptor_number), MaybeObject::FromObject(key));
1369  set(ToValueIndex(descriptor_number), value);
1370  set(ToDetailsIndex(descriptor_number),
1371  MaybeObject::FromObject(details.AsSmi()));
1372 }
1373 
1374 void DescriptorArray::Set(int descriptor_number, Descriptor* desc) {
1375  Name key = *desc->GetKey();
1376  MaybeObject value = *desc->GetValue();
1377  Set(descriptor_number, key, value, desc->GetDetails());
1378 }
1379 
1380 
1381 void DescriptorArray::Append(Descriptor* desc) {
1382  DisallowHeapAllocation no_gc;
1383  int descriptor_number = number_of_descriptors();
1384  DCHECK_LE(descriptor_number + 1, number_of_all_descriptors());
1385  set_number_of_descriptors(descriptor_number + 1);
1386  Set(descriptor_number, desc);
1387 
1388  uint32_t hash = desc->GetKey()->Hash();
1389 
1390  int insertion;
1391 
1392  for (insertion = descriptor_number; insertion > 0; --insertion) {
1393  Name key = GetSortedKey(insertion - 1);
1394  if (key->Hash() <= hash) break;
1395  SetSortedKey(insertion, GetSortedKeyIndex(insertion - 1));
1396  }
1397 
1398  SetSortedKey(insertion, descriptor_number);
1399 }
1400 
1401 
1402 void DescriptorArray::SwapSortedKeys(int first, int second) {
1403  int first_key = GetSortedKeyIndex(first);
1404  SetSortedKey(first, GetSortedKeyIndex(second));
1405  SetSortedKey(second, first_key);
1406 }
1407 
1408 int DescriptorArray::length() const {
1409  return number_of_all_descriptors() * kEntrySize;
1410 }
1411 
1412 MaybeObject DescriptorArray::get(int index) const {
1413  DCHECK(index >= 0 && index < this->length());
1414  return RELAXED_READ_WEAK_FIELD(this, offset(index));
1415 }
1416 
1417 void DescriptorArray::set(int index, MaybeObject value) {
1418  DCHECK(index >= 0 && index < this->length());
1419  RELAXED_WRITE_WEAK_FIELD(this, offset(index), value);
1420  WEAK_WRITE_BARRIER(this, offset(index), value);
1421 }
1422 
1423 bool StringSetShape::IsMatch(String key, Object* value) {
1424  DCHECK(value->IsString());
1425  return key->Equals(String::cast(value));
1426 }
1427 
1428 uint32_t StringSetShape::Hash(Isolate* isolate, String key) {
1429  return key->Hash();
1430 }
1431 
1432 uint32_t StringSetShape::HashForObject(Isolate* isolate, Object* object) {
1433  return String::cast(object)->Hash();
1434 }
1435 
1436 StringTableKey::StringTableKey(uint32_t hash_field)
1437  : HashTableKey(hash_field >> Name::kHashShift), hash_field_(hash_field) {}
1438 
1439 void StringTableKey::set_hash_field(uint32_t hash_field) {
1440  hash_field_ = hash_field;
1441  set_hash(hash_field >> Name::kHashShift);
1442 }
1443 
1444 Handle<Object> StringTableShape::AsHandle(Isolate* isolate,
1445  StringTableKey* key) {
1446  return key->AsHandle(isolate);
1447 }
1448 
1449 uint32_t StringTableShape::HashForObject(Isolate* isolate, Object* object) {
1450  return String::cast(object)->Hash();
1451 }
1452 
1453 RootIndex StringTableShape::GetMapRootIndex() {
1454  return RootIndex::kStringTableMap;
1455 }
1456 
1457 bool NumberDictionary::requires_slow_elements() {
1458  Object* max_index_object = get(kMaxNumberKeyIndex);
1459  if (!max_index_object->IsSmi()) return false;
1460  return 0 != (Smi::ToInt(max_index_object) & kRequiresSlowElementsMask);
1461 }
1462 
1463 uint32_t NumberDictionary::max_number_key() {
1464  DCHECK(!requires_slow_elements());
1465  Object* max_index_object = get(kMaxNumberKeyIndex);
1466  if (!max_index_object->IsSmi()) return 0;
1467  uint32_t value = static_cast<uint32_t>(Smi::ToInt(max_index_object));
1468  return value >> kRequiresSlowElementsTagSize;
1469 }
1470 
1471 void NumberDictionary::set_requires_slow_elements() {
1472  set(kMaxNumberKeyIndex, Smi::FromInt(kRequiresSlowElementsMask));
1473 }
1474 
1475 DEFINE_DEOPT_ELEMENT_ACCESSORS2(TranslationByteArray, ByteArray)
1476 DEFINE_DEOPT_ELEMENT_ACCESSORS2(InlinedFunctionCount, Smi)
1477 DEFINE_DEOPT_ELEMENT_ACCESSORS2(LiteralArray, FixedArray)
1478 DEFINE_DEOPT_ELEMENT_ACCESSORS2(OsrBytecodeOffset, Smi)
1479 DEFINE_DEOPT_ELEMENT_ACCESSORS2(OsrPcOffset, Smi)
1480 DEFINE_DEOPT_ELEMENT_ACCESSORS2(OptimizationId, Smi)
1481 DEFINE_DEOPT_ELEMENT_ACCESSORS2(InliningPositions, PodArray<InliningPosition>)
1482 
1483 DEFINE_DEOPT_ENTRY_ACCESSORS(BytecodeOffsetRaw, Smi)
1484 DEFINE_DEOPT_ENTRY_ACCESSORS(TranslationIndex, Smi)
1485 DEFINE_DEOPT_ENTRY_ACCESSORS(Pc, Smi)
1486 
1487 SMI_ACCESSORS(FreeSpace, size, kSizeOffset)
1488 RELAXED_SMI_ACCESSORS(FreeSpace, size, kSizeOffset)
1489 
1490 
1491 int FreeSpace::Size() { return size(); }
1492 
1493 
1494 FreeSpace* FreeSpace::next() {
1495 #ifdef DEBUG
1496  Heap* heap = Heap::FromWritableHeapObject(this);
1497  DCHECK_IMPLIES(map() != heap->isolate()->root(RootIndex::kFreeSpaceMap),
1498  !heap->deserialization_complete() && map().is_null());
1499 #endif
1500  DCHECK_LE(kNextOffset + kPointerSize, relaxed_read_size());
1501  return reinterpret_cast<FreeSpace*>(Memory<Address>(address() + kNextOffset));
1502 }
1503 
1504 
1505 void FreeSpace::set_next(FreeSpace* next) {
1506 #ifdef DEBUG
1507  Heap* heap = Heap::FromWritableHeapObject(this);
1508  DCHECK_IMPLIES(map() != heap->isolate()->root(RootIndex::kFreeSpaceMap),
1509  !heap->deserialization_complete() && map().is_null());
1510 #endif
1511  DCHECK_LE(kNextOffset + kPointerSize, relaxed_read_size());
1512  base::Relaxed_Store(
1513  reinterpret_cast<base::AtomicWord*>(address() + kNextOffset),
1514  reinterpret_cast<base::AtomicWord>(next));
1515 }
1516 
1517 
1518 FreeSpace* FreeSpace::cast(HeapObject* o) {
1519  SLOW_DCHECK(!Heap::FromWritableHeapObject(o)->deserialization_complete() ||
1520  o->IsFreeSpace());
1521  return reinterpret_cast<FreeSpace*>(o);
1522 }
1523 
1524 int HeapObject::SizeFromMap(Map map) const {
1525  int instance_size = map->instance_size();
1526  if (instance_size != kVariableSizeSentinel) return instance_size;
1527  // Only inline the most frequent cases.
1528  InstanceType instance_type = map->instance_type();
1529  if (IsInRange(instance_type, FIRST_FIXED_ARRAY_TYPE, LAST_FIXED_ARRAY_TYPE)) {
1530  return FixedArray::SizeFor(
1531  FixedArray::unchecked_cast(this)->synchronized_length());
1532  }
1533  if (IsInRange(instance_type, FIRST_CONTEXT_TYPE, LAST_CONTEXT_TYPE)) {
1534  // Native context has fixed size.
1535  DCHECK_NE(instance_type, NATIVE_CONTEXT_TYPE);
1536  return Context::SizeFor(Context::unchecked_cast(this)->length());
1537  }
1538  if (instance_type == ONE_BYTE_STRING_TYPE ||
1539  instance_type == ONE_BYTE_INTERNALIZED_STRING_TYPE) {
1540  // Strings may get concurrently truncated, hence we have to access its
1541  // length synchronized.
1542  return SeqOneByteString::SizeFor(
1543  SeqOneByteString::unchecked_cast(this)->synchronized_length());
1544  }
1545  if (instance_type == BYTE_ARRAY_TYPE) {
1546  return ByteArray::SizeFor(
1547  ByteArray::unchecked_cast(this)->synchronized_length());
1548  }
1549  if (instance_type == BYTECODE_ARRAY_TYPE) {
1550  return BytecodeArray::SizeFor(
1551  BytecodeArray::unchecked_cast(this)->synchronized_length());
1552  }
1553  if (instance_type == FREE_SPACE_TYPE) {
1554  return reinterpret_cast<const FreeSpace*>(this)->relaxed_read_size();
1555  }
1556  if (instance_type == STRING_TYPE ||
1557  instance_type == INTERNALIZED_STRING_TYPE) {
1558  // Strings may get concurrently truncated, hence we have to access its
1559  // length synchronized.
1560  return SeqTwoByteString::SizeFor(
1561  SeqTwoByteString::unchecked_cast(this)->synchronized_length());
1562  }
1563  if (instance_type == FIXED_DOUBLE_ARRAY_TYPE) {
1564  return FixedDoubleArray::SizeFor(
1565  FixedDoubleArray::unchecked_cast(this)->synchronized_length());
1566  }
1567  if (instance_type == FEEDBACK_METADATA_TYPE) {
1568  return FeedbackMetadata::SizeFor(
1569  reinterpret_cast<const FeedbackMetadata*>(this)
1570  ->synchronized_slot_count());
1571  }
1572  if (instance_type == DESCRIPTOR_ARRAY_TYPE) {
1573  return DescriptorArray::SizeFor(
1574  reinterpret_cast<const DescriptorArray*>(this)
1575  ->number_of_all_descriptors());
1576  }
1577  if (IsInRange(instance_type, FIRST_WEAK_FIXED_ARRAY_TYPE,
1578  LAST_WEAK_FIXED_ARRAY_TYPE)) {
1579  return WeakFixedArray::SizeFor(
1580  reinterpret_cast<const WeakFixedArray*>(this)->synchronized_length());
1581  }
1582  if (instance_type == WEAK_ARRAY_LIST_TYPE) {
1583  return WeakArrayList::SizeForCapacity(
1584  reinterpret_cast<const WeakArrayList*>(this)->synchronized_capacity());
1585  }
1586  if (IsInRange(instance_type, FIRST_FIXED_TYPED_ARRAY_TYPE,
1587  LAST_FIXED_TYPED_ARRAY_TYPE)) {
1588  return FixedTypedArrayBase::unchecked_cast(this)->TypedArraySize(
1589  instance_type);
1590  }
1591  if (instance_type == SMALL_ORDERED_HASH_SET_TYPE) {
1592  return SmallOrderedHashSet::SizeFor(
1593  SmallOrderedHashSet::unchecked_cast(this)->Capacity());
1594  }
1595  if (instance_type == SMALL_ORDERED_HASH_MAP_TYPE) {
1596  return SmallOrderedHashMap::SizeFor(
1597  SmallOrderedHashMap::unchecked_cast(this)->Capacity());
1598  }
1599  if (instance_type == SMALL_ORDERED_NAME_DICTIONARY_TYPE) {
1600  return SmallOrderedNameDictionary::SizeFor(
1601  SmallOrderedNameDictionary::unchecked_cast(this)->Capacity());
1602  }
1603  if (instance_type == PROPERTY_ARRAY_TYPE) {
1604  return PropertyArray::SizeFor(
1605  PropertyArray::cast(this)->synchronized_length());
1606  }
1607  if (instance_type == FEEDBACK_VECTOR_TYPE) {
1608  return FeedbackVector::SizeFor(
1609  reinterpret_cast<const FeedbackVector*>(this)->length());
1610  }
1611  if (instance_type == BIGINT_TYPE) {
1612  return BigInt::SizeFor(reinterpret_cast<const BigInt*>(this)->length());
1613  }
1614  if (instance_type == PRE_PARSED_SCOPE_DATA_TYPE) {
1615  return PreParsedScopeData::SizeFor(
1616  reinterpret_cast<const PreParsedScopeData*>(this)->length());
1617  }
1618  if (instance_type == CODE_TYPE) {
1619  return Code::unchecked_cast(this)->CodeSize();
1620  }
1621  DCHECK_EQ(instance_type, EMBEDDER_DATA_ARRAY_TYPE);
1622  return EmbedderDataArray::SizeFor(
1623  EmbedderDataArray::unchecked_cast(this)->length());
1624 }
1625 
1626 ACCESSORS(Tuple2, value1, Object, kValue1Offset)
1627 ACCESSORS(Tuple2, value2, Object, kValue2Offset)
1628 ACCESSORS(Tuple3, value3, Object, kValue3Offset)
1629 
1630 ACCESSORS2(TemplateObjectDescription, raw_strings, FixedArray,
1631  kRawStringsOffset)
1632 ACCESSORS2(TemplateObjectDescription, cooked_strings, FixedArray,
1633  kCookedStringsOffset)
1634 
1635 ACCESSORS(AccessorPair, getter, Object, kGetterOffset)
1636 ACCESSORS(AccessorPair, setter, Object, kSetterOffset)
1637 
1638 // static
1639 bool Foreign::IsNormalized(Object* value) {
1640  if (value == Smi::kZero) return true;
1641  return Foreign::cast(value)->foreign_address() != kNullAddress;
1642 }
1643 
1644 Address Foreign::foreign_address() {
1645  return READ_UINTPTR_FIELD(this, kForeignAddressOffset);
1646 }
1647 
1648 void Foreign::set_foreign_address(Address value) {
1649  WRITE_UINTPTR_FIELD(this, kForeignAddressOffset, value);
1650 }
1651 
1652 template <class Derived>
1653 void SmallOrderedHashTable<Derived>::SetDataEntry(int entry, int relative_index,
1654  Object* value) {
1655  DCHECK_NE(kNotFound, entry);
1656  Address entry_offset = GetDataEntryOffset(entry, relative_index);
1657  RELAXED_WRITE_FIELD(this, entry_offset, value);
1658  WRITE_BARRIER(this, static_cast<int>(entry_offset), value);
1659 }
1660 
1661 // static
1662 Maybe<bool> Object::GreaterThan(Isolate* isolate, Handle<Object> x,
1663  Handle<Object> y) {
1664  Maybe<ComparisonResult> result = Compare(isolate, x, y);
1665  if (result.IsJust()) {
1666  switch (result.FromJust()) {
1667  case ComparisonResult::kGreaterThan:
1668  return Just(true);
1669  case ComparisonResult::kLessThan:
1670  case ComparisonResult::kEqual:
1671  case ComparisonResult::kUndefined:
1672  return Just(false);
1673  }
1674  }
1675  return Nothing<bool>();
1676 }
1677 
1678 
1679 // static
1680 Maybe<bool> Object::GreaterThanOrEqual(Isolate* isolate, Handle<Object> x,
1681  Handle<Object> y) {
1682  Maybe<ComparisonResult> result = Compare(isolate, x, y);
1683  if (result.IsJust()) {
1684  switch (result.FromJust()) {
1685  case ComparisonResult::kEqual:
1686  case ComparisonResult::kGreaterThan:
1687  return Just(true);
1688  case ComparisonResult::kLessThan:
1689  case ComparisonResult::kUndefined:
1690  return Just(false);
1691  }
1692  }
1693  return Nothing<bool>();
1694 }
1695 
1696 
1697 // static
1698 Maybe<bool> Object::LessThan(Isolate* isolate, Handle<Object> x,
1699  Handle<Object> y) {
1700  Maybe<ComparisonResult> result = Compare(isolate, x, y);
1701  if (result.IsJust()) {
1702  switch (result.FromJust()) {
1703  case ComparisonResult::kLessThan:
1704  return Just(true);
1705  case ComparisonResult::kEqual:
1706  case ComparisonResult::kGreaterThan:
1707  case ComparisonResult::kUndefined:
1708  return Just(false);
1709  }
1710  }
1711  return Nothing<bool>();
1712 }
1713 
1714 
1715 // static
1716 Maybe<bool> Object::LessThanOrEqual(Isolate* isolate, Handle<Object> x,
1717  Handle<Object> y) {
1718  Maybe<ComparisonResult> result = Compare(isolate, x, y);
1719  if (result.IsJust()) {
1720  switch (result.FromJust()) {
1721  case ComparisonResult::kEqual:
1722  case ComparisonResult::kLessThan:
1723  return Just(true);
1724  case ComparisonResult::kGreaterThan:
1725  case ComparisonResult::kUndefined:
1726  return Just(false);
1727  }
1728  }
1729  return Nothing<bool>();
1730 }
1731 
1732 MaybeHandle<Object> Object::GetPropertyOrElement(Isolate* isolate,
1733  Handle<Object> object,
1734  Handle<Name> name) {
1735  LookupIterator it = LookupIterator::PropertyOrElement(isolate, object, name);
1736  return GetProperty(&it);
1737 }
1738 
1739 MaybeHandle<Object> Object::SetPropertyOrElement(Isolate* isolate,
1740  Handle<Object> object,
1741  Handle<Name> name,
1742  Handle<Object> value,
1743  LanguageMode language_mode,
1744  StoreOrigin store_origin) {
1745  LookupIterator it = LookupIterator::PropertyOrElement(isolate, object, name);
1746  MAYBE_RETURN_NULL(SetProperty(&it, value, language_mode, store_origin));
1747  return value;
1748 }
1749 
1750 MaybeHandle<Object> Object::GetPropertyOrElement(Handle<Object> receiver,
1751  Handle<Name> name,
1752  Handle<JSReceiver> holder) {
1753  LookupIterator it = LookupIterator::PropertyOrElement(holder->GetIsolate(),
1754  receiver, name, holder);
1755  return GetProperty(&it);
1756 }
1757 
1758 
1759 
1760 Object* AccessorPair::get(AccessorComponent component) {
1761  return component == ACCESSOR_GETTER ? getter() : setter();
1762 }
1763 
1764 
1765 void AccessorPair::set(AccessorComponent component, Object* value) {
1766  if (component == ACCESSOR_GETTER) {
1767  set_getter(value);
1768  } else {
1769  set_setter(value);
1770  }
1771 }
1772 
1773 
1774 void AccessorPair::SetComponents(Object* getter, Object* setter) {
1775  if (!getter->IsNull()) set_getter(getter);
1776  if (!setter->IsNull()) set_setter(setter);
1777 }
1778 
1779 bool AccessorPair::Equals(AccessorPair* pair) {
1780  return (this == pair) || pair->Equals(getter(), setter());
1781 }
1782 
1783 
1784 bool AccessorPair::Equals(Object* getter_value, Object* setter_value) {
1785  return (getter() == getter_value) && (setter() == setter_value);
1786 }
1787 
1788 
1789 bool AccessorPair::ContainsAccessor() {
1790  return IsJSAccessor(getter()) || IsJSAccessor(setter());
1791 }
1792 
1793 
1794 bool AccessorPair::IsJSAccessor(Object* obj) {
1795  return obj->IsCallable() || obj->IsUndefined();
1796 }
1797 
1798 template <typename Derived, typename Shape>
1799 void Dictionary<Derived, Shape>::ClearEntry(Isolate* isolate, int entry) {
1800  Object* the_hole = this->GetReadOnlyRoots().the_hole_value();
1801  PropertyDetails details = PropertyDetails::Empty();
1802  Derived::cast(*this)->SetEntry(isolate, entry, the_hole, the_hole, details);
1803 }
1804 
1805 template <typename Derived, typename Shape>
1806 void Dictionary<Derived, Shape>::SetEntry(Isolate* isolate, int entry,
1807  Object* key, Object* value,
1808  PropertyDetails details) {
1809  DCHECK(Dictionary::kEntrySize == 2 || Dictionary::kEntrySize == 3);
1810  DCHECK(!key->IsName() || details.dictionary_index() > 0);
1811  int index = DerivedHashTable::EntryToIndex(entry);
1812  DisallowHeapAllocation no_gc;
1813  WriteBarrierMode mode = this->GetWriteBarrierMode(no_gc);
1814  this->set(index + Derived::kEntryKeyIndex, key, mode);
1815  this->set(index + Derived::kEntryValueIndex, value, mode);
1816  if (Shape::kHasDetails) DetailsAtPut(isolate, entry, details);
1817 }
1818 
1819 Object* GlobalDictionaryShape::Unwrap(Object* object) {
1820  return PropertyCell::cast(object)->name();
1821 }
1822 
1823 RootIndex GlobalDictionaryShape::GetMapRootIndex() {
1824  return RootIndex::kGlobalDictionaryMap;
1825 }
1826 
1827 Name NameDictionary::NameAt(int entry) { return Name::cast(KeyAt(entry)); }
1828 
1829 RootIndex NameDictionaryShape::GetMapRootIndex() {
1830  return RootIndex::kNameDictionaryMap;
1831 }
1832 
1833 PropertyCell* GlobalDictionary::CellAt(int entry) {
1834  DCHECK(KeyAt(entry)->IsPropertyCell());
1835  return PropertyCell::cast(KeyAt(entry));
1836 }
1837 
1838 bool GlobalDictionaryShape::IsLive(ReadOnlyRoots roots, Object* k) {
1839  DCHECK_NE(roots.the_hole_value(), k);
1840  return k != roots.undefined_value();
1841 }
1842 
1843 bool GlobalDictionaryShape::IsKey(ReadOnlyRoots roots, Object* k) {
1844  return IsLive(roots, k) && !PropertyCell::cast(k)->value()->IsTheHole(roots);
1845 }
1846 
1847 Name GlobalDictionary::NameAt(int entry) { return CellAt(entry)->name(); }
1848 Object* GlobalDictionary::ValueAt(int entry) { return CellAt(entry)->value(); }
1849 
1850 void GlobalDictionary::SetEntry(Isolate* isolate, int entry, Object* key,
1851  Object* value, PropertyDetails details) {
1852  DCHECK_EQ(key, PropertyCell::cast(value)->name());
1853  set(EntryToIndex(entry) + kEntryKeyIndex, value);
1854  DetailsAtPut(isolate, entry, details);
1855 }
1856 
1857 void GlobalDictionary::ValueAtPut(int entry, Object* value) {
1858  set(EntryToIndex(entry), value);
1859 }
1860 
1861 bool NumberDictionaryBaseShape::IsMatch(uint32_t key, Object* other) {
1862  DCHECK(other->IsNumber());
1863  return key == static_cast<uint32_t>(other->Number());
1864 }
1865 
1866 uint32_t NumberDictionaryBaseShape::Hash(Isolate* isolate, uint32_t key) {
1867  return ComputeSeededHash(key, isolate->heap()->HashSeed());
1868 }
1869 
1870 uint32_t NumberDictionaryBaseShape::HashForObject(Isolate* isolate,
1871  Object* other) {
1872  DCHECK(other->IsNumber());
1873  return ComputeSeededHash(static_cast<uint32_t>(other->Number()),
1874  isolate->heap()->HashSeed());
1875 }
1876 
1877 Handle<Object> NumberDictionaryBaseShape::AsHandle(Isolate* isolate,
1878  uint32_t key) {
1879  return isolate->factory()->NewNumberFromUint(key);
1880 }
1881 
1882 RootIndex NumberDictionaryShape::GetMapRootIndex() {
1883  return RootIndex::kNumberDictionaryMap;
1884 }
1885 
1886 RootIndex SimpleNumberDictionaryShape::GetMapRootIndex() {
1887  return RootIndex::kSimpleNumberDictionaryMap;
1888 }
1889 
1890 bool NameDictionaryShape::IsMatch(Handle<Name> key, Object* other) {
1891  DCHECK(other->IsTheHole() || Name::cast(other)->IsUniqueName());
1892  DCHECK(key->IsUniqueName());
1893  return *key == other;
1894 }
1895 
1896 uint32_t NameDictionaryShape::Hash(Isolate* isolate, Handle<Name> key) {
1897  return key->Hash();
1898 }
1899 
1900 uint32_t NameDictionaryShape::HashForObject(Isolate* isolate, Object* other) {
1901  return Name::cast(other)->Hash();
1902 }
1903 
1904 bool GlobalDictionaryShape::IsMatch(Handle<Name> key, Object* other) {
1905  DCHECK(PropertyCell::cast(other)->name()->IsUniqueName());
1906  return *key == PropertyCell::cast(other)->name();
1907 }
1908 
1909 uint32_t GlobalDictionaryShape::HashForObject(Isolate* isolate, Object* other) {
1910  return PropertyCell::cast(other)->name()->Hash();
1911 }
1912 
1913 Handle<Object> NameDictionaryShape::AsHandle(Isolate* isolate,
1914  Handle<Name> key) {
1915  DCHECK(key->IsUniqueName());
1916  return key;
1917 }
1918 
1919 template <typename Dictionary>
1920 PropertyDetails GlobalDictionaryShape::DetailsAt(Dictionary dict, int entry) {
1921  DCHECK_LE(0, entry); // Not found is -1, which is not caught by get().
1922  return dict->CellAt(entry)->property_details();
1923 }
1924 
1925 template <typename Dictionary>
1926 void GlobalDictionaryShape::DetailsAtPut(Isolate* isolate, Dictionary dict,
1927  int entry, PropertyDetails value) {
1928  DCHECK_LE(0, entry); // Not found is -1, which is not caught by get().
1929  PropertyCell* cell = dict->CellAt(entry);
1930  if (cell->property_details().IsReadOnly() != value.IsReadOnly()) {
1931  cell->dependent_code()->DeoptimizeDependentCodeGroup(
1932  isolate, DependentCode::kPropertyCellChangedGroup);
1933  }
1934  cell->set_property_details(value);
1935 }
1936 
1937 bool ObjectHashTableShape::IsMatch(Handle<Object> key, Object* other) {
1938  return key->SameValue(other);
1939 }
1940 
1941 uint32_t ObjectHashTableShape::Hash(Isolate* isolate, Handle<Object> key) {
1942  return Smi::ToInt(key->GetHash());
1943 }
1944 
1945 uint32_t ObjectHashTableShape::HashForObject(Isolate* isolate, Object* other) {
1946  return Smi::ToInt(other->GetHash());
1947 }
1948 
1949 // static
1950 Object* Object::GetSimpleHash(Object* object) {
1951  DisallowHeapAllocation no_gc;
1952  if (object->IsSmi()) {
1953  uint32_t hash = ComputeUnseededHash(Smi::ToInt(object));
1954  return Smi::FromInt(hash & Smi::kMaxValue);
1955  }
1956  if (object->IsHeapNumber()) {
1957  double num = HeapNumber::cast(object)->value();
1958  if (std::isnan(num)) return Smi::FromInt(Smi::kMaxValue);
1959  // Use ComputeUnseededHash for all values in Signed32 range, including -0,
1960  // which is considered equal to 0 because collections use SameValueZero.
1961  uint32_t hash;
1962  // Check range before conversion to avoid undefined behavior.
1963  if (num >= kMinInt && num <= kMaxInt && FastI2D(FastD2I(num)) == num) {
1964  hash = ComputeUnseededHash(FastD2I(num));
1965  } else {
1966  hash = ComputeLongHash(double_to_uint64(num));
1967  }
1968  return Smi::FromInt(hash & Smi::kMaxValue);
1969  }
1970  if (object->IsName()) {
1971  uint32_t hash = Name::cast(object)->Hash();
1972  return Smi::FromInt(hash);
1973  }
1974  if (object->IsOddball()) {
1975  uint32_t hash = Oddball::cast(object)->to_string()->Hash();
1976  return Smi::FromInt(hash);
1977  }
1978  if (object->IsBigInt()) {
1979  uint32_t hash = BigInt::cast(object)->Hash();
1980  return Smi::FromInt(hash & Smi::kMaxValue);
1981  }
1982  DCHECK(object->IsJSReceiver());
1983  return object;
1984 }
1985 
1986 Object* Object::GetHash() {
1987  DisallowHeapAllocation no_gc;
1988  Object* hash = GetSimpleHash(this);
1989  if (hash->IsSmi()) return hash;
1990 
1991  DCHECK(IsJSReceiver());
1992  JSReceiver* receiver = JSReceiver::cast(this);
1993  return receiver->GetIdentityHash();
1994 }
1995 
1996 Handle<Object> ObjectHashTableShape::AsHandle(Handle<Object> key) {
1997  return key;
1998 }
1999 
2000 Relocatable::Relocatable(Isolate* isolate) {
2001  isolate_ = isolate;
2002  prev_ = isolate->relocatable_top();
2003  isolate->set_relocatable_top(this);
2004 }
2005 
2006 
2007 Relocatable::~Relocatable() {
2008  DCHECK_EQ(isolate_->relocatable_top(), this);
2009  isolate_->set_relocatable_top(prev_);
2010 }
2011 
2012 
2013 template<class Derived, class TableType>
2014 Object* OrderedHashTableIterator<Derived, TableType>::CurrentKey() {
2015  TableType table = TableType::cast(this->table());
2016  int index = Smi::ToInt(this->index());
2017  Object* key = table->KeyAt(index);
2018  DCHECK(!key->IsTheHole());
2019  return key;
2020 }
2021 
2022 // Predictably converts HeapObject* or Address to uint32 by calculating
2023 // offset of the address in respective MemoryChunk.
2024 static inline uint32_t ObjectAddressForHashing(void* object) {
2025  uint32_t value = static_cast<uint32_t>(reinterpret_cast<uintptr_t>(object));
2026  return value & MemoryChunk::kAlignmentMask;
2027 }
2028 
2029 static inline Handle<Object> MakeEntryPair(Isolate* isolate, uint32_t index,
2030  Handle<Object> value) {
2031  Handle<Object> key = isolate->factory()->Uint32ToString(index);
2032  Handle<FixedArray> entry_storage =
2033  isolate->factory()->NewUninitializedFixedArray(2);
2034  {
2035  entry_storage->set(0, *key, SKIP_WRITE_BARRIER);
2036  entry_storage->set(1, *value, SKIP_WRITE_BARRIER);
2037  }
2038  return isolate->factory()->NewJSArrayWithElements(entry_storage,
2039  PACKED_ELEMENTS, 2);
2040 }
2041 
2042 static inline Handle<Object> MakeEntryPair(Isolate* isolate, Handle<Object> key,
2043  Handle<Object> value) {
2044  Handle<FixedArray> entry_storage =
2045  isolate->factory()->NewUninitializedFixedArray(2);
2046  {
2047  entry_storage->set(0, *key, SKIP_WRITE_BARRIER);
2048  entry_storage->set(1, *value, SKIP_WRITE_BARRIER);
2049  }
2050  return isolate->factory()->NewJSArrayWithElements(entry_storage,
2051  PACKED_ELEMENTS, 2);
2052 }
2053 
2054 
2055 bool ScopeInfo::IsAsmModule() const { return AsmModuleField::decode(Flags()); }
2056 
2057 bool ScopeInfo::HasSimpleParameters() const {
2058  return HasSimpleParametersField::decode(Flags());
2059 }
2060 
2061 #define FIELD_ACCESSORS(name) \
2062  void ScopeInfo::Set##name(int value) { set(k##name, Smi::FromInt(value)); } \
2063  int ScopeInfo::name() const { \
2064  if (length() > 0) { \
2065  return Smi::ToInt(get(k##name)); \
2066  } else { \
2067  return 0; \
2068  } \
2069  }
2070 FOR_EACH_SCOPE_INFO_NUMERIC_FIELD(FIELD_ACCESSORS)
2071 #undef FIELD_ACCESSORS
2072 
2073 FreshlyAllocatedBigInt* FreshlyAllocatedBigInt::cast(Object* object) {
2074  SLOW_DCHECK(object->IsBigInt());
2075  return reinterpret_cast<FreshlyAllocatedBigInt*>(object);
2076 }
2077 
2078 } // namespace internal
2079 } // namespace v8
2080 
2081 #include "src/objects/object-macros-undef.h"
2082 
2083 #endif // V8_OBJECTS_INL_H_
bool IsNumber() const
Definition: api.cc:3389
Definition: libplatform.h:13
PropertyFilter
Definition: v8.h:3185