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/atomicops.h"
18 #include "src/base/bits.h"
19 #include "src/base/tsan.h"
20 #include "src/builtins/builtins.h"
21 #include "src/contexts-inl.h"
22 #include "src/conversions-inl.h"
23 #include "src/feedback-vector-inl.h"
24 #include "src/field-index-inl.h"
25 #include "src/handles-inl.h"
26 #include "src/heap/factory.h"
27 #include "src/heap/heap-inl.h"
28 #include "src/isolate-inl.h"
29 #include "src/keys.h"
30 #include "src/layout-descriptor-inl.h"
31 #include "src/lookup-cache-inl.h"
32 #include "src/lookup.h"
33 #include "src/objects/arguments-inl.h"
34 #include "src/objects/bigint.h"
35 #include "src/objects/data-handler-inl.h"
36 #include "src/objects/descriptor-array.h"
37 #include "src/objects/fixed-array-inl.h"
38 #include "src/objects/js-array-inl.h"
39 #include "src/objects/js-collection-inl.h"
40 #include "src/objects/js-promise-inl.h"
41 #include "src/objects/js-regexp-inl.h"
42 #include "src/objects/js-regexp-string-iterator-inl.h"
43 #include "src/objects/literal-objects.h"
44 #include "src/objects/map-inl.h"
45 #include "src/objects/module-inl.h"
46 #include "src/objects/name-inl.h"
47 #include "src/objects/regexp-match-info.h"
48 #include "src/objects/scope-info.h"
49 #include "src/objects/template-objects.h"
50 #include "src/objects/templates.h"
51 #include "src/property-details.h"
52 #include "src/property.h"
53 #include "src/prototype.h"
54 #include "src/transitions-inl.h"
55 #include "src/v8memory.h"
56 
57 // Has to be the last include (doesn't have include guards):
58 #include "src/objects/object-macros.h"
59 
60 namespace v8 {
61 namespace internal {
62 
PropertyDetails(Smi * smi)63 PropertyDetails::PropertyDetails(Smi* smi) {
64   value_ = smi->value();
65 }
66 
67 
AsSmi()68 Smi* PropertyDetails::AsSmi() const {
69   // Ensure the upper 2 bits have the same value by sign extending it. This is
70   // necessary to be able to use the 31st bit of the property details.
71   int value = value_ << 1;
72   return Smi::FromInt(value >> 1);
73 }
74 
75 
field_width_in_words()76 int PropertyDetails::field_width_in_words() const {
77   DCHECK_EQ(location(), kField);
78   if (!FLAG_unbox_double_fields) return 1;
79   if (kDoubleSize == kPointerSize) return 1;
80   return representation().IsDouble() ? kDoubleSize / kPointerSize : 1;
81 }
82 
TYPE_CHECKER(BigInt,BIGINT_TYPE)83 TYPE_CHECKER(BigInt, BIGINT_TYPE)
84 TYPE_CHECKER(BoilerplateDescription, BOILERPLATE_DESCRIPTION_TYPE)
85 TYPE_CHECKER(BreakPoint, TUPLE2_TYPE)
86 TYPE_CHECKER(BreakPointInfo, TUPLE2_TYPE)
87 TYPE_CHECKER(Cell, CELL_TYPE)
88 TYPE_CHECKER(ConstantElementsPair, TUPLE2_TYPE)
89 TYPE_CHECKER(CoverageInfo, FIXED_ARRAY_TYPE)
90 TYPE_CHECKER(DescriptorArray, DESCRIPTOR_ARRAY_TYPE)
91 TYPE_CHECKER(FeedbackCell, FEEDBACK_CELL_TYPE)
92 TYPE_CHECKER(FeedbackMetadata, FEEDBACK_METADATA_TYPE)
93 TYPE_CHECKER(FeedbackVector, FEEDBACK_VECTOR_TYPE)
94 TYPE_CHECKER(Foreign, FOREIGN_TYPE)
95 TYPE_CHECKER(FreeSpace, FREE_SPACE_TYPE)
96 TYPE_CHECKER(HashTable, HASH_TABLE_TYPE)
97 TYPE_CHECKER(HeapNumber, HEAP_NUMBER_TYPE)
98 TYPE_CHECKER(JSArrayIterator, JS_ARRAY_ITERATOR_TYPE)
99 TYPE_CHECKER(JSAsyncFromSyncIterator, JS_ASYNC_FROM_SYNC_ITERATOR_TYPE)
100 TYPE_CHECKER(JSAsyncGeneratorObject, JS_ASYNC_GENERATOR_OBJECT_TYPE)
101 TYPE_CHECKER(JSBoundFunction, JS_BOUND_FUNCTION_TYPE)
102 TYPE_CHECKER(JSContextExtensionObject, JS_CONTEXT_EXTENSION_OBJECT_TYPE)
103 TYPE_CHECKER(JSDataView, JS_DATA_VIEW_TYPE)
104 TYPE_CHECKER(JSDate, JS_DATE_TYPE)
105 TYPE_CHECKER(JSError, JS_ERROR_TYPE)
106 TYPE_CHECKER(JSFunction, JS_FUNCTION_TYPE)
107 TYPE_CHECKER(JSGlobalObject, JS_GLOBAL_OBJECT_TYPE)
108 #ifdef V8_INTL_SUPPORT
109 TYPE_CHECKER(JSLocale, JS_INTL_LOCALE_TYPE)
110 #endif  // V8_INTL_SUPPORT
111 TYPE_CHECKER(JSMessageObject, JS_MESSAGE_OBJECT_TYPE)
112 TYPE_CHECKER(JSStringIterator, JS_STRING_ITERATOR_TYPE)
113 TYPE_CHECKER(JSValue, JS_VALUE_TYPE)
114 TYPE_CHECKER(MutableHeapNumber, MUTABLE_HEAP_NUMBER_TYPE)
115 TYPE_CHECKER(Oddball, ODDBALL_TYPE)
116 TYPE_CHECKER(PreParsedScopeData, TUPLE2_TYPE)
117 TYPE_CHECKER(PropertyArray, PROPERTY_ARRAY_TYPE)
118 TYPE_CHECKER(PropertyCell, PROPERTY_CELL_TYPE)
119 TYPE_CHECKER(PropertyDescriptorObject, FIXED_ARRAY_TYPE)
120 TYPE_CHECKER(ScopeInfo, SCOPE_INFO_TYPE)
121 TYPE_CHECKER(SmallOrderedHashMap, SMALL_ORDERED_HASH_MAP_TYPE)
122 TYPE_CHECKER(SmallOrderedHashSet, SMALL_ORDERED_HASH_SET_TYPE)
123 TYPE_CHECKER(SourcePositionTableWithFrameCache, TUPLE2_TYPE)
124 TYPE_CHECKER(TemplateObjectDescription, TUPLE2_TYPE)
125 TYPE_CHECKER(TransitionArray, TRANSITION_ARRAY_TYPE)
126 TYPE_CHECKER(WasmGlobalObject, WASM_GLOBAL_TYPE)
127 TYPE_CHECKER(WasmInstanceObject, WASM_INSTANCE_TYPE)
128 TYPE_CHECKER(WasmMemoryObject, WASM_MEMORY_TYPE)
129 TYPE_CHECKER(WasmModuleObject, WASM_MODULE_TYPE)
130 TYPE_CHECKER(WasmTableObject, WASM_TABLE_TYPE)
131 TYPE_CHECKER(WeakCell, WEAK_CELL_TYPE)
132 
133 #define TYPED_ARRAY_TYPE_CHECKER(Type, type, TYPE, ctype, size) \
134   TYPE_CHECKER(Fixed##Type##Array, FIXED_##TYPE##_ARRAY_TYPE)
135 TYPED_ARRAYS(TYPED_ARRAY_TYPE_CHECKER)
136 #undef TYPED_ARRAY_TYPE_CHECKER
137 
138 
139 bool HeapObject::IsFixedArrayBase() const {
140   return IsFixedArray() || IsFixedDoubleArray() || IsFixedTypedArrayBase();
141 }
142 
IsFixedArray()143 bool HeapObject::IsFixedArray() const {
144   InstanceType instance_type = map()->instance_type();
145   return instance_type >= FIRST_FIXED_ARRAY_TYPE &&
146          instance_type <= LAST_FIXED_ARRAY_TYPE;
147 }
148 
IsWeakFixedArray()149 bool HeapObject::IsWeakFixedArray() const {
150   InstanceType instance_type = map()->instance_type();
151   return instance_type >= FIRST_WEAK_FIXED_ARRAY_TYPE &&
152          instance_type <= LAST_WEAK_FIXED_ARRAY_TYPE;
153 }
154 
IsSloppyArgumentsElements()155 bool HeapObject::IsSloppyArgumentsElements() const {
156   return IsFixedArrayExact();
157 }
158 
IsJSSloppyArgumentsObject()159 bool HeapObject::IsJSSloppyArgumentsObject() const {
160   return IsJSArgumentsObject();
161 }
162 
IsJSGeneratorObject()163 bool HeapObject::IsJSGeneratorObject() const {
164   return map()->instance_type() == JS_GENERATOR_OBJECT_TYPE ||
165          IsJSAsyncGeneratorObject();
166 }
167 
IsClassBoilerplate()168 bool HeapObject::IsClassBoilerplate() const { return IsFixedArrayExact(); }
169 
IsExternal()170 bool HeapObject::IsExternal() const {
171   return map()->FindRootMap() == GetHeap()->external_map();
172 }
173 
174 #define IS_TYPE_FUNCTION_DEF(type_)                               \
175   bool Object::Is##type_() const {                                \
176     return IsHeapObject() && HeapObject::cast(this)->Is##type_(); \
177   }
178 HEAP_OBJECT_TYPE_LIST(IS_TYPE_FUNCTION_DEF)
179 #undef IS_TYPE_FUNCTION_DEF
180 
181 #define IS_TYPE_FUNCTION_DEF(Type, Value)             \
182   bool Object::Is##Type(Isolate* isolate) const {     \
183     return this == isolate->heap()->Value();          \
184   }                                                   \
185   bool HeapObject::Is##Type(Isolate* isolate) const { \
186     return this == isolate->heap()->Value();          \
187   }
ODDBALL_LIST(IS_TYPE_FUNCTION_DEF)188 ODDBALL_LIST(IS_TYPE_FUNCTION_DEF)
189 #undef IS_TYPE_FUNCTION_DEF
190 
191 bool Object::IsNullOrUndefined(Isolate* isolate) const {
192   Heap* heap = isolate->heap();
193   return this == heap->null_value() || this == heap->undefined_value();
194 }
195 
IsNullOrUndefined(Isolate * isolate)196 bool HeapObject::IsNullOrUndefined(Isolate* isolate) const {
197   Heap* heap = isolate->heap();
198   return this == heap->null_value() || this == heap->undefined_value();
199 }
200 
IsString()201 bool HeapObject::IsString() const {
202   return map()->instance_type() < FIRST_NONSTRING_TYPE;
203 }
204 
IsName()205 bool HeapObject::IsName() const {
206   return map()->instance_type() <= LAST_NAME_TYPE;
207 }
208 
IsUniqueName()209 bool HeapObject::IsUniqueName() const {
210   return IsInternalizedString() || IsSymbol();
211 }
212 
IsFunction()213 bool HeapObject::IsFunction() const {
214   STATIC_ASSERT(LAST_FUNCTION_TYPE == LAST_TYPE);
215   return map()->instance_type() >= FIRST_FUNCTION_TYPE;
216 }
217 
IsCallable()218 bool HeapObject::IsCallable() const { return map()->is_callable(); }
219 
IsConstructor()220 bool HeapObject::IsConstructor() const { return map()->is_constructor(); }
221 
IsTemplateInfo()222 bool HeapObject::IsTemplateInfo() const {
223   return IsObjectTemplateInfo() || IsFunctionTemplateInfo();
224 }
225 
IsInternalizedString()226 bool HeapObject::IsInternalizedString() const {
227   uint32_t type = map()->instance_type();
228   STATIC_ASSERT(kNotInternalizedTag != 0);
229   return (type & (kIsNotStringMask | kIsNotInternalizedMask)) ==
230       (kStringTag | kInternalizedTag);
231 }
232 
IsConsString()233 bool HeapObject::IsConsString() const {
234   if (!IsString()) return false;
235   return StringShape(String::cast(this)).IsCons();
236 }
237 
IsThinString()238 bool HeapObject::IsThinString() const {
239   if (!IsString()) return false;
240   return StringShape(String::cast(this)).IsThin();
241 }
242 
IsSlicedString()243 bool HeapObject::IsSlicedString() const {
244   if (!IsString()) return false;
245   return StringShape(String::cast(this)).IsSliced();
246 }
247 
IsSeqString()248 bool HeapObject::IsSeqString() const {
249   if (!IsString()) return false;
250   return StringShape(String::cast(this)).IsSequential();
251 }
252 
IsSeqOneByteString()253 bool HeapObject::IsSeqOneByteString() const {
254   if (!IsString()) return false;
255   return StringShape(String::cast(this)).IsSequential() &&
256          String::cast(this)->IsOneByteRepresentation();
257 }
258 
IsSeqTwoByteString()259 bool HeapObject::IsSeqTwoByteString() const {
260   if (!IsString()) return false;
261   return StringShape(String::cast(this)).IsSequential() &&
262          String::cast(this)->IsTwoByteRepresentation();
263 }
264 
IsExternalString()265 bool HeapObject::IsExternalString() const {
266   if (!IsString()) return false;
267   return StringShape(String::cast(this)).IsExternal();
268 }
269 
IsExternalOneByteString()270 bool HeapObject::IsExternalOneByteString() const {
271   if (!IsString()) return false;
272   return StringShape(String::cast(this)).IsExternal() &&
273          String::cast(this)->IsOneByteRepresentation();
274 }
275 
IsExternalTwoByteString()276 bool HeapObject::IsExternalTwoByteString() const {
277   if (!IsString()) return false;
278   return StringShape(String::cast(this)).IsExternal() &&
279          String::cast(this)->IsTwoByteRepresentation();
280 }
281 
IsNumber()282 bool Object::IsNumber() const { return IsSmi() || IsHeapNumber(); }
283 
IsNumeric()284 bool Object::IsNumeric() const { return IsNumber() || IsBigInt(); }
285 
IsFiller()286 bool HeapObject::IsFiller() const {
287   InstanceType instance_type = map()->instance_type();
288   return instance_type == FREE_SPACE_TYPE || instance_type == FILLER_TYPE;
289 }
290 
IsFixedTypedArrayBase()291 bool HeapObject::IsFixedTypedArrayBase() const {
292   InstanceType instance_type = map()->instance_type();
293   return (instance_type >= FIRST_FIXED_TYPED_ARRAY_TYPE &&
294           instance_type <= LAST_FIXED_TYPED_ARRAY_TYPE);
295 }
296 
IsJSReceiver()297 bool HeapObject::IsJSReceiver() const {
298   STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE);
299   return map()->instance_type() >= FIRST_JS_RECEIVER_TYPE;
300 }
301 
IsJSObject()302 bool HeapObject::IsJSObject() const {
303   STATIC_ASSERT(LAST_JS_OBJECT_TYPE == LAST_TYPE);
304   return map()->IsJSObjectMap();
305 }
306 
IsJSProxy()307 bool HeapObject::IsJSProxy() const { return map()->IsJSProxyMap(); }
308 
IsJSMapIterator()309 bool HeapObject::IsJSMapIterator() const {
310   InstanceType instance_type = map()->instance_type();
311   STATIC_ASSERT(JS_MAP_KEY_ITERATOR_TYPE + 1 == JS_MAP_KEY_VALUE_ITERATOR_TYPE);
312   STATIC_ASSERT(JS_MAP_KEY_VALUE_ITERATOR_TYPE + 1 ==
313                 JS_MAP_VALUE_ITERATOR_TYPE);
314   return (instance_type >= JS_MAP_KEY_ITERATOR_TYPE &&
315           instance_type <= JS_MAP_VALUE_ITERATOR_TYPE);
316 }
317 
IsJSSetIterator()318 bool HeapObject::IsJSSetIterator() const {
319   InstanceType instance_type = map()->instance_type();
320   return (instance_type == JS_SET_VALUE_ITERATOR_TYPE ||
321           instance_type == JS_SET_KEY_VALUE_ITERATOR_TYPE);
322 }
323 
IsJSWeakCollection()324 bool HeapObject::IsJSWeakCollection() const {
325   return IsJSWeakMap() || IsJSWeakSet();
326 }
327 
IsJSCollection()328 bool HeapObject::IsJSCollection() const { return IsJSMap() || IsJSSet(); }
329 
IsMicrotask()330 bool HeapObject::IsMicrotask() const {
331   InstanceType instance_type = map()->instance_type();
332   return (instance_type >= FIRST_MICROTASK_TYPE &&
333           instance_type <= LAST_MICROTASK_TYPE);
334 }
335 
IsPromiseReactionJobTask()336 bool HeapObject::IsPromiseReactionJobTask() const {
337   return IsPromiseFulfillReactionJobTask() || IsPromiseRejectReactionJobTask();
338 }
339 
IsEnumCache()340 bool HeapObject::IsEnumCache() const { return IsTuple2(); }
341 
IsFrameArray()342 bool HeapObject::IsFrameArray() const { return IsFixedArrayExact(); }
343 
IsArrayList()344 bool HeapObject::IsArrayList() const {
345   return map() == GetHeap()->array_list_map() ||
346          this == GetHeap()->empty_fixed_array();
347 }
348 
IsRegExpMatchInfo()349 bool HeapObject::IsRegExpMatchInfo() const { return IsFixedArrayExact(); }
350 
IsLayoutDescriptor()351 bool Object::IsLayoutDescriptor() const { return IsSmi() || IsByteArray(); }
352 
IsDeoptimizationData()353 bool HeapObject::IsDeoptimizationData() const {
354   // Must be a fixed array.
355   if (!IsFixedArrayExact()) return false;
356 
357   // There's no sure way to detect the difference between a fixed array and
358   // a deoptimization data array.  Since this is used for asserts we can
359   // check that the length is zero or else the fixed size plus a multiple of
360   // the entry size.
361   int length = FixedArray::cast(this)->length();
362   if (length == 0) return true;
363 
364   length -= DeoptimizationData::kFirstDeoptEntryIndex;
365   return length >= 0 && length % DeoptimizationData::kDeoptEntrySize == 0;
366 }
367 
IsHandlerTable()368 bool HeapObject::IsHandlerTable() const {
369   if (!IsFixedArrayExact()) return false;
370   // There's actually no way to see the difference between a fixed array and
371   // a handler table array.
372   return true;
373 }
374 
IsTemplateList()375 bool HeapObject::IsTemplateList() const {
376   if (!IsFixedArrayExact()) return false;
377   // There's actually no way to see the difference between a fixed array and
378   // a template list.
379   if (FixedArray::cast(this)->length() < 1) return false;
380   return true;
381 }
382 
IsDependentCode()383 bool HeapObject::IsDependentCode() const {
384   if (!IsFixedArrayExact()) return false;
385   // There's actually no way to see the difference between a fixed array and
386   // a dependent codes array.
387   return true;
388 }
389 
IsContext()390 bool HeapObject::IsContext() const {
391   Map* map = this->map();
392   Heap* heap = GetHeap();
393   return (
394       map == heap->function_context_map() || map == heap->catch_context_map() ||
395       map == heap->with_context_map() || map == heap->native_context_map() ||
396       map == heap->block_context_map() || map == heap->module_context_map() ||
397       map == heap->eval_context_map() || map == heap->script_context_map() ||
398       map == heap->debug_evaluate_context_map());
399 }
400 
IsNativeContext()401 bool HeapObject::IsNativeContext() const {
402   return map() == GetHeap()->native_context_map();
403 }
404 
IsScriptContextTable()405 bool HeapObject::IsScriptContextTable() const {
406   return map() == GetHeap()->script_context_table_map();
407 }
408 
409 template <>
410 inline bool Is<JSFunction>(Object* obj) {
411   return obj->IsJSFunction();
412 }
413 
IsAbstractCode()414 bool HeapObject::IsAbstractCode() const {
415   return IsBytecodeArray() || IsCode();
416 }
417 
IsStringWrapper()418 bool HeapObject::IsStringWrapper() const {
419   return IsJSValue() && JSValue::cast(this)->value()->IsString();
420 }
421 
IsBooleanWrapper()422 bool HeapObject::IsBooleanWrapper() const {
423   return IsJSValue() && JSValue::cast(this)->value()->IsBoolean();
424 }
425 
IsScriptWrapper()426 bool HeapObject::IsScriptWrapper() const {
427   return IsJSValue() && JSValue::cast(this)->value()->IsScript();
428 }
429 
IsNumberWrapper()430 bool HeapObject::IsNumberWrapper() const {
431   return IsJSValue() && JSValue::cast(this)->value()->IsNumber();
432 }
433 
IsBigIntWrapper()434 bool HeapObject::IsBigIntWrapper() const {
435   return IsJSValue() && JSValue::cast(this)->value()->IsBigInt();
436 }
437 
IsSymbolWrapper()438 bool HeapObject::IsSymbolWrapper() const {
439   return IsJSValue() && JSValue::cast(this)->value()->IsSymbol();
440 }
441 
IsBoolean()442 bool HeapObject::IsBoolean() const {
443   return IsOddball() &&
444          ((Oddball::cast(this)->kind() & Oddball::kNotBooleanMask) == 0);
445 }
446 
IsJSArrayBufferView()447 bool HeapObject::IsJSArrayBufferView() const {
448   return IsJSDataView() || IsJSTypedArray();
449 }
450 
IsDictionary()451 bool HeapObject::IsDictionary() const {
452   return IsHashTable() && this != GetHeap()->string_table();
453 }
454 
IsGlobalDictionary()455 bool HeapObject::IsGlobalDictionary() const {
456   return map() == GetHeap()->global_dictionary_map();
457 }
458 
IsNameDictionary()459 bool HeapObject::IsNameDictionary() const {
460   return map() == GetHeap()->name_dictionary_map();
461 }
462 
IsNumberDictionary()463 bool HeapObject::IsNumberDictionary() const {
464   return map() == GetHeap()->number_dictionary_map();
465 }
466 
IsSimpleNumberDictionary()467 bool HeapObject::IsSimpleNumberDictionary() const {
468   return map() == GetHeap()->simple_number_dictionary_map();
469 }
470 
IsStringTable()471 bool HeapObject::IsStringTable() const {
472   return map() == GetHeap()->string_table_map();
473 }
474 
IsStringSet()475 bool HeapObject::IsStringSet() const { return IsHashTable(); }
476 
IsObjectHashSet()477 bool HeapObject::IsObjectHashSet() const { return IsHashTable(); }
478 
IsNormalizedMapCache()479 bool HeapObject::IsNormalizedMapCache() const {
480   return NormalizedMapCache::IsNormalizedMapCache(this);
481 }
482 
IsCompilationCacheTable()483 bool HeapObject::IsCompilationCacheTable() const { return IsHashTable(); }
484 
IsMapCache()485 bool HeapObject::IsMapCache() const { return IsHashTable(); }
486 
IsObjectHashTable()487 bool HeapObject::IsObjectHashTable() const { return IsHashTable(); }
488 
IsOrderedHashSet()489 bool HeapObject::IsOrderedHashSet() const {
490   return map() == GetHeap()->ordered_hash_set_map();
491 }
492 
IsOrderedHashMap()493 bool HeapObject::IsOrderedHashMap() const {
494   return map() == GetHeap()->ordered_hash_map_map();
495 }
496 
IsSmallOrderedHashTable()497 bool Object::IsSmallOrderedHashTable() const {
498   return IsSmallOrderedHashSet() || IsSmallOrderedHashMap();
499 }
500 
IsPrimitive()501 bool Object::IsPrimitive() const {
502   return IsSmi() || HeapObject::cast(this)->map()->IsPrimitiveMap();
503 }
504 
505 // static
IsArray(Handle<Object> object)506 Maybe<bool> Object::IsArray(Handle<Object> object) {
507   if (object->IsSmi()) return Just(false);
508   Handle<HeapObject> heap_object = Handle<HeapObject>::cast(object);
509   if (heap_object->IsJSArray()) return Just(true);
510   if (!heap_object->IsJSProxy()) return Just(false);
511   return JSProxy::IsArray(Handle<JSProxy>::cast(object));
512 }
513 
IsJSGlobalProxy()514 bool HeapObject::IsJSGlobalProxy() const {
515   bool result = map()->instance_type() == JS_GLOBAL_PROXY_TYPE;
516   DCHECK(!result || map()->is_access_check_needed());
517   return result;
518 }
519 
IsUndetectable()520 bool HeapObject::IsUndetectable() const { return map()->is_undetectable(); }
521 
IsAccessCheckNeeded()522 bool HeapObject::IsAccessCheckNeeded() const {
523   if (IsJSGlobalProxy()) {
524     const JSGlobalProxy* proxy = JSGlobalProxy::cast(this);
525     JSGlobalObject* global = proxy->GetIsolate()->context()->global_object();
526     return proxy->IsDetachedFrom(global);
527   }
528   return map()->is_access_check_needed();
529 }
530 
IsStruct()531 bool HeapObject::IsStruct() const {
532   switch (map()->instance_type()) {
533 #define MAKE_STRUCT_CASE(NAME, Name, name) \
534   case NAME##_TYPE:                        \
535     return true;
536     STRUCT_LIST(MAKE_STRUCT_CASE)
537 #undef MAKE_STRUCT_CASE
538     default:
539       return false;
540   }
541 }
542 
543 #define MAKE_STRUCT_PREDICATE(NAME, Name, name)                  \
544   bool Object::Is##Name() const {                                \
545     return IsHeapObject() && HeapObject::cast(this)->Is##Name(); \
546   }                                                              \
547   bool HeapObject::Is##Name() const {                            \
548     return map()->instance_type() == NAME##_TYPE;                \
549   }
STRUCT_LIST(MAKE_STRUCT_PREDICATE)550 STRUCT_LIST(MAKE_STRUCT_PREDICATE)
551 #undef MAKE_STRUCT_PREDICATE
552 
553 double Object::Number() const {
554   DCHECK(IsNumber());
555   return IsSmi()
556              ? static_cast<double>(reinterpret_cast<const Smi*>(this)->value())
557              : reinterpret_cast<const HeapNumber*>(this)->value();
558 }
559 
IsNaN()560 bool Object::IsNaN() const {
561   return this->IsHeapNumber() && std::isnan(HeapNumber::cast(this)->value());
562 }
563 
IsMinusZero()564 bool Object::IsMinusZero() const {
565   return this->IsHeapNumber() &&
566          i::IsMinusZero(HeapNumber::cast(this)->value());
567 }
568 
569 // ------------------------------------
570 // Cast operations
571 
572 CAST_ACCESSOR(AccessorPair)
CAST_ACCESSOR(AllocationMemento)573 CAST_ACCESSOR(AllocationMemento)
574 CAST_ACCESSOR(AllocationSite)
575 CAST_ACCESSOR(AsyncGeneratorRequest)
576 CAST_ACCESSOR(BigInt)
577 CAST_ACCESSOR(BoilerplateDescription)
578 CAST_ACCESSOR(Cell)
579 CAST_ACCESSOR(ConstantElementsPair)
580 CAST_ACCESSOR(DescriptorArray)
581 CAST_ACCESSOR(EnumCache)
582 CAST_ACCESSOR(FeedbackCell)
583 CAST_ACCESSOR(Foreign)
584 CAST_ACCESSOR(GlobalDictionary)
585 CAST_ACCESSOR(HeapObject)
586 CAST_ACCESSOR(JSAsyncFromSyncIterator)
587 CAST_ACCESSOR(JSAsyncGeneratorObject)
588 CAST_ACCESSOR(JSBoundFunction)
589 CAST_ACCESSOR(JSDataView)
590 CAST_ACCESSOR(JSDate)
591 CAST_ACCESSOR(JSFunction)
592 CAST_ACCESSOR(JSGeneratorObject)
593 CAST_ACCESSOR(JSGlobalObject)
594 CAST_ACCESSOR(JSGlobalProxy)
595 CAST_ACCESSOR(JSMessageObject)
596 CAST_ACCESSOR(JSObject)
597 CAST_ACCESSOR(JSProxy)
598 CAST_ACCESSOR(JSReceiver)
599 CAST_ACCESSOR(JSStringIterator)
600 CAST_ACCESSOR(JSValue)
601 CAST_ACCESSOR(LayoutDescriptor)
602 CAST_ACCESSOR(NameDictionary)
603 CAST_ACCESSOR(NormalizedMapCache)
604 CAST_ACCESSOR(NumberDictionary)
605 CAST_ACCESSOR(Object)
606 CAST_ACCESSOR(ObjectHashSet)
607 CAST_ACCESSOR(ObjectHashTable)
608 CAST_ACCESSOR(Oddball)
609 CAST_ACCESSOR(OrderedHashMap)
610 CAST_ACCESSOR(OrderedHashSet)
611 CAST_ACCESSOR(PropertyArray)
612 CAST_ACCESSOR(PropertyCell)
613 CAST_ACCESSOR(PrototypeInfo)
614 CAST_ACCESSOR(RegExpMatchInfo)
615 CAST_ACCESSOR(ScopeInfo)
616 CAST_ACCESSOR(SimpleNumberDictionary)
617 CAST_ACCESSOR(SmallOrderedHashMap)
618 CAST_ACCESSOR(SmallOrderedHashSet)
619 CAST_ACCESSOR(Smi)
620 CAST_ACCESSOR(SourcePositionTableWithFrameCache)
621 CAST_ACCESSOR(StackFrameInfo)
622 CAST_ACCESSOR(StringSet)
623 CAST_ACCESSOR(StringTable)
624 CAST_ACCESSOR(Struct)
625 CAST_ACCESSOR(TemplateObjectDescription)
626 CAST_ACCESSOR(Tuple2)
627 CAST_ACCESSOR(Tuple3)
628 CAST_ACCESSOR(WeakCell)
629 
630 bool Object::HasValidElements() {
631   // Dictionary is covered under FixedArray.
632   return IsFixedArray() || IsFixedDoubleArray() || IsFixedTypedArrayBase();
633 }
634 
KeyEquals(Object * second)635 bool Object::KeyEquals(Object* second) {
636   Object* first = this;
637   if (second->IsNumber()) {
638     if (first->IsNumber()) return first->Number() == second->Number();
639     Object* temp = first;
640     first = second;
641     second = temp;
642   }
643   if (first->IsNumber()) {
644     DCHECK_LE(0, first->Number());
645     uint32_t expected = static_cast<uint32_t>(first->Number());
646     uint32_t index;
647     return Name::cast(second)->AsArrayIndex(&index) && index == expected;
648   }
649   return Name::cast(first)->Equals(Name::cast(second));
650 }
651 
FilterKey(PropertyFilter filter)652 bool Object::FilterKey(PropertyFilter filter) {
653   DCHECK(!IsPropertyCell());
654   if (IsSymbol()) {
655     if (filter & SKIP_SYMBOLS) return true;
656     if (Symbol::cast(this)->is_private()) return true;
657   } else {
658     if (filter & SKIP_STRINGS) return true;
659   }
660   return false;
661 }
662 
NewStorageFor(Isolate * isolate,Handle<Object> object,Representation representation)663 Handle<Object> Object::NewStorageFor(Isolate* isolate, Handle<Object> object,
664                                      Representation representation) {
665   if (!representation.IsDouble()) return object;
666   Handle<HeapNumber> result = isolate->factory()->NewHeapNumber(MUTABLE);
667   if (object->IsUninitialized(isolate)) {
668     result->set_value_as_bits(kHoleNanInt64);
669   } else if (object->IsMutableHeapNumber()) {
670     // Ensure that all bits of the double value are preserved.
671     result->set_value_as_bits(HeapNumber::cast(*object)->value_as_bits());
672   } else {
673     result->set_value(object->Number());
674   }
675   return result;
676 }
677 
WrapForRead(Isolate * isolate,Handle<Object> object,Representation representation)678 Handle<Object> Object::WrapForRead(Isolate* isolate, Handle<Object> object,
679                                    Representation representation) {
680   DCHECK(!object->IsUninitialized(isolate));
681   if (!representation.IsDouble()) {
682     DCHECK(object->FitsRepresentation(representation));
683     return object;
684   }
685   return isolate->factory()->NewHeapNumber(HeapNumber::cast(*object)->value());
686 }
687 
OptimalRepresentation()688 Representation Object::OptimalRepresentation() {
689   if (!FLAG_track_fields) return Representation::Tagged();
690   if (IsSmi()) {
691     return Representation::Smi();
692   } else if (FLAG_track_double_fields && IsHeapNumber()) {
693     return Representation::Double();
694   } else if (FLAG_track_computed_fields &&
695              IsUninitialized(HeapObject::cast(this)->GetIsolate())) {
696     return Representation::None();
697   } else if (FLAG_track_heap_object_fields) {
698     DCHECK(IsHeapObject());
699     return Representation::HeapObject();
700   } else {
701     return Representation::Tagged();
702   }
703 }
704 
705 
OptimalElementsKind()706 ElementsKind Object::OptimalElementsKind() {
707   if (IsSmi()) return PACKED_SMI_ELEMENTS;
708   if (IsNumber()) return PACKED_DOUBLE_ELEMENTS;
709   return PACKED_ELEMENTS;
710 }
711 
712 
FitsRepresentation(Representation representation)713 bool Object::FitsRepresentation(Representation representation) {
714   if (FLAG_track_fields && representation.IsSmi()) {
715     return IsSmi();
716   } else if (FLAG_track_double_fields && representation.IsDouble()) {
717     return IsMutableHeapNumber() || IsNumber();
718   } else if (FLAG_track_heap_object_fields && representation.IsHeapObject()) {
719     return IsHeapObject();
720   } else if (FLAG_track_fields && representation.IsNone()) {
721     return false;
722   }
723   return true;
724 }
725 
ToUint32(uint32_t * value)726 bool Object::ToUint32(uint32_t* value) const {
727   if (IsSmi()) {
728     int num = Smi::ToInt(this);
729     if (num < 0) return false;
730     *value = static_cast<uint32_t>(num);
731     return true;
732   }
733   if (IsHeapNumber()) {
734     double num = HeapNumber::cast(this)->value();
735     return DoubleToUint32IfEqualToSelf(num, value);
736   }
737   return false;
738 }
739 
740 // static
ToObject(Isolate * isolate,Handle<Object> object,const char * method_name)741 MaybeHandle<JSReceiver> Object::ToObject(Isolate* isolate,
742                                          Handle<Object> object,
743                                          const char* method_name) {
744   if (object->IsJSReceiver()) return Handle<JSReceiver>::cast(object);
745   return ToObject(isolate, object, isolate->native_context(), method_name);
746 }
747 
748 
749 // static
ToName(Isolate * isolate,Handle<Object> input)750 MaybeHandle<Name> Object::ToName(Isolate* isolate, Handle<Object> input) {
751   if (input->IsName()) return Handle<Name>::cast(input);
752   return ConvertToName(isolate, input);
753 }
754 
755 // static
ToPropertyKey(Isolate * isolate,Handle<Object> value)756 MaybeHandle<Object> Object::ToPropertyKey(Isolate* isolate,
757                                           Handle<Object> value) {
758   if (value->IsSmi() || HeapObject::cast(*value)->IsName()) return value;
759   return ConvertToPropertyKey(isolate, value);
760 }
761 
762 // static
ToPrimitive(Handle<Object> input,ToPrimitiveHint hint)763 MaybeHandle<Object> Object::ToPrimitive(Handle<Object> input,
764                                         ToPrimitiveHint hint) {
765   if (input->IsPrimitive()) return input;
766   return JSReceiver::ToPrimitive(Handle<JSReceiver>::cast(input), hint);
767 }
768 
769 // static
ToNumber(Handle<Object> input)770 MaybeHandle<Object> Object::ToNumber(Handle<Object> input) {
771   if (input->IsNumber()) return input;  // Shortcut.
772   return ConvertToNumberOrNumeric(HeapObject::cast(*input)->GetIsolate(), input,
773                                   Conversion::kToNumber);
774 }
775 
776 // static
ToNumeric(Handle<Object> input)777 MaybeHandle<Object> Object::ToNumeric(Handle<Object> input) {
778   if (input->IsNumber() || input->IsBigInt()) return input;  // Shortcut.
779   return ConvertToNumberOrNumeric(HeapObject::cast(*input)->GetIsolate(), input,
780                                   Conversion::kToNumeric);
781 }
782 
783 // static
ToInteger(Isolate * isolate,Handle<Object> input)784 MaybeHandle<Object> Object::ToInteger(Isolate* isolate, Handle<Object> input) {
785   if (input->IsSmi()) return input;
786   return ConvertToInteger(isolate, input);
787 }
788 
789 // static
ToInt32(Isolate * isolate,Handle<Object> input)790 MaybeHandle<Object> Object::ToInt32(Isolate* isolate, Handle<Object> input) {
791   if (input->IsSmi()) return input;
792   return ConvertToInt32(isolate, input);
793 }
794 
795 // static
ToUint32(Isolate * isolate,Handle<Object> input)796 MaybeHandle<Object> Object::ToUint32(Isolate* isolate, Handle<Object> input) {
797   if (input->IsSmi()) return handle(Smi::cast(*input)->ToUint32Smi(), isolate);
798   return ConvertToUint32(isolate, input);
799 }
800 
801 // static
ToString(Isolate * isolate,Handle<Object> input)802 MaybeHandle<String> Object::ToString(Isolate* isolate, Handle<Object> input) {
803   if (input->IsString()) return Handle<String>::cast(input);
804   return ConvertToString(isolate, input);
805 }
806 
807 // static
ToLength(Isolate * isolate,Handle<Object> input)808 MaybeHandle<Object> Object::ToLength(Isolate* isolate, Handle<Object> input) {
809   if (input->IsSmi()) {
810     int value = std::max(Smi::ToInt(*input), 0);
811     return handle(Smi::FromInt(value), isolate);
812   }
813   return ConvertToLength(isolate, input);
814 }
815 
816 // static
ToIndex(Isolate * isolate,Handle<Object> input,MessageTemplate::Template error_index)817 MaybeHandle<Object> Object::ToIndex(Isolate* isolate, Handle<Object> input,
818                                     MessageTemplate::Template error_index) {
819   if (input->IsSmi() && Smi::ToInt(*input) >= 0) return input;
820   return ConvertToIndex(isolate, input, error_index);
821 }
822 
GetProperty(Handle<Object> object,Handle<Name> name)823 MaybeHandle<Object> Object::GetProperty(Handle<Object> object,
824                                         Handle<Name> name) {
825   LookupIterator it(object, name);
826   if (!it.IsFound()) return it.factory()->undefined_value();
827   return GetProperty(&it);
828 }
829 
GetProperty(Handle<JSReceiver> receiver,Handle<Name> name)830 MaybeHandle<Object> JSReceiver::GetProperty(Handle<JSReceiver> receiver,
831                                             Handle<Name> name) {
832   LookupIterator it(receiver, name, receiver);
833   if (!it.IsFound()) return it.factory()->undefined_value();
834   return Object::GetProperty(&it);
835 }
836 
GetElement(Isolate * isolate,Handle<Object> object,uint32_t index)837 MaybeHandle<Object> Object::GetElement(Isolate* isolate, Handle<Object> object,
838                                        uint32_t index) {
839   LookupIterator it(isolate, object, index);
840   if (!it.IsFound()) return it.factory()->undefined_value();
841   return GetProperty(&it);
842 }
843 
GetElement(Isolate * isolate,Handle<JSReceiver> receiver,uint32_t index)844 MaybeHandle<Object> JSReceiver::GetElement(Isolate* isolate,
845                                            Handle<JSReceiver> receiver,
846                                            uint32_t index) {
847   LookupIterator it(isolate, receiver, index, receiver);
848   if (!it.IsFound()) return it.factory()->undefined_value();
849   return Object::GetProperty(&it);
850 }
851 
GetDataProperty(Handle<JSReceiver> object,Handle<Name> name)852 Handle<Object> JSReceiver::GetDataProperty(Handle<JSReceiver> object,
853                                            Handle<Name> name) {
854   LookupIterator it(object, name, object,
855                     LookupIterator::PROTOTYPE_CHAIN_SKIP_INTERCEPTOR);
856   if (!it.IsFound()) return it.factory()->undefined_value();
857   return GetDataProperty(&it);
858 }
859 
SetElement(Isolate * isolate,Handle<Object> object,uint32_t index,Handle<Object> value,LanguageMode language_mode)860 MaybeHandle<Object> Object::SetElement(Isolate* isolate, Handle<Object> object,
861                                        uint32_t index, Handle<Object> value,
862                                        LanguageMode language_mode) {
863   LookupIterator it(isolate, object, index);
864   MAYBE_RETURN_NULL(
865       SetProperty(&it, value, language_mode, MAY_BE_STORE_FROM_KEYED));
866   return value;
867 }
868 
GetPrototype(Isolate * isolate,Handle<JSReceiver> receiver)869 MaybeHandle<Object> JSReceiver::GetPrototype(Isolate* isolate,
870                                              Handle<JSReceiver> receiver) {
871   // We don't expect access checks to be needed on JSProxy objects.
872   DCHECK(!receiver->IsAccessCheckNeeded() || receiver->IsJSObject());
873   PrototypeIterator iter(isolate, receiver, kStartAtReceiver,
874                          PrototypeIterator::END_AT_NON_HIDDEN);
875   do {
876     if (!iter.AdvanceFollowingProxies()) return MaybeHandle<Object>();
877   } while (!iter.IsAtEnd());
878   return PrototypeIterator::GetCurrent(iter);
879 }
880 
GetProperty(Isolate * isolate,Handle<JSReceiver> receiver,const char * name)881 MaybeHandle<Object> JSReceiver::GetProperty(Isolate* isolate,
882                                             Handle<JSReceiver> receiver,
883                                             const char* name) {
884   Handle<String> str = isolate->factory()->InternalizeUtf8String(name);
885   return GetProperty(receiver, str);
886 }
887 
888 // static
OwnPropertyKeys(Handle<JSReceiver> object)889 V8_WARN_UNUSED_RESULT MaybeHandle<FixedArray> JSReceiver::OwnPropertyKeys(
890     Handle<JSReceiver> object) {
891   return KeyAccumulator::GetKeys(object, KeyCollectionMode::kOwnOnly,
892                                  ALL_PROPERTIES,
893                                  GetKeysConversion::kConvertToString);
894 }
895 
PrototypeHasNoElements(Isolate * isolate,JSObject * object)896 bool JSObject::PrototypeHasNoElements(Isolate* isolate, JSObject* object) {
897   DisallowHeapAllocation no_gc;
898   HeapObject* prototype = HeapObject::cast(object->map()->prototype());
899   HeapObject* null = isolate->heap()->null_value();
900   HeapObject* empty_fixed_array = isolate->heap()->empty_fixed_array();
901   HeapObject* empty_slow_element_dictionary =
902       isolate->heap()->empty_slow_element_dictionary();
903   while (prototype != null) {
904     Map* map = prototype->map();
905     if (map->IsCustomElementsReceiverMap()) return false;
906     HeapObject* elements = JSObject::cast(prototype)->elements();
907     if (elements != empty_fixed_array &&
908         elements != empty_slow_element_dictionary) {
909       return false;
910     }
911     prototype = HeapObject::cast(map->prototype());
912   }
913   return true;
914 }
915 
RawField(const HeapObject * obj,int byte_offset)916 Object** HeapObject::RawField(const HeapObject* obj, int byte_offset) {
917   return reinterpret_cast<Object**>(FIELD_ADDR(obj, byte_offset));
918 }
919 
RawMaybeWeakField(HeapObject * obj,int byte_offset)920 MaybeObject** HeapObject::RawMaybeWeakField(HeapObject* obj, int byte_offset) {
921   return reinterpret_cast<MaybeObject**>(FIELD_ADDR(obj, byte_offset));
922 }
923 
ToInt(const Object * object)924 int Smi::ToInt(const Object* object) { return Smi::cast(object)->value(); }
925 
FromMap(const Map * map)926 MapWord MapWord::FromMap(const Map* map) {
927   return MapWord(reinterpret_cast<uintptr_t>(map));
928 }
929 
ToMap()930 Map* MapWord::ToMap() const { return reinterpret_cast<Map*>(value_); }
931 
IsForwardingAddress()932 bool MapWord::IsForwardingAddress() const {
933   return HAS_SMI_TAG(reinterpret_cast<Object*>(value_));
934 }
935 
936 
FromForwardingAddress(HeapObject * object)937 MapWord MapWord::FromForwardingAddress(HeapObject* object) {
938   Address raw = reinterpret_cast<Address>(object) - kHeapObjectTag;
939   return MapWord(static_cast<uintptr_t>(raw));
940 }
941 
942 
ToForwardingAddress()943 HeapObject* MapWord::ToForwardingAddress() {
944   DCHECK(IsForwardingAddress());
945   return HeapObject::FromAddress(static_cast<Address>(value_));
946 }
947 
948 
949 #ifdef VERIFY_HEAP
VerifyObjectField(int offset)950 void HeapObject::VerifyObjectField(int offset) {
951   VerifyPointer(READ_FIELD(this, offset));
952 }
953 
VerifySmiField(int offset)954 void HeapObject::VerifySmiField(int offset) {
955   CHECK(READ_FIELD(this, offset)->IsSmi());
956 }
957 #endif
958 
959 
GetHeap()960 Heap* HeapObject::GetHeap() const {
961   Heap* heap = MemoryChunk::FromAddress(
962                    reinterpret_cast<Address>(const_cast<HeapObject*>(this)))
963                    ->heap();
964   SLOW_DCHECK(heap != nullptr);
965   return heap;
966 }
967 
968 
GetIsolate()969 Isolate* HeapObject::GetIsolate() const {
970   return GetHeap()->isolate();
971 }
972 
map()973 Map* HeapObject::map() const {
974   return map_word().ToMap();
975 }
976 
977 
set_map(Map * value)978 void HeapObject::set_map(Map* value) {
979   if (value != nullptr) {
980 #ifdef VERIFY_HEAP
981     value->GetHeap()->VerifyObjectLayoutChange(this, value);
982 #endif
983   }
984   set_map_word(MapWord::FromMap(value));
985   if (value != nullptr) {
986     // TODO(1600) We are passing nullptr as a slot because maps can never be on
987     // evacuation candidate.
988     value->GetHeap()->incremental_marking()->RecordWrite(this, nullptr, value);
989   }
990 }
991 
synchronized_map()992 Map* HeapObject::synchronized_map() const {
993   return synchronized_map_word().ToMap();
994 }
995 
996 
synchronized_set_map(Map * value)997 void HeapObject::synchronized_set_map(Map* value) {
998   if (value != nullptr) {
999 #ifdef VERIFY_HEAP
1000     value->GetHeap()->VerifyObjectLayoutChange(this, value);
1001 #endif
1002   }
1003   synchronized_set_map_word(MapWord::FromMap(value));
1004   if (value != nullptr) {
1005     // TODO(1600) We are passing nullptr as a slot because maps can never be on
1006     // evacuation candidate.
1007     value->GetHeap()->incremental_marking()->RecordWrite(this, nullptr, value);
1008   }
1009 }
1010 
1011 
1012 // Unsafe accessor omitting write barrier.
set_map_no_write_barrier(Map * value)1013 void HeapObject::set_map_no_write_barrier(Map* value) {
1014   if (value != nullptr) {
1015 #ifdef VERIFY_HEAP
1016     value->GetHeap()->VerifyObjectLayoutChange(this, value);
1017 #endif
1018   }
1019   set_map_word(MapWord::FromMap(value));
1020 }
1021 
set_map_after_allocation(Map * value,WriteBarrierMode mode)1022 void HeapObject::set_map_after_allocation(Map* value, WriteBarrierMode mode) {
1023   set_map_word(MapWord::FromMap(value));
1024   if (mode != SKIP_WRITE_BARRIER) {
1025     DCHECK_NOT_NULL(value);
1026     // TODO(1600) We are passing nullptr as a slot because maps can never be on
1027     // evacuation candidate.
1028     value->GetHeap()->incremental_marking()->RecordWrite(this, nullptr, value);
1029   }
1030 }
1031 
map_slot()1032 HeapObject** HeapObject::map_slot() {
1033   return reinterpret_cast<HeapObject**>(FIELD_ADDR(this, kMapOffset));
1034 }
1035 
map_word()1036 MapWord HeapObject::map_word() const {
1037   return MapWord(
1038       reinterpret_cast<uintptr_t>(RELAXED_READ_FIELD(this, kMapOffset)));
1039 }
1040 
1041 
set_map_word(MapWord map_word)1042 void HeapObject::set_map_word(MapWord map_word) {
1043   RELAXED_WRITE_FIELD(this, kMapOffset,
1044                       reinterpret_cast<Object*>(map_word.value_));
1045 }
1046 
1047 
synchronized_map_word()1048 MapWord HeapObject::synchronized_map_word() const {
1049   return MapWord(
1050       reinterpret_cast<uintptr_t>(ACQUIRE_READ_FIELD(this, kMapOffset)));
1051 }
1052 
1053 
synchronized_set_map_word(MapWord map_word)1054 void HeapObject::synchronized_set_map_word(MapWord map_word) {
1055   RELEASE_WRITE_FIELD(
1056       this, kMapOffset, reinterpret_cast<Object*>(map_word.value_));
1057 }
1058 
Size()1059 int HeapObject::Size() const { return SizeFromMap(map()); }
1060 
value()1061 double HeapNumber::value() const {
1062   return READ_DOUBLE_FIELD(this, kValueOffset);
1063 }
1064 
1065 
set_value(double value)1066 void HeapNumber::set_value(double value) {
1067   WRITE_DOUBLE_FIELD(this, kValueOffset, value);
1068 }
1069 
value_as_bits()1070 uint64_t HeapNumber::value_as_bits() const {
1071   return READ_UINT64_FIELD(this, kValueOffset);
1072 }
1073 
set_value_as_bits(uint64_t bits)1074 void HeapNumber::set_value_as_bits(uint64_t bits) {
1075   WRITE_UINT64_FIELD(this, kValueOffset, bits);
1076 }
1077 
get_exponent()1078 int HeapNumber::get_exponent() {
1079   return ((READ_INT_FIELD(this, kExponentOffset) & kExponentMask) >>
1080           kExponentShift) - kExponentBias;
1081 }
1082 
1083 
get_sign()1084 int HeapNumber::get_sign() {
1085   return READ_INT_FIELD(this, kExponentOffset) & kSignMask;
1086 }
1087 
ACCESSORS(JSReceiver,raw_properties_or_hash,Object,kPropertiesOrHashOffset)1088 ACCESSORS(JSReceiver, raw_properties_or_hash, Object, kPropertiesOrHashOffset)
1089 
1090 FixedArrayBase* JSObject::elements() const {
1091   Object* array = READ_FIELD(this, kElementsOffset);
1092   return static_cast<FixedArrayBase*>(array);
1093 }
1094 
Initialize()1095 void AllocationSite::Initialize() {
1096   set_transition_info_or_boilerplate(Smi::kZero);
1097   SetElementsKind(GetInitialFastElementsKind());
1098   set_nested_site(Smi::kZero);
1099   set_pretenure_data(0);
1100   set_pretenure_create_count(0);
1101   set_dependent_code(DependentCode::cast(GetHeap()->empty_fixed_array()),
1102                      SKIP_WRITE_BARRIER);
1103 }
1104 
IsZombie()1105 bool AllocationSite::IsZombie() const {
1106   return pretenure_decision() == kZombie;
1107 }
1108 
IsMaybeTenure()1109 bool AllocationSite::IsMaybeTenure() const {
1110   return pretenure_decision() == kMaybeTenure;
1111 }
1112 
PretenuringDecisionMade()1113 bool AllocationSite::PretenuringDecisionMade() const {
1114   return pretenure_decision() != kUndecided;
1115 }
1116 
1117 
MarkZombie()1118 void AllocationSite::MarkZombie() {
1119   DCHECK(!IsZombie());
1120   Initialize();
1121   set_pretenure_decision(kZombie);
1122 }
1123 
GetElementsKind()1124 ElementsKind AllocationSite::GetElementsKind() const {
1125   return ElementsKindBits::decode(transition_info());
1126 }
1127 
1128 
SetElementsKind(ElementsKind kind)1129 void AllocationSite::SetElementsKind(ElementsKind kind) {
1130   set_transition_info(ElementsKindBits::update(transition_info(), kind));
1131 }
1132 
CanInlineCall()1133 bool AllocationSite::CanInlineCall() const {
1134   return DoNotInlineBit::decode(transition_info()) == 0;
1135 }
1136 
1137 
SetDoNotInlineCall()1138 void AllocationSite::SetDoNotInlineCall() {
1139   set_transition_info(DoNotInlineBit::update(transition_info(), true));
1140 }
1141 
PointsToLiteral()1142 bool AllocationSite::PointsToLiteral() const {
1143   Object* raw_value = transition_info_or_boilerplate();
1144   DCHECK_EQ(!raw_value->IsSmi(),
1145             raw_value->IsJSArray() || raw_value->IsJSObject());
1146   return !raw_value->IsSmi();
1147 }
1148 
1149 
1150 // Heuristic: We only need to create allocation site info if the boilerplate
1151 // elements kind is the initial elements kind.
ShouldTrack(ElementsKind boilerplate_elements_kind)1152 bool AllocationSite::ShouldTrack(ElementsKind boilerplate_elements_kind) {
1153   return IsSmiElementsKind(boilerplate_elements_kind);
1154 }
1155 
CanTrack(InstanceType type)1156 inline bool AllocationSite::CanTrack(InstanceType type) {
1157   if (FLAG_allocation_site_pretenuring) {
1158     // TurboFan doesn't care at all about String pretenuring feedback,
1159     // so don't bother even trying to track that.
1160     return type == JS_ARRAY_TYPE || type == JS_OBJECT_TYPE;
1161   }
1162   return type == JS_ARRAY_TYPE;
1163 }
1164 
pretenure_decision()1165 AllocationSite::PretenureDecision AllocationSite::pretenure_decision() const {
1166   return PretenureDecisionBits::decode(pretenure_data());
1167 }
1168 
set_pretenure_decision(PretenureDecision decision)1169 void AllocationSite::set_pretenure_decision(PretenureDecision decision) {
1170   int value = pretenure_data();
1171   set_pretenure_data(PretenureDecisionBits::update(value, decision));
1172 }
1173 
deopt_dependent_code()1174 bool AllocationSite::deopt_dependent_code() const {
1175   return DeoptDependentCodeBit::decode(pretenure_data());
1176 }
1177 
set_deopt_dependent_code(bool deopt)1178 void AllocationSite::set_deopt_dependent_code(bool deopt) {
1179   int value = pretenure_data();
1180   set_pretenure_data(DeoptDependentCodeBit::update(value, deopt));
1181 }
1182 
memento_found_count()1183 int AllocationSite::memento_found_count() const {
1184   return MementoFoundCountBits::decode(pretenure_data());
1185 }
1186 
set_memento_found_count(int count)1187 inline void AllocationSite::set_memento_found_count(int count) {
1188   int value = pretenure_data();
1189   // Verify that we can count more mementos than we can possibly find in one
1190   // new space collection.
1191   DCHECK((GetHeap()->MaxSemiSpaceSize() /
1192           (Heap::kMinObjectSizeInWords * kPointerSize +
1193            AllocationMemento::kSize)) < MementoFoundCountBits::kMax);
1194   DCHECK_LT(count, MementoFoundCountBits::kMax);
1195   set_pretenure_data(MementoFoundCountBits::update(value, count));
1196 }
1197 
memento_create_count()1198 int AllocationSite::memento_create_count() const {
1199   return pretenure_create_count();
1200 }
1201 
set_memento_create_count(int count)1202 void AllocationSite::set_memento_create_count(int count) {
1203   set_pretenure_create_count(count);
1204 }
1205 
IncrementMementoFoundCount(int increment)1206 bool AllocationSite::IncrementMementoFoundCount(int increment) {
1207   if (IsZombie()) return false;
1208 
1209   int value = memento_found_count();
1210   set_memento_found_count(value + increment);
1211   return memento_found_count() >= kPretenureMinimumCreated;
1212 }
1213 
1214 
IncrementMementoCreateCount()1215 inline void AllocationSite::IncrementMementoCreateCount() {
1216   DCHECK(FLAG_allocation_site_pretenuring);
1217   int value = memento_create_count();
1218   set_memento_create_count(value + 1);
1219 }
1220 
IsValid()1221 bool AllocationMemento::IsValid() const {
1222   return allocation_site()->IsAllocationSite() &&
1223          !AllocationSite::cast(allocation_site())->IsZombie();
1224 }
1225 
GetAllocationSite()1226 AllocationSite* AllocationMemento::GetAllocationSite() const {
1227   DCHECK(IsValid());
1228   return AllocationSite::cast(allocation_site());
1229 }
1230 
GetAllocationSiteUnchecked()1231 Address AllocationMemento::GetAllocationSiteUnchecked() const {
1232   return reinterpret_cast<Address>(allocation_site());
1233 }
1234 
EnsureCanContainHeapObjectElements(Handle<JSObject> object)1235 void JSObject::EnsureCanContainHeapObjectElements(Handle<JSObject> object) {
1236   JSObject::ValidateElements(*object);
1237   ElementsKind elements_kind = object->map()->elements_kind();
1238   if (!IsObjectElementsKind(elements_kind)) {
1239     if (IsHoleyElementsKind(elements_kind)) {
1240       TransitionElementsKind(object, HOLEY_ELEMENTS);
1241     } else {
1242       TransitionElementsKind(object, PACKED_ELEMENTS);
1243     }
1244   }
1245 }
1246 
1247 
EnsureCanContainElements(Handle<JSObject> object,Object ** objects,uint32_t count,EnsureElementsMode mode)1248 void JSObject::EnsureCanContainElements(Handle<JSObject> object,
1249                                         Object** objects,
1250                                         uint32_t count,
1251                                         EnsureElementsMode mode) {
1252   ElementsKind current_kind = object->GetElementsKind();
1253   ElementsKind target_kind = current_kind;
1254   {
1255     DisallowHeapAllocation no_allocation;
1256     DCHECK(mode != ALLOW_COPIED_DOUBLE_ELEMENTS);
1257     bool is_holey = IsHoleyElementsKind(current_kind);
1258     if (current_kind == HOLEY_ELEMENTS) return;
1259     Object* the_hole = object->GetHeap()->the_hole_value();
1260     for (uint32_t i = 0; i < count; ++i) {
1261       Object* current = *objects++;
1262       if (current == the_hole) {
1263         is_holey = true;
1264         target_kind = GetHoleyElementsKind(target_kind);
1265       } else if (!current->IsSmi()) {
1266         if (mode == ALLOW_CONVERTED_DOUBLE_ELEMENTS && current->IsNumber()) {
1267           if (IsSmiElementsKind(target_kind)) {
1268             if (is_holey) {
1269               target_kind = HOLEY_DOUBLE_ELEMENTS;
1270             } else {
1271               target_kind = PACKED_DOUBLE_ELEMENTS;
1272             }
1273           }
1274         } else if (is_holey) {
1275           target_kind = HOLEY_ELEMENTS;
1276           break;
1277         } else {
1278           target_kind = PACKED_ELEMENTS;
1279         }
1280       }
1281     }
1282   }
1283   if (target_kind != current_kind) {
1284     TransitionElementsKind(object, target_kind);
1285   }
1286 }
1287 
1288 
EnsureCanContainElements(Handle<JSObject> object,Handle<FixedArrayBase> elements,uint32_t length,EnsureElementsMode mode)1289 void JSObject::EnsureCanContainElements(Handle<JSObject> object,
1290                                         Handle<FixedArrayBase> elements,
1291                                         uint32_t length,
1292                                         EnsureElementsMode mode) {
1293   Heap* heap = object->GetHeap();
1294   if (elements->map() != heap->fixed_double_array_map()) {
1295     DCHECK(elements->map() == heap->fixed_array_map() ||
1296            elements->map() == heap->fixed_cow_array_map());
1297     if (mode == ALLOW_COPIED_DOUBLE_ELEMENTS) {
1298       mode = DONT_ALLOW_DOUBLE_ELEMENTS;
1299     }
1300     Object** objects =
1301         Handle<FixedArray>::cast(elements)->GetFirstElementAddress();
1302     EnsureCanContainElements(object, objects, length, mode);
1303     return;
1304   }
1305 
1306   DCHECK(mode == ALLOW_COPIED_DOUBLE_ELEMENTS);
1307   if (object->GetElementsKind() == HOLEY_SMI_ELEMENTS) {
1308     TransitionElementsKind(object, HOLEY_DOUBLE_ELEMENTS);
1309   } else if (object->GetElementsKind() == PACKED_SMI_ELEMENTS) {
1310     Handle<FixedDoubleArray> double_array =
1311         Handle<FixedDoubleArray>::cast(elements);
1312     for (uint32_t i = 0; i < length; ++i) {
1313       if (double_array->is_the_hole(i)) {
1314         TransitionElementsKind(object, HOLEY_DOUBLE_ELEMENTS);
1315         return;
1316       }
1317     }
1318     TransitionElementsKind(object, PACKED_DOUBLE_ELEMENTS);
1319   }
1320 }
1321 
1322 
SetMapAndElements(Handle<JSObject> object,Handle<Map> new_map,Handle<FixedArrayBase> value)1323 void JSObject::SetMapAndElements(Handle<JSObject> object,
1324                                  Handle<Map> new_map,
1325                                  Handle<FixedArrayBase> value) {
1326   JSObject::MigrateToMap(object, new_map);
1327   DCHECK((object->map()->has_fast_smi_or_object_elements() ||
1328           (*value == object->GetHeap()->empty_fixed_array()) ||
1329           object->map()->has_fast_string_wrapper_elements()) ==
1330          (value->map() == object->GetHeap()->fixed_array_map() ||
1331           value->map() == object->GetHeap()->fixed_cow_array_map()));
1332   DCHECK((*value == object->GetHeap()->empty_fixed_array()) ||
1333          (object->map()->has_fast_double_elements() ==
1334           value->IsFixedDoubleArray()));
1335   object->set_elements(*value);
1336 }
1337 
1338 
set_elements(FixedArrayBase * value,WriteBarrierMode mode)1339 void JSObject::set_elements(FixedArrayBase* value, WriteBarrierMode mode) {
1340   WRITE_FIELD(this, kElementsOffset, value);
1341   CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kElementsOffset, value, mode);
1342 }
1343 
1344 
initialize_elements()1345 void JSObject::initialize_elements() {
1346   FixedArrayBase* elements = map()->GetInitialElements();
1347   WRITE_FIELD(this, kElementsOffset, elements);
1348 }
1349 
1350 
GetIndexedInterceptor()1351 InterceptorInfo* JSObject::GetIndexedInterceptor() {
1352   return map()->GetIndexedInterceptor();
1353 }
1354 
GetNamedInterceptor()1355 InterceptorInfo* JSObject::GetNamedInterceptor() {
1356   return map()->GetNamedInterceptor();
1357 }
1358 
to_number_raw()1359 double Oddball::to_number_raw() const {
1360   return READ_DOUBLE_FIELD(this, kToNumberRawOffset);
1361 }
1362 
set_to_number_raw(double value)1363 void Oddball::set_to_number_raw(double value) {
1364   WRITE_DOUBLE_FIELD(this, kToNumberRawOffset, value);
1365 }
1366 
set_to_number_raw_as_bits(uint64_t bits)1367 void Oddball::set_to_number_raw_as_bits(uint64_t bits) {
1368   WRITE_UINT64_FIELD(this, kToNumberRawOffset, bits);
1369 }
1370 
ACCESSORS(Oddball,to_string,String,kToStringOffset)1371 ACCESSORS(Oddball, to_string, String, kToStringOffset)
1372 ACCESSORS(Oddball, to_number, Object, kToNumberOffset)
1373 ACCESSORS(Oddball, type_of, String, kTypeOfOffset)
1374 
1375 byte Oddball::kind() const { return Smi::ToInt(READ_FIELD(this, kKindOffset)); }
1376 
set_kind(byte value)1377 void Oddball::set_kind(byte value) {
1378   WRITE_FIELD(this, kKindOffset, Smi::FromInt(value));
1379 }
1380 
1381 
1382 // static
ToNumber(Handle<Oddball> input)1383 Handle<Object> Oddball::ToNumber(Handle<Oddball> input) {
1384   return handle(input->to_number(), input->GetIsolate());
1385 }
1386 
1387 
ACCESSORS(Cell,value,Object,kValueOffset)1388 ACCESSORS(Cell, value, Object, kValueOffset)
1389 ACCESSORS(FeedbackCell, value, HeapObject, kValueOffset)
1390 ACCESSORS(PropertyCell, dependent_code, DependentCode, kDependentCodeOffset)
1391 ACCESSORS(PropertyCell, name, Name, kNameOffset)
1392 ACCESSORS(PropertyCell, value, Object, kValueOffset)
1393 ACCESSORS(PropertyCell, property_details_raw, Object, kDetailsOffset)
1394 
1395 PropertyDetails PropertyCell::property_details() {
1396   return PropertyDetails(Smi::cast(property_details_raw()));
1397 }
1398 
1399 
set_property_details(PropertyDetails details)1400 void PropertyCell::set_property_details(PropertyDetails details) {
1401   set_property_details_raw(details.AsSmi());
1402 }
1403 
1404 
value()1405 Object* WeakCell::value() const { return READ_FIELD(this, kValueOffset); }
1406 
1407 
clear()1408 void WeakCell::clear() {
1409   // Either the garbage collector is clearing the cell or we are simply
1410   // initializing the root empty weak cell.
1411   DCHECK(GetHeap()->gc_state() == Heap::MARK_COMPACT ||
1412          this == GetHeap()->empty_weak_cell());
1413   WRITE_FIELD(this, kValueOffset, Smi::kZero);
1414 }
1415 
1416 
initialize(HeapObject * val)1417 void WeakCell::initialize(HeapObject* val) {
1418   WRITE_FIELD(this, kValueOffset, val);
1419   // We just have to execute the generational barrier here because we never
1420   // mark through a weak cell and collect evacuation candidates when we process
1421   // all weak cells.
1422   Heap* heap = val->GetHeap();
1423   WriteBarrierMode mode =
1424       heap->incremental_marking()->marking_state()->IsBlack(this)
1425           ? UPDATE_WRITE_BARRIER
1426           : UPDATE_WEAK_WRITE_BARRIER;
1427   CONDITIONAL_WRITE_BARRIER(heap, this, kValueOffset, val, mode);
1428 }
1429 
cleared()1430 bool WeakCell::cleared() const { return value() == Smi::kZero; }
1431 
GetHeaderSize()1432 int JSObject::GetHeaderSize() const { return GetHeaderSize(map()); }
1433 
GetHeaderSize(const Map * map)1434 int JSObject::GetHeaderSize(const Map* map) {
1435   // Check for the most common kind of JavaScript object before
1436   // falling into the generic switch. This speeds up the internal
1437   // field operations considerably on average.
1438   InstanceType instance_type = map->instance_type();
1439   return instance_type == JS_OBJECT_TYPE
1440              ? JSObject::kHeaderSize
1441              : GetHeaderSize(instance_type, map->has_prototype_slot());
1442 }
1443 
IsSpecialReceiverInstanceType(InstanceType instance_type)1444 inline bool IsSpecialReceiverInstanceType(InstanceType instance_type) {
1445   return instance_type <= LAST_SPECIAL_RECEIVER_TYPE;
1446 }
1447 
1448 // This should be in objects/map-inl.h, but can't, because of a cyclic
1449 // dependency.
IsSpecialReceiverMap()1450 bool Map::IsSpecialReceiverMap() const {
1451   bool result = IsSpecialReceiverInstanceType(instance_type());
1452   DCHECK_IMPLIES(!result,
1453                  !has_named_interceptor() && !is_access_check_needed());
1454   return result;
1455 }
1456 
IsCustomElementsReceiverInstanceType(InstanceType instance_type)1457 inline bool IsCustomElementsReceiverInstanceType(InstanceType instance_type) {
1458   return instance_type <= LAST_CUSTOM_ELEMENTS_RECEIVER;
1459 }
1460 
1461 // This should be in objects/map-inl.h, but can't, because of a cyclic
1462 // dependency.
IsCustomElementsReceiverMap()1463 bool Map::IsCustomElementsReceiverMap() const {
1464   return IsCustomElementsReceiverInstanceType(instance_type());
1465 }
1466 
1467 // static
GetEmbedderFieldCount(const Map * map)1468 int JSObject::GetEmbedderFieldCount(const Map* map) {
1469   int instance_size = map->instance_size();
1470   if (instance_size == kVariableSizeSentinel) return 0;
1471   return ((instance_size - GetHeaderSize(map)) >> kPointerSizeLog2) -
1472          map->GetInObjectProperties();
1473 }
1474 
GetEmbedderFieldCount()1475 int JSObject::GetEmbedderFieldCount() const {
1476   return GetEmbedderFieldCount(map());
1477 }
1478 
GetEmbedderFieldOffset(int index)1479 int JSObject::GetEmbedderFieldOffset(int index) {
1480   DCHECK(index < GetEmbedderFieldCount() && index >= 0);
1481   return GetHeaderSize() + (kPointerSize * index);
1482 }
1483 
GetEmbedderField(int index)1484 Object* JSObject::GetEmbedderField(int index) {
1485   DCHECK(index < GetEmbedderFieldCount() && index >= 0);
1486   // Internal objects do follow immediately after the header, whereas in-object
1487   // properties are at the end of the object. Therefore there is no need
1488   // to adjust the index here.
1489   return READ_FIELD(this, GetHeaderSize() + (kPointerSize * index));
1490 }
1491 
SetEmbedderField(int index,Object * value)1492 void JSObject::SetEmbedderField(int index, Object* value) {
1493   DCHECK(index < GetEmbedderFieldCount() && index >= 0);
1494   // Internal objects do follow immediately after the header, whereas in-object
1495   // properties are at the end of the object. Therefore there is no need
1496   // to adjust the index here.
1497   int offset = GetHeaderSize() + (kPointerSize * index);
1498   WRITE_FIELD(this, offset, value);
1499   WRITE_BARRIER(GetHeap(), this, offset, value);
1500 }
1501 
SetEmbedderField(int index,Smi * value)1502 void JSObject::SetEmbedderField(int index, Smi* value) {
1503   DCHECK(index < GetEmbedderFieldCount() && index >= 0);
1504   // Internal objects do follow immediately after the header, whereas in-object
1505   // properties are at the end of the object. Therefore there is no need
1506   // to adjust the index here.
1507   int offset = GetHeaderSize() + (kPointerSize * index);
1508   WRITE_FIELD(this, offset, value);
1509 }
1510 
1511 
IsUnboxedDoubleField(FieldIndex index)1512 bool JSObject::IsUnboxedDoubleField(FieldIndex index) {
1513   if (!FLAG_unbox_double_fields) return false;
1514   return map()->IsUnboxedDoubleField(index);
1515 }
1516 
1517 // Access fast-case object properties at index. The use of these routines
1518 // is needed to correctly distinguish between properties stored in-object and
1519 // properties stored in the properties array.
RawFastPropertyAt(FieldIndex index)1520 Object* JSObject::RawFastPropertyAt(FieldIndex index) {
1521   DCHECK(!IsUnboxedDoubleField(index));
1522   if (index.is_inobject()) {
1523     return READ_FIELD(this, index.offset());
1524   } else {
1525     return property_array()->get(index.outobject_array_index());
1526   }
1527 }
1528 
1529 
RawFastDoublePropertyAt(FieldIndex index)1530 double JSObject::RawFastDoublePropertyAt(FieldIndex index) {
1531   DCHECK(IsUnboxedDoubleField(index));
1532   return READ_DOUBLE_FIELD(this, index.offset());
1533 }
1534 
RawFastDoublePropertyAsBitsAt(FieldIndex index)1535 uint64_t JSObject::RawFastDoublePropertyAsBitsAt(FieldIndex index) {
1536   DCHECK(IsUnboxedDoubleField(index));
1537   return READ_UINT64_FIELD(this, index.offset());
1538 }
1539 
RawFastPropertyAtPut(FieldIndex index,Object * value)1540 void JSObject::RawFastPropertyAtPut(FieldIndex index, Object* value) {
1541   if (index.is_inobject()) {
1542     int offset = index.offset();
1543     WRITE_FIELD(this, offset, value);
1544     WRITE_BARRIER(GetHeap(), this, offset, value);
1545   } else {
1546     property_array()->set(index.outobject_array_index(), value);
1547   }
1548 }
1549 
RawFastDoublePropertyAsBitsAtPut(FieldIndex index,uint64_t bits)1550 void JSObject::RawFastDoublePropertyAsBitsAtPut(FieldIndex index,
1551                                                 uint64_t bits) {
1552   // Double unboxing is enabled only on 64-bit platforms.
1553   DCHECK_EQ(kDoubleSize, kPointerSize);
1554   Address field_addr = FIELD_ADDR(this, index.offset());
1555   base::Relaxed_Store(reinterpret_cast<base::AtomicWord*>(field_addr),
1556                       static_cast<base::AtomicWord>(bits));
1557 }
1558 
FastPropertyAtPut(FieldIndex index,Object * value)1559 void JSObject::FastPropertyAtPut(FieldIndex index, Object* value) {
1560   if (IsUnboxedDoubleField(index)) {
1561     DCHECK(value->IsMutableHeapNumber());
1562     // Ensure that all bits of the double value are preserved.
1563     RawFastDoublePropertyAsBitsAtPut(index,
1564                                      HeapNumber::cast(value)->value_as_bits());
1565   } else {
1566     RawFastPropertyAtPut(index, value);
1567   }
1568 }
1569 
WriteToField(int descriptor,PropertyDetails details,Object * value)1570 void JSObject::WriteToField(int descriptor, PropertyDetails details,
1571                             Object* value) {
1572   DCHECK_EQ(kField, details.location());
1573   DCHECK_EQ(kData, details.kind());
1574   DisallowHeapAllocation no_gc;
1575   FieldIndex index = FieldIndex::ForDescriptor(map(), descriptor);
1576   if (details.representation().IsDouble()) {
1577     // Nothing more to be done.
1578     if (value->IsUninitialized(this->GetIsolate())) {
1579       return;
1580     }
1581     // Manipulating the signaling NaN used for the hole and uninitialized
1582     // double field sentinel in C++, e.g. with bit_cast or value()/set_value(),
1583     // will change its value on ia32 (the x87 stack is used to return values
1584     // and stores to the stack silently clear the signalling bit).
1585     uint64_t bits;
1586     if (value->IsSmi()) {
1587       bits = bit_cast<uint64_t>(static_cast<double>(Smi::ToInt(value)));
1588     } else {
1589       DCHECK(value->IsHeapNumber());
1590       bits = HeapNumber::cast(value)->value_as_bits();
1591     }
1592     if (IsUnboxedDoubleField(index)) {
1593       RawFastDoublePropertyAsBitsAtPut(index, bits);
1594     } else {
1595       HeapNumber* box = HeapNumber::cast(RawFastPropertyAt(index));
1596       DCHECK(box->IsMutableHeapNumber());
1597       box->set_value_as_bits(bits);
1598     }
1599   } else {
1600     RawFastPropertyAtPut(index, value);
1601   }
1602 }
1603 
GetInObjectPropertyOffset(int index)1604 int JSObject::GetInObjectPropertyOffset(int index) {
1605   return map()->GetInObjectPropertyOffset(index);
1606 }
1607 
1608 
InObjectPropertyAt(int index)1609 Object* JSObject::InObjectPropertyAt(int index) {
1610   int offset = GetInObjectPropertyOffset(index);
1611   return READ_FIELD(this, offset);
1612 }
1613 
1614 
InObjectPropertyAtPut(int index,Object * value,WriteBarrierMode mode)1615 Object* JSObject::InObjectPropertyAtPut(int index,
1616                                         Object* value,
1617                                         WriteBarrierMode mode) {
1618   // Adjust for the number of properties stored in the object.
1619   int offset = GetInObjectPropertyOffset(index);
1620   WRITE_FIELD(this, offset, value);
1621   CONDITIONAL_WRITE_BARRIER(GetHeap(), this, offset, value, mode);
1622   return value;
1623 }
1624 
1625 
InitializeBody(Map * map,int start_offset,Object * pre_allocated_value,Object * filler_value)1626 void JSObject::InitializeBody(Map* map, int start_offset,
1627                               Object* pre_allocated_value,
1628                               Object* filler_value) {
1629   DCHECK(!filler_value->IsHeapObject() ||
1630          !GetHeap()->InNewSpace(filler_value));
1631   DCHECK(!pre_allocated_value->IsHeapObject() ||
1632          !GetHeap()->InNewSpace(pre_allocated_value));
1633   int size = map->instance_size();
1634   int offset = start_offset;
1635   if (filler_value != pre_allocated_value) {
1636     int end_of_pre_allocated_offset =
1637         size - (map->UnusedPropertyFields() * kPointerSize);
1638     DCHECK_LE(kHeaderSize, end_of_pre_allocated_offset);
1639     while (offset < end_of_pre_allocated_offset) {
1640       WRITE_FIELD(this, offset, pre_allocated_value);
1641       offset += kPointerSize;
1642     }
1643   }
1644   while (offset < size) {
1645     WRITE_FIELD(this, offset, filler_value);
1646     offset += kPointerSize;
1647   }
1648 }
1649 
InitializeBody(int object_size)1650 void Struct::InitializeBody(int object_size) {
1651   Object* value = GetHeap()->undefined_value();
1652   for (int offset = kHeaderSize; offset < object_size; offset += kPointerSize) {
1653     WRITE_FIELD(this, offset, value);
1654   }
1655 }
1656 
ToArrayLength(uint32_t * index)1657 bool Object::ToArrayLength(uint32_t* index) const {
1658   return Object::ToUint32(index);
1659 }
1660 
ToArrayIndex(uint32_t * index)1661 bool Object::ToArrayIndex(uint32_t* index) const {
1662   return Object::ToUint32(index) && *index != kMaxUInt32;
1663 }
1664 
1665 
VerifyApiCallResultType()1666 void Object::VerifyApiCallResultType() {
1667 #if DEBUG
1668   if (IsSmi()) return;
1669   DCHECK(IsHeapObject());
1670   Isolate* isolate = HeapObject::cast(this)->GetIsolate();
1671   if (!(IsString() || IsSymbol() || IsJSReceiver() || IsHeapNumber() ||
1672         IsBigInt() || IsUndefined(isolate) || IsTrue(isolate) ||
1673         IsFalse(isolate) || IsNull(isolate))) {
1674     FATAL("API call returned invalid object");
1675   }
1676 #endif  // DEBUG
1677 }
1678 
get(int index)1679 Object* PropertyArray::get(int index) const {
1680   DCHECK_GE(index, 0);
1681   DCHECK_LE(index, this->length());
1682   return RELAXED_READ_FIELD(this, kHeaderSize + index * kPointerSize);
1683 }
1684 
set(int index,Object * value)1685 void PropertyArray::set(int index, Object* value) {
1686   DCHECK(IsPropertyArray());
1687   DCHECK_GE(index, 0);
1688   DCHECK_LT(index, this->length());
1689   int offset = kHeaderSize + index * kPointerSize;
1690   RELAXED_WRITE_FIELD(this, offset, value);
1691   WRITE_BARRIER(GetHeap(), this, offset, value);
1692 }
1693 
NumberOfCaptureRegisters()1694 int RegExpMatchInfo::NumberOfCaptureRegisters() {
1695   DCHECK_GE(length(), kLastMatchOverhead);
1696   Object* obj = get(kNumberOfCapturesIndex);
1697   return Smi::ToInt(obj);
1698 }
1699 
SetNumberOfCaptureRegisters(int value)1700 void RegExpMatchInfo::SetNumberOfCaptureRegisters(int value) {
1701   DCHECK_GE(length(), kLastMatchOverhead);
1702   set(kNumberOfCapturesIndex, Smi::FromInt(value));
1703 }
1704 
LastSubject()1705 String* RegExpMatchInfo::LastSubject() {
1706   DCHECK_GE(length(), kLastMatchOverhead);
1707   Object* obj = get(kLastSubjectIndex);
1708   return String::cast(obj);
1709 }
1710 
SetLastSubject(String * value)1711 void RegExpMatchInfo::SetLastSubject(String* value) {
1712   DCHECK_GE(length(), kLastMatchOverhead);
1713   set(kLastSubjectIndex, value);
1714 }
1715 
LastInput()1716 Object* RegExpMatchInfo::LastInput() {
1717   DCHECK_GE(length(), kLastMatchOverhead);
1718   return get(kLastInputIndex);
1719 }
1720 
SetLastInput(Object * value)1721 void RegExpMatchInfo::SetLastInput(Object* value) {
1722   DCHECK_GE(length(), kLastMatchOverhead);
1723   set(kLastInputIndex, value);
1724 }
1725 
Capture(int i)1726 int RegExpMatchInfo::Capture(int i) {
1727   DCHECK_LT(i, NumberOfCaptureRegisters());
1728   Object* obj = get(kFirstCaptureIndex + i);
1729   return Smi::ToInt(obj);
1730 }
1731 
SetCapture(int i,int value)1732 void RegExpMatchInfo::SetCapture(int i, int value) {
1733   DCHECK_LT(i, NumberOfCaptureRegisters());
1734   set(kFirstCaptureIndex + i, Smi::FromInt(value));
1735 }
1736 
GetWriteBarrierMode(const DisallowHeapAllocation & promise)1737 WriteBarrierMode HeapObject::GetWriteBarrierMode(
1738     const DisallowHeapAllocation& promise) {
1739   Heap* heap = GetHeap();
1740   if (heap->incremental_marking()->IsMarking()) return UPDATE_WRITE_BARRIER;
1741   if (heap->InNewSpace(this)) return SKIP_WRITE_BARRIER;
1742   return UPDATE_WRITE_BARRIER;
1743 }
1744 
RequiredAlignment(Map * map)1745 AllocationAlignment HeapObject::RequiredAlignment(Map* map) {
1746 #ifdef V8_HOST_ARCH_32_BIT
1747   int instance_type = map->instance_type();
1748   if (instance_type == FIXED_FLOAT64_ARRAY_TYPE ||
1749       instance_type == FIXED_DOUBLE_ARRAY_TYPE) {
1750     return kDoubleAligned;
1751   }
1752   if (instance_type == HEAP_NUMBER_TYPE) return kDoubleUnaligned;
1753 #endif  // V8_HOST_ARCH_32_BIT
1754   return kWordAligned;
1755 }
1756 
NeedsRehashing()1757 bool HeapObject::NeedsRehashing() const {
1758   switch (map()->instance_type()) {
1759     case DESCRIPTOR_ARRAY_TYPE:
1760       return DescriptorArray::cast(this)->number_of_descriptors() > 1;
1761     case TRANSITION_ARRAY_TYPE:
1762       return TransitionArray::cast(this)->number_of_entries() > 1;
1763     case HASH_TABLE_TYPE:
1764       if (IsOrderedHashMap()) {
1765         return OrderedHashMap::cast(this)->NumberOfElements() > 0;
1766       } else if (IsOrderedHashSet()) {
1767         return OrderedHashSet::cast(this)->NumberOfElements() > 0;
1768       }
1769       return true;
1770     case SMALL_ORDERED_HASH_MAP_TYPE:
1771     case SMALL_ORDERED_HASH_SET_TYPE:
1772       return true;
1773     default:
1774       return false;
1775   }
1776 }
1777 
set(int index,Object * value,WriteBarrierMode mode)1778 void PropertyArray::set(int index, Object* value, WriteBarrierMode mode) {
1779   DCHECK_GE(index, 0);
1780   DCHECK_LT(index, this->length());
1781   int offset = kHeaderSize + index * kPointerSize;
1782   RELAXED_WRITE_FIELD(this, offset, value);
1783   CONDITIONAL_WRITE_BARRIER(GetHeap(), this, offset, value, mode);
1784 }
1785 
data_start()1786 Object** PropertyArray::data_start() {
1787   return HeapObject::RawField(this, kHeaderSize);
1788 }
1789 
ACCESSORS(EnumCache,keys,FixedArray,kKeysOffset)1790 ACCESSORS(EnumCache, keys, FixedArray, kKeysOffset)
1791 ACCESSORS(EnumCache, indices, FixedArray, kIndicesOffset)
1792 
1793 int DescriptorArray::number_of_descriptors() const {
1794   return Smi::ToInt(get(kDescriptorLengthIndex));
1795 }
1796 
number_of_descriptors_storage()1797 int DescriptorArray::number_of_descriptors_storage() const {
1798   return (length() - kFirstIndex) / kEntrySize;
1799 }
1800 
NumberOfSlackDescriptors()1801 int DescriptorArray::NumberOfSlackDescriptors() const {
1802   return number_of_descriptors_storage() - number_of_descriptors();
1803 }
1804 
1805 
SetNumberOfDescriptors(int number_of_descriptors)1806 void DescriptorArray::SetNumberOfDescriptors(int number_of_descriptors) {
1807   set(kDescriptorLengthIndex, Smi::FromInt(number_of_descriptors));
1808 }
1809 
number_of_entries()1810 inline int DescriptorArray::number_of_entries() const {
1811   return number_of_descriptors();
1812 }
1813 
CopyEnumCacheFrom(DescriptorArray * array)1814 void DescriptorArray::CopyEnumCacheFrom(DescriptorArray* array) {
1815   set(kEnumCacheIndex, array->get(kEnumCacheIndex));
1816 }
1817 
GetEnumCache()1818 EnumCache* DescriptorArray::GetEnumCache() {
1819   return EnumCache::cast(get(kEnumCacheIndex));
1820 }
1821 
1822 // Perform a binary search in a fixed array.
1823 template <SearchMode search_mode, typename T>
BinarySearch(T * array,Name * name,int valid_entries,int * out_insertion_index)1824 int BinarySearch(T* array, Name* name, int valid_entries,
1825                  int* out_insertion_index) {
1826   DCHECK(search_mode == ALL_ENTRIES || out_insertion_index == nullptr);
1827   int low = 0;
1828   int high = array->number_of_entries() - 1;
1829   uint32_t hash = name->hash_field();
1830   int limit = high;
1831 
1832   DCHECK(low <= high);
1833 
1834   while (low != high) {
1835     int mid = low + (high - low) / 2;
1836     Name* mid_name = array->GetSortedKey(mid);
1837     uint32_t mid_hash = mid_name->hash_field();
1838 
1839     if (mid_hash >= hash) {
1840       high = mid;
1841     } else {
1842       low = mid + 1;
1843     }
1844   }
1845 
1846   for (; low <= limit; ++low) {
1847     int sort_index = array->GetSortedKeyIndex(low);
1848     Name* entry = array->GetKey(sort_index);
1849     uint32_t current_hash = entry->hash_field();
1850     if (current_hash != hash) {
1851       if (search_mode == ALL_ENTRIES && out_insertion_index != nullptr) {
1852         *out_insertion_index = sort_index + (current_hash > hash ? 0 : 1);
1853       }
1854       return T::kNotFound;
1855     }
1856     if (entry == name) {
1857       if (search_mode == ALL_ENTRIES || sort_index < valid_entries) {
1858         return sort_index;
1859       }
1860       return T::kNotFound;
1861     }
1862   }
1863 
1864   if (search_mode == ALL_ENTRIES && out_insertion_index != nullptr) {
1865     *out_insertion_index = limit + 1;
1866   }
1867   return T::kNotFound;
1868 }
1869 
1870 
1871 // Perform a linear search in this fixed array. len is the number of entry
1872 // indices that are valid.
1873 template <SearchMode search_mode, typename T>
LinearSearch(T * array,Name * name,int valid_entries,int * out_insertion_index)1874 int LinearSearch(T* array, Name* name, int valid_entries,
1875                  int* out_insertion_index) {
1876   if (search_mode == ALL_ENTRIES && out_insertion_index != nullptr) {
1877     uint32_t hash = name->hash_field();
1878     int len = array->number_of_entries();
1879     for (int number = 0; number < len; number++) {
1880       int sorted_index = array->GetSortedKeyIndex(number);
1881       Name* entry = array->GetKey(sorted_index);
1882       uint32_t current_hash = entry->hash_field();
1883       if (current_hash > hash) {
1884         *out_insertion_index = sorted_index;
1885         return T::kNotFound;
1886       }
1887       if (entry == name) return sorted_index;
1888     }
1889     *out_insertion_index = len;
1890     return T::kNotFound;
1891   } else {
1892     DCHECK_LE(valid_entries, array->number_of_entries());
1893     DCHECK_NULL(out_insertion_index);  // Not supported here.
1894     for (int number = 0; number < valid_entries; number++) {
1895       if (array->GetKey(number) == name) return number;
1896     }
1897     return T::kNotFound;
1898   }
1899 }
1900 
1901 
1902 template <SearchMode search_mode, typename T>
Search(T * array,Name * name,int valid_entries,int * out_insertion_index)1903 int Search(T* array, Name* name, int valid_entries, int* out_insertion_index) {
1904   SLOW_DCHECK(array->IsSortedNoDuplicates());
1905 
1906   if (valid_entries == 0) {
1907     if (search_mode == ALL_ENTRIES && out_insertion_index != nullptr) {
1908       *out_insertion_index = 0;
1909     }
1910     return T::kNotFound;
1911   }
1912 
1913   // Fast case: do linear search for small arrays.
1914   const int kMaxElementsForLinearSearch = 8;
1915   if (valid_entries <= kMaxElementsForLinearSearch) {
1916     return LinearSearch<search_mode>(array, name, valid_entries,
1917                                      out_insertion_index);
1918   }
1919 
1920   // Slow case: perform binary search.
1921   return BinarySearch<search_mode>(array, name, valid_entries,
1922                                    out_insertion_index);
1923 }
1924 
1925 
Search(Name * name,int valid_descriptors)1926 int DescriptorArray::Search(Name* name, int valid_descriptors) {
1927   DCHECK(name->IsUniqueName());
1928   return internal::Search<VALID_ENTRIES>(this, name, valid_descriptors,
1929                                          nullptr);
1930 }
1931 
SearchWithCache(Isolate * isolate,Name * name,Map * map)1932 int DescriptorArray::SearchWithCache(Isolate* isolate, Name* name, Map* map) {
1933   DCHECK(name->IsUniqueName());
1934   int number_of_own_descriptors = map->NumberOfOwnDescriptors();
1935   if (number_of_own_descriptors == 0) return kNotFound;
1936 
1937   DescriptorLookupCache* cache = isolate->descriptor_lookup_cache();
1938   int number = cache->Lookup(map, name);
1939 
1940   if (number == DescriptorLookupCache::kAbsent) {
1941     number = Search(name, number_of_own_descriptors);
1942     cache->Update(map, name, number);
1943   }
1944 
1945   return number;
1946 }
1947 
1948 
GetKeySlot(int descriptor_number)1949 Object** DescriptorArray::GetKeySlot(int descriptor_number) {
1950   DCHECK(descriptor_number < number_of_descriptors());
1951   return RawFieldOfElementAt(ToKeyIndex(descriptor_number));
1952 }
1953 
1954 
GetDescriptorStartSlot(int descriptor_number)1955 Object** DescriptorArray::GetDescriptorStartSlot(int descriptor_number) {
1956   return GetKeySlot(descriptor_number);
1957 }
1958 
1959 
GetDescriptorEndSlot(int descriptor_number)1960 Object** DescriptorArray::GetDescriptorEndSlot(int descriptor_number) {
1961   return GetValueSlot(descriptor_number - 1) + 1;
1962 }
1963 
1964 
GetKey(int descriptor_number)1965 Name* DescriptorArray::GetKey(int descriptor_number) {
1966   DCHECK(descriptor_number < number_of_descriptors());
1967   return Name::cast(get(ToKeyIndex(descriptor_number)));
1968 }
1969 
1970 
GetSortedKeyIndex(int descriptor_number)1971 int DescriptorArray::GetSortedKeyIndex(int descriptor_number) {
1972   return GetDetails(descriptor_number).pointer();
1973 }
1974 
1975 
GetSortedKey(int descriptor_number)1976 Name* DescriptorArray::GetSortedKey(int descriptor_number) {
1977   return GetKey(GetSortedKeyIndex(descriptor_number));
1978 }
1979 
1980 
SetSortedKey(int descriptor_index,int pointer)1981 void DescriptorArray::SetSortedKey(int descriptor_index, int pointer) {
1982   PropertyDetails details = GetDetails(descriptor_index);
1983   set(ToDetailsIndex(descriptor_index), details.set_pointer(pointer).AsSmi());
1984 }
1985 
1986 
GetValueSlot(int descriptor_number)1987 Object** DescriptorArray::GetValueSlot(int descriptor_number) {
1988   DCHECK(descriptor_number < number_of_descriptors());
1989   return RawFieldOfElementAt(ToValueIndex(descriptor_number));
1990 }
1991 
1992 
GetValueOffset(int descriptor_number)1993 int DescriptorArray::GetValueOffset(int descriptor_number) {
1994   return OffsetOfElementAt(ToValueIndex(descriptor_number));
1995 }
1996 
1997 
GetValue(int descriptor_number)1998 Object* DescriptorArray::GetValue(int descriptor_number) {
1999   DCHECK(descriptor_number < number_of_descriptors());
2000   return get(ToValueIndex(descriptor_number));
2001 }
2002 
2003 
SetValue(int descriptor_index,Object * value)2004 void DescriptorArray::SetValue(int descriptor_index, Object* value) {
2005   set(ToValueIndex(descriptor_index), value);
2006 }
2007 
2008 
GetDetails(int descriptor_number)2009 PropertyDetails DescriptorArray::GetDetails(int descriptor_number) {
2010   DCHECK(descriptor_number < number_of_descriptors());
2011   Object* details = get(ToDetailsIndex(descriptor_number));
2012   return PropertyDetails(Smi::cast(details));
2013 }
2014 
GetFieldIndex(int descriptor_number)2015 int DescriptorArray::GetFieldIndex(int descriptor_number) {
2016   DCHECK_EQ(GetDetails(descriptor_number).location(), kField);
2017   return GetDetails(descriptor_number).field_index();
2018 }
2019 
GetFieldType(int descriptor_number)2020 FieldType* DescriptorArray::GetFieldType(int descriptor_number) {
2021   DCHECK_EQ(GetDetails(descriptor_number).location(), kField);
2022   Object* wrapped_type = GetValue(descriptor_number);
2023   return Map::UnwrapFieldType(wrapped_type);
2024 }
2025 
Get(int descriptor_number,Descriptor * desc)2026 void DescriptorArray::Get(int descriptor_number, Descriptor* desc) {
2027   desc->Init(handle(GetKey(descriptor_number), GetIsolate()),
2028              handle(GetValue(descriptor_number), GetIsolate()),
2029              GetDetails(descriptor_number));
2030 }
2031 
Set(int descriptor_number,Name * key,Object * value,PropertyDetails details)2032 void DescriptorArray::Set(int descriptor_number, Name* key, Object* value,
2033                           PropertyDetails details) {
2034   // Range check.
2035   DCHECK(descriptor_number < number_of_descriptors());
2036   set(ToKeyIndex(descriptor_number), key);
2037   set(ToValueIndex(descriptor_number), value);
2038   set(ToDetailsIndex(descriptor_number), details.AsSmi());
2039 }
2040 
Set(int descriptor_number,Descriptor * desc)2041 void DescriptorArray::Set(int descriptor_number, Descriptor* desc) {
2042   Name* key = *desc->GetKey();
2043   Object* value = *desc->GetValue();
2044   Set(descriptor_number, key, value, desc->GetDetails());
2045 }
2046 
2047 
Append(Descriptor * desc)2048 void DescriptorArray::Append(Descriptor* desc) {
2049   DisallowHeapAllocation no_gc;
2050   int descriptor_number = number_of_descriptors();
2051   SetNumberOfDescriptors(descriptor_number + 1);
2052   Set(descriptor_number, desc);
2053 
2054   uint32_t hash = desc->GetKey()->Hash();
2055 
2056   int insertion;
2057 
2058   for (insertion = descriptor_number; insertion > 0; --insertion) {
2059     Name* key = GetSortedKey(insertion - 1);
2060     if (key->Hash() <= hash) break;
2061     SetSortedKey(insertion, GetSortedKeyIndex(insertion - 1));
2062   }
2063 
2064   SetSortedKey(insertion, descriptor_number);
2065 }
2066 
2067 
SwapSortedKeys(int first,int second)2068 void DescriptorArray::SwapSortedKeys(int first, int second) {
2069   int first_key = GetSortedKeyIndex(first);
2070   SetSortedKey(first, GetSortedKeyIndex(second));
2071   SetSortedKey(second, first_key);
2072 }
2073 
IsMatch(String * key,Object * value)2074 bool StringSetShape::IsMatch(String* key, Object* value) {
2075   DCHECK(value->IsString());
2076   return key->Equals(String::cast(value));
2077 }
2078 
Hash(Isolate * isolate,String * key)2079 uint32_t StringSetShape::Hash(Isolate* isolate, String* key) {
2080   return key->Hash();
2081 }
2082 
HashForObject(Isolate * isolate,Object * object)2083 uint32_t StringSetShape::HashForObject(Isolate* isolate, Object* object) {
2084   return String::cast(object)->Hash();
2085 }
2086 
StringTableKey(uint32_t hash_field)2087 StringTableKey::StringTableKey(uint32_t hash_field)
2088     : HashTableKey(hash_field >> Name::kHashShift), hash_field_(hash_field) {}
2089 
set_hash_field(uint32_t hash_field)2090 void StringTableKey::set_hash_field(uint32_t hash_field) {
2091   hash_field_ = hash_field;
2092   set_hash(hash_field >> Name::kHashShift);
2093 }
2094 
AsHandle(Isolate * isolate,StringTableKey * key)2095 Handle<Object> StringTableShape::AsHandle(Isolate* isolate,
2096                                           StringTableKey* key) {
2097   return key->AsHandle(isolate);
2098 }
2099 
HashForObject(Isolate * isolate,Object * object)2100 uint32_t StringTableShape::HashForObject(Isolate* isolate, Object* object) {
2101   return String::cast(object)->Hash();
2102 }
2103 
GetMapRootIndex()2104 int StringTableShape::GetMapRootIndex() {
2105   return Heap::kStringTableMapRootIndex;
2106 }
2107 
requires_slow_elements()2108 bool NumberDictionary::requires_slow_elements() {
2109   Object* max_index_object = get(kMaxNumberKeyIndex);
2110   if (!max_index_object->IsSmi()) return false;
2111   return 0 != (Smi::ToInt(max_index_object) & kRequiresSlowElementsMask);
2112 }
2113 
max_number_key()2114 uint32_t NumberDictionary::max_number_key() {
2115   DCHECK(!requires_slow_elements());
2116   Object* max_index_object = get(kMaxNumberKeyIndex);
2117   if (!max_index_object->IsSmi()) return 0;
2118   uint32_t value = static_cast<uint32_t>(Smi::ToInt(max_index_object));
2119   return value >> kRequiresSlowElementsTagSize;
2120 }
2121 
set_requires_slow_elements()2122 void NumberDictionary::set_requires_slow_elements() {
2123   set(kMaxNumberKeyIndex, Smi::FromInt(kRequiresSlowElementsMask));
2124 }
2125 
DEFINE_DEOPT_ELEMENT_ACCESSORS(TranslationByteArray,ByteArray)2126 DEFINE_DEOPT_ELEMENT_ACCESSORS(TranslationByteArray, ByteArray)
2127 DEFINE_DEOPT_ELEMENT_ACCESSORS(InlinedFunctionCount, Smi)
2128 DEFINE_DEOPT_ELEMENT_ACCESSORS(LiteralArray, FixedArray)
2129 DEFINE_DEOPT_ELEMENT_ACCESSORS(OsrBytecodeOffset, Smi)
2130 DEFINE_DEOPT_ELEMENT_ACCESSORS(OsrPcOffset, Smi)
2131 DEFINE_DEOPT_ELEMENT_ACCESSORS(OptimizationId, Smi)
2132 DEFINE_DEOPT_ELEMENT_ACCESSORS(WeakCellCache, Object)
2133 DEFINE_DEOPT_ELEMENT_ACCESSORS(InliningPositions, PodArray<InliningPosition>)
2134 
2135 DEFINE_DEOPT_ENTRY_ACCESSORS(BytecodeOffsetRaw, Smi)
2136 DEFINE_DEOPT_ENTRY_ACCESSORS(TranslationIndex, Smi)
2137 DEFINE_DEOPT_ENTRY_ACCESSORS(Pc, Smi)
2138 
2139 int PropertyArray::length() const {
2140   Object* value_obj = READ_FIELD(this, kLengthAndHashOffset);
2141   int value = Smi::ToInt(value_obj);
2142   return LengthField::decode(value);
2143 }
2144 
initialize_length(int len)2145 void PropertyArray::initialize_length(int len) {
2146   SLOW_DCHECK(len >= 0);
2147   SLOW_DCHECK(len < LengthField::kMax);
2148   WRITE_FIELD(this, kLengthAndHashOffset, Smi::FromInt(len));
2149 }
2150 
synchronized_length()2151 int PropertyArray::synchronized_length() const {
2152   Object* value_obj = ACQUIRE_READ_FIELD(this, kLengthAndHashOffset);
2153   int value = Smi::ToInt(value_obj);
2154   return LengthField::decode(value);
2155 }
2156 
Hash()2157 int PropertyArray::Hash() const {
2158   Object* value_obj = READ_FIELD(this, kLengthAndHashOffset);
2159   int value = Smi::ToInt(value_obj);
2160   return HashField::decode(value);
2161 }
2162 
SetHash(int hash)2163 void PropertyArray::SetHash(int hash) {
2164   Object* value_obj = READ_FIELD(this, kLengthAndHashOffset);
2165   int value = Smi::ToInt(value_obj);
2166   value = HashField::update(value, hash);
2167   WRITE_FIELD(this, kLengthAndHashOffset, Smi::FromInt(value));
2168 }
2169 
SMI_ACCESSORS(FreeSpace,size,kSizeOffset)2170 SMI_ACCESSORS(FreeSpace, size, kSizeOffset)
2171 RELAXED_SMI_ACCESSORS(FreeSpace, size, kSizeOffset)
2172 
2173 
2174 int FreeSpace::Size() { return size(); }
2175 
2176 
next()2177 FreeSpace* FreeSpace::next() {
2178   DCHECK(map() == GetHeap()->root(Heap::kFreeSpaceMapRootIndex) ||
2179          (!GetHeap()->deserialization_complete() && map() == nullptr));
2180   DCHECK_LE(kNextOffset + kPointerSize, relaxed_read_size());
2181   return reinterpret_cast<FreeSpace*>(
2182       Memory::Address_at(address() + kNextOffset));
2183 }
2184 
2185 
set_next(FreeSpace * next)2186 void FreeSpace::set_next(FreeSpace* next) {
2187   DCHECK(map() == GetHeap()->root(Heap::kFreeSpaceMapRootIndex) ||
2188          (!GetHeap()->deserialization_complete() && map() == nullptr));
2189   DCHECK_LE(kNextOffset + kPointerSize, relaxed_read_size());
2190   base::Relaxed_Store(
2191       reinterpret_cast<base::AtomicWord*>(address() + kNextOffset),
2192       reinterpret_cast<base::AtomicWord>(next));
2193 }
2194 
2195 
cast(HeapObject * o)2196 FreeSpace* FreeSpace::cast(HeapObject* o) {
2197   SLOW_DCHECK(!o->GetHeap()->deserialization_complete() || o->IsFreeSpace());
2198   return reinterpret_cast<FreeSpace*>(o);
2199 }
2200 
SizeFromMap(Map * map)2201 int HeapObject::SizeFromMap(Map* map) const {
2202   int instance_size = map->instance_size();
2203   if (instance_size != kVariableSizeSentinel) return instance_size;
2204   // Only inline the most frequent cases.
2205   InstanceType instance_type = map->instance_type();
2206   if (instance_type >= FIRST_FIXED_ARRAY_TYPE &&
2207       instance_type <= LAST_FIXED_ARRAY_TYPE) {
2208     return FixedArray::SizeFor(
2209         reinterpret_cast<const FixedArray*>(this)->synchronized_length());
2210   }
2211   if (instance_type == ONE_BYTE_STRING_TYPE ||
2212       instance_type == ONE_BYTE_INTERNALIZED_STRING_TYPE) {
2213     // Strings may get concurrently truncated, hence we have to access its
2214     // length synchronized.
2215     return SeqOneByteString::SizeFor(
2216         reinterpret_cast<const SeqOneByteString*>(this)->synchronized_length());
2217   }
2218   if (instance_type == BYTE_ARRAY_TYPE) {
2219     return ByteArray::SizeFor(
2220         reinterpret_cast<const ByteArray*>(this)->synchronized_length());
2221   }
2222   if (instance_type == BYTECODE_ARRAY_TYPE) {
2223     return BytecodeArray::SizeFor(
2224         reinterpret_cast<const BytecodeArray*>(this)->synchronized_length());
2225   }
2226   if (instance_type == FREE_SPACE_TYPE) {
2227     return reinterpret_cast<const FreeSpace*>(this)->relaxed_read_size();
2228   }
2229   if (instance_type == STRING_TYPE ||
2230       instance_type == INTERNALIZED_STRING_TYPE) {
2231     // Strings may get concurrently truncated, hence we have to access its
2232     // length synchronized.
2233     return SeqTwoByteString::SizeFor(
2234         reinterpret_cast<const SeqTwoByteString*>(this)->synchronized_length());
2235   }
2236   if (instance_type == FIXED_DOUBLE_ARRAY_TYPE) {
2237     return FixedDoubleArray::SizeFor(
2238         reinterpret_cast<const FixedDoubleArray*>(this)->synchronized_length());
2239   }
2240   if (instance_type == FEEDBACK_METADATA_TYPE) {
2241     return FeedbackMetadata::SizeFor(
2242         reinterpret_cast<const FeedbackMetadata*>(this)
2243             ->synchronized_slot_count());
2244   }
2245   if (instance_type >= FIRST_WEAK_FIXED_ARRAY_TYPE &&
2246       instance_type <= LAST_WEAK_FIXED_ARRAY_TYPE) {
2247     return WeakFixedArray::SizeFor(
2248         reinterpret_cast<const WeakFixedArray*>(this)->synchronized_length());
2249   }
2250   if (instance_type == WEAK_ARRAY_LIST_TYPE) {
2251     return WeakArrayList::SizeForCapacity(
2252         reinterpret_cast<const WeakArrayList*>(this)->synchronized_capacity());
2253   }
2254   if (instance_type >= FIRST_FIXED_TYPED_ARRAY_TYPE &&
2255       instance_type <= LAST_FIXED_TYPED_ARRAY_TYPE) {
2256     return reinterpret_cast<const FixedTypedArrayBase*>(this)->TypedArraySize(
2257         instance_type);
2258   }
2259   if (instance_type == SMALL_ORDERED_HASH_SET_TYPE) {
2260     return SmallOrderedHashSet::SizeFor(
2261         reinterpret_cast<const SmallOrderedHashSet*>(this)->Capacity());
2262   }
2263   if (instance_type == PROPERTY_ARRAY_TYPE) {
2264     return PropertyArray::SizeFor(
2265         reinterpret_cast<const PropertyArray*>(this)->synchronized_length());
2266   }
2267   if (instance_type == SMALL_ORDERED_HASH_MAP_TYPE) {
2268     return SmallOrderedHashMap::SizeFor(
2269         reinterpret_cast<const SmallOrderedHashMap*>(this)->Capacity());
2270   }
2271   if (instance_type == FEEDBACK_VECTOR_TYPE) {
2272     return FeedbackVector::SizeFor(
2273         reinterpret_cast<const FeedbackVector*>(this)->length());
2274   }
2275   if (instance_type == BIGINT_TYPE) {
2276     return BigInt::SizeFor(reinterpret_cast<const BigInt*>(this)->length());
2277   }
2278   DCHECK(instance_type == CODE_TYPE);
2279   return reinterpret_cast<const Code*>(this)->CodeSize();
2280 }
2281 
raw_bound_target_function()2282 Object* JSBoundFunction::raw_bound_target_function() const {
2283   return READ_FIELD(this, kBoundTargetFunctionOffset);
2284 }
2285 
ACCESSORS(JSBoundFunction,bound_target_function,JSReceiver,kBoundTargetFunctionOffset)2286 ACCESSORS(JSBoundFunction, bound_target_function, JSReceiver,
2287           kBoundTargetFunctionOffset)
2288 ACCESSORS(JSBoundFunction, bound_this, Object, kBoundThisOffset)
2289 ACCESSORS(JSBoundFunction, bound_arguments, FixedArray, kBoundArgumentsOffset)
2290 
2291 ACCESSORS(JSFunction, shared, SharedFunctionInfo, kSharedFunctionInfoOffset)
2292 ACCESSORS(JSFunction, feedback_cell, FeedbackCell, kFeedbackCellOffset)
2293 
2294 ACCESSORS(JSGlobalObject, native_context, Context, kNativeContextOffset)
2295 ACCESSORS(JSGlobalObject, global_proxy, JSObject, kGlobalProxyOffset)
2296 
2297 ACCESSORS(JSGlobalProxy, native_context, Object, kNativeContextOffset)
2298 
2299 ACCESSORS(AsyncGeneratorRequest, next, Object, kNextOffset)
2300 SMI_ACCESSORS(AsyncGeneratorRequest, resume_mode, kResumeModeOffset)
2301 ACCESSORS(AsyncGeneratorRequest, value, Object, kValueOffset)
2302 ACCESSORS(AsyncGeneratorRequest, promise, Object, kPromiseOffset)
2303 
2304 Map* PrototypeInfo::ObjectCreateMap() {
2305   return Map::cast(WeakCell::cast(object_create_map())->value());
2306 }
2307 
2308 // static
SetObjectCreateMap(Handle<PrototypeInfo> info,Handle<Map> map)2309 void PrototypeInfo::SetObjectCreateMap(Handle<PrototypeInfo> info,
2310                                        Handle<Map> map) {
2311   Handle<WeakCell> cell = Map::WeakCellForMap(map);
2312   info->set_object_create_map(*cell);
2313 }
2314 
HasObjectCreateMap()2315 bool PrototypeInfo::HasObjectCreateMap() {
2316   Object* cache = object_create_map();
2317   return cache->IsWeakCell() && !WeakCell::cast(cache)->cleared();
2318 }
2319 
ACCESSORS(PrototypeInfo,weak_cell,Object,kWeakCellOffset)2320 ACCESSORS(PrototypeInfo, weak_cell, Object, kWeakCellOffset)
2321 ACCESSORS(PrototypeInfo, prototype_users, Object, kPrototypeUsersOffset)
2322 ACCESSORS(PrototypeInfo, object_create_map, Object, kObjectCreateMap)
2323 SMI_ACCESSORS(PrototypeInfo, registry_slot, kRegistrySlotOffset)
2324 SMI_ACCESSORS(PrototypeInfo, bit_field, kBitFieldOffset)
2325 BOOL_ACCESSORS(PrototypeInfo, bit_field, should_be_fast_map, kShouldBeFastBit)
2326 
2327 ACCESSORS(Tuple2, value1, Object, kValue1Offset)
2328 ACCESSORS(Tuple2, value2, Object, kValue2Offset)
2329 ACCESSORS(Tuple3, value3, Object, kValue3Offset)
2330 
2331 SMI_ACCESSORS(ConstantElementsPair, elements_kind, kElementsKindOffset)
2332 ACCESSORS(ConstantElementsPair, constant_values, FixedArrayBase,
2333           kConstantValuesOffset)
2334 bool ConstantElementsPair::is_empty() const {
2335   return constant_values()->length() == 0;
2336 }
2337 
ACCESSORS(TemplateObjectDescription,raw_strings,FixedArray,kRawStringsOffset)2338 ACCESSORS(TemplateObjectDescription, raw_strings, FixedArray, kRawStringsOffset)
2339 ACCESSORS(TemplateObjectDescription, cooked_strings, FixedArray,
2340           kCookedStringsOffset)
2341 
2342 ACCESSORS(AccessorPair, getter, Object, kGetterOffset)
2343 ACCESSORS(AccessorPair, setter, Object, kSetterOffset)
2344 
2345 ACCESSORS(AllocationSite, transition_info_or_boilerplate, Object,
2346           kTransitionInfoOrBoilerplateOffset)
2347 
2348 JSObject* AllocationSite::boilerplate() const {
2349   DCHECK(PointsToLiteral());
2350   return JSObject::cast(transition_info_or_boilerplate());
2351 }
2352 
set_boilerplate(JSObject * object,WriteBarrierMode mode)2353 void AllocationSite::set_boilerplate(JSObject* object, WriteBarrierMode mode) {
2354   set_transition_info_or_boilerplate(object, mode);
2355 }
2356 
transition_info()2357 int AllocationSite::transition_info() const {
2358   DCHECK(!PointsToLiteral());
2359   return Smi::cast(transition_info_or_boilerplate())->value();
2360 }
2361 
set_transition_info(int value)2362 void AllocationSite::set_transition_info(int value) {
2363   DCHECK(!PointsToLiteral());
2364   set_transition_info_or_boilerplate(Smi::FromInt(value), SKIP_WRITE_BARRIER);
2365 }
2366 
ACCESSORS(AllocationSite,nested_site,Object,kNestedSiteOffset)2367 ACCESSORS(AllocationSite, nested_site, Object, kNestedSiteOffset)
2368 SMI_ACCESSORS(AllocationSite, pretenure_data, kPretenureDataOffset)
2369 SMI_ACCESSORS(AllocationSite, pretenure_create_count,
2370               kPretenureCreateCountOffset)
2371 ACCESSORS(AllocationSite, dependent_code, DependentCode,
2372           kDependentCodeOffset)
2373 ACCESSORS(AllocationSite, weak_next, Object, kWeakNextOffset)
2374 ACCESSORS(AllocationMemento, allocation_site, Object, kAllocationSiteOffset)
2375 
2376 SMI_ACCESSORS(StackFrameInfo, line_number, kLineNumberIndex)
2377 SMI_ACCESSORS(StackFrameInfo, column_number, kColumnNumberIndex)
2378 SMI_ACCESSORS(StackFrameInfo, script_id, kScriptIdIndex)
2379 ACCESSORS(StackFrameInfo, script_name, Object, kScriptNameIndex)
2380 ACCESSORS(StackFrameInfo, script_name_or_source_url, Object,
2381           kScriptNameOrSourceUrlIndex)
2382 ACCESSORS(StackFrameInfo, function_name, Object, kFunctionNameIndex)
2383 SMI_ACCESSORS(StackFrameInfo, flag, kFlagIndex)
2384 BOOL_ACCESSORS(StackFrameInfo, flag, is_eval, kIsEvalBit)
2385 BOOL_ACCESSORS(StackFrameInfo, flag, is_constructor, kIsConstructorBit)
2386 BOOL_ACCESSORS(StackFrameInfo, flag, is_wasm, kIsWasmBit)
2387 SMI_ACCESSORS(StackFrameInfo, id, kIdIndex)
2388 
2389 ACCESSORS(SourcePositionTableWithFrameCache, source_position_table, ByteArray,
2390           kSourcePositionTableIndex)
2391 ACCESSORS(SourcePositionTableWithFrameCache, stack_frame_cache,
2392           SimpleNumberDictionary, kStackFrameCacheIndex)
2393 
2394 
2395 FeedbackVector* JSFunction::feedback_vector() const {
2396   DCHECK(has_feedback_vector());
2397   return FeedbackVector::cast(feedback_cell()->value());
2398 }
2399 
2400 // Code objects that are marked for deoptimization are not considered to be
2401 // optimized. This is because the JSFunction might have been already
2402 // deoptimized but its code() still needs to be unlinked, which will happen on
2403 // its next activation.
2404 // TODO(jupvfranco): rename this function. Maybe RunOptimizedCode,
2405 // or IsValidOptimizedCode.
IsOptimized()2406 bool JSFunction::IsOptimized() {
2407   return code()->kind() == Code::OPTIMIZED_FUNCTION &&
2408          !code()->marked_for_deoptimization();
2409 }
2410 
HasOptimizedCode()2411 bool JSFunction::HasOptimizedCode() {
2412   return IsOptimized() ||
2413          (has_feedback_vector() && feedback_vector()->has_optimized_code() &&
2414           !feedback_vector()->optimized_code()->marked_for_deoptimization());
2415 }
2416 
HasOptimizationMarker()2417 bool JSFunction::HasOptimizationMarker() {
2418   return has_feedback_vector() && feedback_vector()->has_optimization_marker();
2419 }
2420 
ClearOptimizationMarker()2421 void JSFunction::ClearOptimizationMarker() {
2422   DCHECK(has_feedback_vector());
2423   feedback_vector()->ClearOptimizationMarker();
2424 }
2425 
2426 // Optimized code marked for deoptimization will tier back down to running
2427 // interpreted on its next activation, and already doesn't count as IsOptimized.
IsInterpreted()2428 bool JSFunction::IsInterpreted() {
2429   return code()->is_interpreter_trampoline_builtin() ||
2430          (code()->kind() == Code::OPTIMIZED_FUNCTION &&
2431           code()->marked_for_deoptimization());
2432 }
2433 
ChecksOptimizationMarker()2434 bool JSFunction::ChecksOptimizationMarker() {
2435   return code()->checks_optimization_marker();
2436 }
2437 
IsMarkedForOptimization()2438 bool JSFunction::IsMarkedForOptimization() {
2439   return has_feedback_vector() && feedback_vector()->optimization_marker() ==
2440                                       OptimizationMarker::kCompileOptimized;
2441 }
2442 
2443 
IsMarkedForConcurrentOptimization()2444 bool JSFunction::IsMarkedForConcurrentOptimization() {
2445   return has_feedback_vector() &&
2446          feedback_vector()->optimization_marker() ==
2447              OptimizationMarker::kCompileOptimizedConcurrent;
2448 }
2449 
2450 
IsInOptimizationQueue()2451 bool JSFunction::IsInOptimizationQueue() {
2452   return has_feedback_vector() && feedback_vector()->optimization_marker() ==
2453                                       OptimizationMarker::kInOptimizationQueue;
2454 }
2455 
2456 
CompleteInobjectSlackTrackingIfActive()2457 void JSFunction::CompleteInobjectSlackTrackingIfActive() {
2458   if (!has_prototype_slot()) return;
2459   if (has_initial_map() && initial_map()->IsInobjectSlackTrackingInProgress()) {
2460     initial_map()->CompleteInobjectSlackTracking();
2461   }
2462 }
2463 
abstract_code()2464 AbstractCode* JSFunction::abstract_code() {
2465   if (IsInterpreted()) {
2466     return AbstractCode::cast(shared()->GetBytecodeArray());
2467   } else {
2468     return AbstractCode::cast(code());
2469   }
2470 }
2471 
code()2472 Code* JSFunction::code() { return Code::cast(READ_FIELD(this, kCodeOffset)); }
2473 
set_code(Code * value)2474 void JSFunction::set_code(Code* value) {
2475   DCHECK(!GetHeap()->InNewSpace(value));
2476   WRITE_FIELD(this, kCodeOffset, value);
2477   GetHeap()->incremental_marking()->RecordWrite(
2478       this, HeapObject::RawField(this, kCodeOffset), value);
2479 }
2480 
2481 
set_code_no_write_barrier(Code * value)2482 void JSFunction::set_code_no_write_barrier(Code* value) {
2483   DCHECK(!GetHeap()->InNewSpace(value));
2484   WRITE_FIELD(this, kCodeOffset, value);
2485 }
2486 
ClearOptimizedCodeSlot(const char * reason)2487 void JSFunction::ClearOptimizedCodeSlot(const char* reason) {
2488   if (has_feedback_vector() && feedback_vector()->has_optimized_code()) {
2489     if (FLAG_trace_opt) {
2490       PrintF("[evicting entry from optimizing code feedback slot (%s) for ",
2491              reason);
2492       ShortPrint();
2493       PrintF("]\n");
2494     }
2495     feedback_vector()->ClearOptimizedCode();
2496   }
2497 }
2498 
SetOptimizationMarker(OptimizationMarker marker)2499 void JSFunction::SetOptimizationMarker(OptimizationMarker marker) {
2500   DCHECK(has_feedback_vector());
2501   DCHECK(ChecksOptimizationMarker());
2502   DCHECK(!HasOptimizedCode());
2503 
2504   feedback_vector()->SetOptimizationMarker(marker);
2505 }
2506 
has_feedback_vector()2507 bool JSFunction::has_feedback_vector() const {
2508   return !feedback_cell()->value()->IsUndefined(GetIsolate());
2509 }
2510 
context()2511 Context* JSFunction::context() {
2512   return Context::cast(READ_FIELD(this, kContextOffset));
2513 }
2514 
has_context()2515 bool JSFunction::has_context() const {
2516   return READ_FIELD(this, kContextOffset)->IsContext();
2517 }
2518 
global_proxy()2519 JSObject* JSFunction::global_proxy() {
2520   return context()->global_proxy();
2521 }
2522 
2523 
native_context()2524 Context* JSFunction::native_context() { return context()->native_context(); }
2525 
2526 
set_context(Object * value)2527 void JSFunction::set_context(Object* value) {
2528   DCHECK(value->IsUndefined(GetIsolate()) || value->IsContext());
2529   WRITE_FIELD(this, kContextOffset, value);
2530   WRITE_BARRIER(GetHeap(), this, kContextOffset, value);
2531 }
2532 
2533 ACCESSORS_CHECKED(JSFunction, prototype_or_initial_map, Object,
2534                   kPrototypeOrInitialMapOffset, map()->has_prototype_slot())
2535 
has_prototype_slot()2536 bool JSFunction::has_prototype_slot() const {
2537   return map()->has_prototype_slot();
2538 }
2539 
initial_map()2540 Map* JSFunction::initial_map() {
2541   return Map::cast(prototype_or_initial_map());
2542 }
2543 
2544 
has_initial_map()2545 bool JSFunction::has_initial_map() {
2546   DCHECK(has_prototype_slot());
2547   return prototype_or_initial_map()->IsMap();
2548 }
2549 
2550 
has_instance_prototype()2551 bool JSFunction::has_instance_prototype() {
2552   DCHECK(has_prototype_slot());
2553   return has_initial_map() ||
2554          !prototype_or_initial_map()->IsTheHole(GetIsolate());
2555 }
2556 
2557 
has_prototype()2558 bool JSFunction::has_prototype() {
2559   DCHECK(has_prototype_slot());
2560   return map()->has_non_instance_prototype() || has_instance_prototype();
2561 }
2562 
2563 
instance_prototype()2564 Object* JSFunction::instance_prototype() {
2565   DCHECK(has_instance_prototype());
2566   if (has_initial_map()) return initial_map()->prototype();
2567   // When there is no initial map and the prototype is a JSObject, the
2568   // initial map field is used for the prototype field.
2569   return prototype_or_initial_map();
2570 }
2571 
2572 
prototype()2573 Object* JSFunction::prototype() {
2574   DCHECK(has_prototype());
2575   // If the function's prototype property has been set to a non-JSObject
2576   // value, that value is stored in the constructor field of the map.
2577   if (map()->has_non_instance_prototype()) {
2578     Object* prototype = map()->GetConstructor();
2579     // The map must have a prototype in that field, not a back pointer.
2580     DCHECK(!prototype->IsMap());
2581     DCHECK(!prototype->IsFunctionTemplateInfo());
2582     return prototype;
2583   }
2584   return instance_prototype();
2585 }
2586 
2587 
is_compiled()2588 bool JSFunction::is_compiled() {
2589   return code()->builtin_index() != Builtins::kCompileLazy;
2590 }
2591 
ACCESSORS(JSProxy,target,Object,kTargetOffset)2592 ACCESSORS(JSProxy, target, Object, kTargetOffset)
2593 ACCESSORS(JSProxy, handler, Object, kHandlerOffset)
2594 
2595 bool JSProxy::IsRevoked() const { return !handler()->IsJSReceiver(); }
2596 
2597 // static
IsNormalized(Object * value)2598 bool Foreign::IsNormalized(Object* value) {
2599   if (value == Smi::kZero) return true;
2600   return Foreign::cast(value)->foreign_address() != kNullAddress;
2601 }
2602 
foreign_address()2603 Address Foreign::foreign_address() {
2604   return AddressFrom<Address>(READ_INTPTR_FIELD(this, kForeignAddressOffset));
2605 }
2606 
set_foreign_address(Address value)2607 void Foreign::set_foreign_address(Address value) {
2608   WRITE_INTPTR_FIELD(this, kForeignAddressOffset, OffsetFrom(value));
2609 }
2610 
2611 template <class Derived>
SetDataEntry(int entry,int relative_index,Object * value)2612 void SmallOrderedHashTable<Derived>::SetDataEntry(int entry, int relative_index,
2613                                                   Object* value) {
2614   Address entry_offset =
2615       kHeaderSize + GetDataEntryOffset(entry, relative_index);
2616   RELAXED_WRITE_FIELD(this, entry_offset, value);
2617   WRITE_BARRIER(GetHeap(), this, static_cast<int>(entry_offset), value);
2618 }
2619 
ACCESSORS(JSGeneratorObject,function,JSFunction,kFunctionOffset)2620 ACCESSORS(JSGeneratorObject, function, JSFunction, kFunctionOffset)
2621 ACCESSORS(JSGeneratorObject, context, Context, kContextOffset)
2622 ACCESSORS(JSGeneratorObject, receiver, Object, kReceiverOffset)
2623 ACCESSORS(JSGeneratorObject, input_or_debug_pos, Object, kInputOrDebugPosOffset)
2624 SMI_ACCESSORS(JSGeneratorObject, resume_mode, kResumeModeOffset)
2625 SMI_ACCESSORS(JSGeneratorObject, continuation, kContinuationOffset)
2626 ACCESSORS(JSGeneratorObject, register_file, FixedArray, kRegisterFileOffset)
2627 
2628 bool JSGeneratorObject::is_suspended() const {
2629   DCHECK_LT(kGeneratorExecuting, 0);
2630   DCHECK_LT(kGeneratorClosed, 0);
2631   return continuation() >= 0;
2632 }
2633 
is_closed()2634 bool JSGeneratorObject::is_closed() const {
2635   return continuation() == kGeneratorClosed;
2636 }
2637 
is_executing()2638 bool JSGeneratorObject::is_executing() const {
2639   return continuation() == kGeneratorExecuting;
2640 }
2641 
ACCESSORS(JSAsyncGeneratorObject,queue,HeapObject,kQueueOffset)2642 ACCESSORS(JSAsyncGeneratorObject, queue, HeapObject, kQueueOffset)
2643 SMI_ACCESSORS(JSAsyncGeneratorObject, is_awaiting, kIsAwaitingOffset)
2644 
2645 ACCESSORS(JSValue, value, Object, kValueOffset)
2646 
2647 
2648 HeapNumber* HeapNumber::cast(Object* object) {
2649   SLOW_DCHECK(object->IsHeapNumber() || object->IsMutableHeapNumber());
2650   return reinterpret_cast<HeapNumber*>(object);
2651 }
2652 
2653 
cast(const Object * object)2654 const HeapNumber* HeapNumber::cast(const Object* object) {
2655   SLOW_DCHECK(object->IsHeapNumber() || object->IsMutableHeapNumber());
2656   return reinterpret_cast<const HeapNumber*>(object);
2657 }
2658 
2659 
ACCESSORS(JSDate,value,Object,kValueOffset)2660 ACCESSORS(JSDate, value, Object, kValueOffset)
2661 ACCESSORS(JSDate, cache_stamp, Object, kCacheStampOffset)
2662 ACCESSORS(JSDate, year, Object, kYearOffset)
2663 ACCESSORS(JSDate, month, Object, kMonthOffset)
2664 ACCESSORS(JSDate, day, Object, kDayOffset)
2665 ACCESSORS(JSDate, weekday, Object, kWeekdayOffset)
2666 ACCESSORS(JSDate, hour, Object, kHourOffset)
2667 ACCESSORS(JSDate, min, Object, kMinOffset)
2668 ACCESSORS(JSDate, sec, Object, kSecOffset)
2669 
2670 
2671 SMI_ACCESSORS(JSMessageObject, type, kTypeOffset)
2672 ACCESSORS(JSMessageObject, argument, Object, kArgumentsOffset)
2673 ACCESSORS(JSMessageObject, script, Object, kScriptOffset)
2674 ACCESSORS(JSMessageObject, stack_frames, Object, kStackFramesOffset)
2675 SMI_ACCESSORS(JSMessageObject, start_position, kStartPositionOffset)
2676 SMI_ACCESSORS(JSMessageObject, end_position, kEndPositionOffset)
2677 SMI_ACCESSORS(JSMessageObject, error_level, kErrorLevelOffset)
2678 
2679 ElementsKind JSObject::GetElementsKind() {
2680   ElementsKind kind = map()->elements_kind();
2681 #if VERIFY_HEAP && DEBUG
2682   FixedArrayBase* fixed_array =
2683       reinterpret_cast<FixedArrayBase*>(READ_FIELD(this, kElementsOffset));
2684 
2685   // If a GC was caused while constructing this object, the elements
2686   // pointer may point to a one pointer filler map.
2687   if (ElementsAreSafeToExamine()) {
2688     Map* map = fixed_array->map();
2689     if (IsSmiOrObjectElementsKind(kind)) {
2690       DCHECK(map == GetHeap()->fixed_array_map() ||
2691              map == GetHeap()->fixed_cow_array_map());
2692     } else if (IsDoubleElementsKind(kind)) {
2693       DCHECK(fixed_array->IsFixedDoubleArray() ||
2694              fixed_array == GetHeap()->empty_fixed_array());
2695     } else if (kind == DICTIONARY_ELEMENTS) {
2696       DCHECK(fixed_array->IsFixedArray());
2697       DCHECK(fixed_array->IsDictionary());
2698     } else {
2699       DCHECK(kind > DICTIONARY_ELEMENTS);
2700     }
2701     DCHECK(!IsSloppyArgumentsElementsKind(kind) ||
2702            (elements()->IsFixedArray() && elements()->length() >= 2));
2703   }
2704 #endif
2705   return kind;
2706 }
2707 
HasObjectElements()2708 bool JSObject::HasObjectElements() {
2709   return IsObjectElementsKind(GetElementsKind());
2710 }
2711 
HasSmiElements()2712 bool JSObject::HasSmiElements() { return IsSmiElementsKind(GetElementsKind()); }
2713 
HasSmiOrObjectElements()2714 bool JSObject::HasSmiOrObjectElements() {
2715   return IsSmiOrObjectElementsKind(GetElementsKind());
2716 }
2717 
HasDoubleElements()2718 bool JSObject::HasDoubleElements() {
2719   return IsDoubleElementsKind(GetElementsKind());
2720 }
2721 
HasHoleyElements()2722 bool JSObject::HasHoleyElements() {
2723   return IsHoleyElementsKind(GetElementsKind());
2724 }
2725 
2726 
HasFastElements()2727 bool JSObject::HasFastElements() {
2728   return IsFastElementsKind(GetElementsKind());
2729 }
2730 
HasFastPackedElements()2731 bool JSObject::HasFastPackedElements() {
2732   return IsFastPackedElementsKind(GetElementsKind());
2733 }
2734 
HasDictionaryElements()2735 bool JSObject::HasDictionaryElements() {
2736   return GetElementsKind() == DICTIONARY_ELEMENTS;
2737 }
2738 
2739 
HasFastArgumentsElements()2740 bool JSObject::HasFastArgumentsElements() {
2741   return GetElementsKind() == FAST_SLOPPY_ARGUMENTS_ELEMENTS;
2742 }
2743 
2744 
HasSlowArgumentsElements()2745 bool JSObject::HasSlowArgumentsElements() {
2746   return GetElementsKind() == SLOW_SLOPPY_ARGUMENTS_ELEMENTS;
2747 }
2748 
2749 
HasSloppyArgumentsElements()2750 bool JSObject::HasSloppyArgumentsElements() {
2751   return IsSloppyArgumentsElementsKind(GetElementsKind());
2752 }
2753 
HasStringWrapperElements()2754 bool JSObject::HasStringWrapperElements() {
2755   return IsStringWrapperElementsKind(GetElementsKind());
2756 }
2757 
HasFastStringWrapperElements()2758 bool JSObject::HasFastStringWrapperElements() {
2759   return GetElementsKind() == FAST_STRING_WRAPPER_ELEMENTS;
2760 }
2761 
HasSlowStringWrapperElements()2762 bool JSObject::HasSlowStringWrapperElements() {
2763   return GetElementsKind() == SLOW_STRING_WRAPPER_ELEMENTS;
2764 }
2765 
HasFixedTypedArrayElements()2766 bool JSObject::HasFixedTypedArrayElements() {
2767   DCHECK_NOT_NULL(elements());
2768   return map()->has_fixed_typed_array_elements();
2769 }
2770 
2771 #define FIXED_TYPED_ELEMENTS_CHECK(Type, type, TYPE, ctype, size)      \
2772   bool JSObject::HasFixed##Type##Elements() {                          \
2773     HeapObject* array = elements();                                    \
2774     DCHECK_NOT_NULL(array);                                            \
2775     if (!array->IsHeapObject()) return false;                          \
2776     return array->map()->instance_type() == FIXED_##TYPE##_ARRAY_TYPE; \
2777   }
2778 
TYPED_ARRAYS(FIXED_TYPED_ELEMENTS_CHECK)2779 TYPED_ARRAYS(FIXED_TYPED_ELEMENTS_CHECK)
2780 
2781 #undef FIXED_TYPED_ELEMENTS_CHECK
2782 
2783 
2784 bool JSObject::HasNamedInterceptor() {
2785   return map()->has_named_interceptor();
2786 }
2787 
2788 
HasIndexedInterceptor()2789 bool JSObject::HasIndexedInterceptor() {
2790   return map()->has_indexed_interceptor();
2791 }
2792 
set_global_dictionary(GlobalDictionary * dictionary)2793 void JSGlobalObject::set_global_dictionary(GlobalDictionary* dictionary) {
2794   DCHECK(IsJSGlobalObject());
2795   set_raw_properties_or_hash(dictionary);
2796 }
2797 
global_dictionary()2798 GlobalDictionary* JSGlobalObject::global_dictionary() {
2799   DCHECK(!HasFastProperties());
2800   DCHECK(IsJSGlobalObject());
2801   return GlobalDictionary::cast(raw_properties_or_hash());
2802 }
2803 
element_dictionary()2804 NumberDictionary* JSObject::element_dictionary() {
2805   DCHECK(HasDictionaryElements() || HasSlowStringWrapperElements());
2806   return NumberDictionary::cast(elements());
2807 }
2808 
2809 // static
GreaterThan(Handle<Object> x,Handle<Object> y)2810 Maybe<bool> Object::GreaterThan(Handle<Object> x, Handle<Object> y) {
2811   Maybe<ComparisonResult> result = Compare(x, y);
2812   if (result.IsJust()) {
2813     switch (result.FromJust()) {
2814       case ComparisonResult::kGreaterThan:
2815         return Just(true);
2816       case ComparisonResult::kLessThan:
2817       case ComparisonResult::kEqual:
2818       case ComparisonResult::kUndefined:
2819         return Just(false);
2820     }
2821   }
2822   return Nothing<bool>();
2823 }
2824 
2825 
2826 // static
GreaterThanOrEqual(Handle<Object> x,Handle<Object> y)2827 Maybe<bool> Object::GreaterThanOrEqual(Handle<Object> x, Handle<Object> y) {
2828   Maybe<ComparisonResult> result = Compare(x, y);
2829   if (result.IsJust()) {
2830     switch (result.FromJust()) {
2831       case ComparisonResult::kEqual:
2832       case ComparisonResult::kGreaterThan:
2833         return Just(true);
2834       case ComparisonResult::kLessThan:
2835       case ComparisonResult::kUndefined:
2836         return Just(false);
2837     }
2838   }
2839   return Nothing<bool>();
2840 }
2841 
2842 
2843 // static
LessThan(Handle<Object> x,Handle<Object> y)2844 Maybe<bool> Object::LessThan(Handle<Object> x, Handle<Object> y) {
2845   Maybe<ComparisonResult> result = Compare(x, y);
2846   if (result.IsJust()) {
2847     switch (result.FromJust()) {
2848       case ComparisonResult::kLessThan:
2849         return Just(true);
2850       case ComparisonResult::kEqual:
2851       case ComparisonResult::kGreaterThan:
2852       case ComparisonResult::kUndefined:
2853         return Just(false);
2854     }
2855   }
2856   return Nothing<bool>();
2857 }
2858 
2859 
2860 // static
LessThanOrEqual(Handle<Object> x,Handle<Object> y)2861 Maybe<bool> Object::LessThanOrEqual(Handle<Object> x, Handle<Object> y) {
2862   Maybe<ComparisonResult> result = Compare(x, y);
2863   if (result.IsJust()) {
2864     switch (result.FromJust()) {
2865       case ComparisonResult::kEqual:
2866       case ComparisonResult::kLessThan:
2867         return Just(true);
2868       case ComparisonResult::kGreaterThan:
2869       case ComparisonResult::kUndefined:
2870         return Just(false);
2871     }
2872   }
2873   return Nothing<bool>();
2874 }
2875 
GetPropertyOrElement(Handle<Object> object,Handle<Name> name)2876 MaybeHandle<Object> Object::GetPropertyOrElement(Handle<Object> object,
2877                                                  Handle<Name> name) {
2878   LookupIterator it =
2879       LookupIterator::PropertyOrElement(name->GetIsolate(), object, name);
2880   return GetProperty(&it);
2881 }
2882 
SetPropertyOrElement(Handle<Object> object,Handle<Name> name,Handle<Object> value,LanguageMode language_mode,StoreFromKeyed store_mode)2883 MaybeHandle<Object> Object::SetPropertyOrElement(Handle<Object> object,
2884                                                  Handle<Name> name,
2885                                                  Handle<Object> value,
2886                                                  LanguageMode language_mode,
2887                                                  StoreFromKeyed store_mode) {
2888   LookupIterator it =
2889       LookupIterator::PropertyOrElement(name->GetIsolate(), object, name);
2890   MAYBE_RETURN_NULL(SetProperty(&it, value, language_mode, store_mode));
2891   return value;
2892 }
2893 
GetPropertyOrElement(Handle<Object> receiver,Handle<Name> name,Handle<JSReceiver> holder)2894 MaybeHandle<Object> Object::GetPropertyOrElement(Handle<Object> receiver,
2895                                                  Handle<Name> name,
2896                                                  Handle<JSReceiver> holder) {
2897   LookupIterator it = LookupIterator::PropertyOrElement(
2898       name->GetIsolate(), receiver, name, holder);
2899   return GetProperty(&it);
2900 }
2901 
2902 
initialize_properties()2903 void JSReceiver::initialize_properties() {
2904   DCHECK(!GetHeap()->InNewSpace(GetHeap()->empty_fixed_array()));
2905   DCHECK(!GetHeap()->InNewSpace(GetHeap()->empty_property_dictionary()));
2906   if (map()->is_dictionary_map()) {
2907     WRITE_FIELD(this, kPropertiesOrHashOffset,
2908                 GetHeap()->empty_property_dictionary());
2909   } else {
2910     WRITE_FIELD(this, kPropertiesOrHashOffset, GetHeap()->empty_fixed_array());
2911   }
2912 }
2913 
HasFastProperties()2914 bool JSReceiver::HasFastProperties() const {
2915   DCHECK(
2916       raw_properties_or_hash()->IsSmi() ||
2917       (raw_properties_or_hash()->IsDictionary() == map()->is_dictionary_map()));
2918   return !map()->is_dictionary_map();
2919 }
2920 
property_dictionary()2921 NameDictionary* JSReceiver::property_dictionary() const {
2922   DCHECK(!IsJSGlobalObject());
2923   DCHECK(!HasFastProperties());
2924 
2925   Object* prop = raw_properties_or_hash();
2926   if (prop->IsSmi()) {
2927     return GetHeap()->empty_property_dictionary();
2928   }
2929 
2930   return NameDictionary::cast(prop);
2931 }
2932 
2933 // TODO(gsathya): Pass isolate directly to this function and access
2934 // the heap from this.
property_array()2935 PropertyArray* JSReceiver::property_array() const {
2936   DCHECK(HasFastProperties());
2937 
2938   Object* prop = raw_properties_or_hash();
2939   if (prop->IsSmi() || prop == GetHeap()->empty_fixed_array()) {
2940     return GetHeap()->empty_property_array();
2941   }
2942 
2943   return PropertyArray::cast(prop);
2944 }
2945 
HasProperty(Handle<JSReceiver> object,Handle<Name> name)2946 Maybe<bool> JSReceiver::HasProperty(Handle<JSReceiver> object,
2947                                     Handle<Name> name) {
2948   LookupIterator it = LookupIterator::PropertyOrElement(object->GetIsolate(),
2949                                                         object, name, object);
2950   return HasProperty(&it);
2951 }
2952 
2953 
HasOwnProperty(Handle<JSReceiver> object,uint32_t index)2954 Maybe<bool> JSReceiver::HasOwnProperty(Handle<JSReceiver> object,
2955                                        uint32_t index) {
2956   if (object->IsJSModuleNamespace()) return Just(false);
2957 
2958   if (object->IsJSObject()) {  // Shortcut.
2959     LookupIterator it(object->GetIsolate(), object, index, object,
2960                       LookupIterator::OWN);
2961     return HasProperty(&it);
2962   }
2963 
2964   Maybe<PropertyAttributes> attributes =
2965       JSReceiver::GetOwnPropertyAttributes(object, index);
2966   MAYBE_RETURN(attributes, Nothing<bool>());
2967   return Just(attributes.FromJust() != ABSENT);
2968 }
2969 
GetPropertyAttributes(Handle<JSReceiver> object,Handle<Name> name)2970 Maybe<PropertyAttributes> JSReceiver::GetPropertyAttributes(
2971     Handle<JSReceiver> object, Handle<Name> name) {
2972   LookupIterator it = LookupIterator::PropertyOrElement(name->GetIsolate(),
2973                                                         object, name, object);
2974   return GetPropertyAttributes(&it);
2975 }
2976 
2977 
GetOwnPropertyAttributes(Handle<JSReceiver> object,Handle<Name> name)2978 Maybe<PropertyAttributes> JSReceiver::GetOwnPropertyAttributes(
2979     Handle<JSReceiver> object, Handle<Name> name) {
2980   LookupIterator it = LookupIterator::PropertyOrElement(
2981       name->GetIsolate(), object, name, object, LookupIterator::OWN);
2982   return GetPropertyAttributes(&it);
2983 }
2984 
GetOwnPropertyAttributes(Handle<JSReceiver> object,uint32_t index)2985 Maybe<PropertyAttributes> JSReceiver::GetOwnPropertyAttributes(
2986     Handle<JSReceiver> object, uint32_t index) {
2987   LookupIterator it(object->GetIsolate(), object, index, object,
2988                     LookupIterator::OWN);
2989   return GetPropertyAttributes(&it);
2990 }
2991 
HasElement(Handle<JSReceiver> object,uint32_t index)2992 Maybe<bool> JSReceiver::HasElement(Handle<JSReceiver> object, uint32_t index) {
2993   LookupIterator it(object->GetIsolate(), object, index, object);
2994   return HasProperty(&it);
2995 }
2996 
2997 
GetElementAttributes(Handle<JSReceiver> object,uint32_t index)2998 Maybe<PropertyAttributes> JSReceiver::GetElementAttributes(
2999     Handle<JSReceiver> object, uint32_t index) {
3000   Isolate* isolate = object->GetIsolate();
3001   LookupIterator it(isolate, object, index, object);
3002   return GetPropertyAttributes(&it);
3003 }
3004 
3005 
GetOwnElementAttributes(Handle<JSReceiver> object,uint32_t index)3006 Maybe<PropertyAttributes> JSReceiver::GetOwnElementAttributes(
3007     Handle<JSReceiver> object, uint32_t index) {
3008   Isolate* isolate = object->GetIsolate();
3009   LookupIterator it(isolate, object, index, object, LookupIterator::OWN);
3010   return GetPropertyAttributes(&it);
3011 }
3012 
3013 
IsDetached()3014 bool JSGlobalObject::IsDetached() {
3015   return JSGlobalProxy::cast(global_proxy())->IsDetachedFrom(this);
3016 }
3017 
3018 
IsDetachedFrom(JSGlobalObject * global)3019 bool JSGlobalProxy::IsDetachedFrom(JSGlobalObject* global) const {
3020   const PrototypeIterator iter(this->GetIsolate(),
3021                                const_cast<JSGlobalProxy*>(this));
3022   return iter.GetCurrent() != global;
3023 }
3024 
SizeWithEmbedderFields(int embedder_field_count)3025 inline int JSGlobalProxy::SizeWithEmbedderFields(int embedder_field_count) {
3026   DCHECK_GE(embedder_field_count, 0);
3027   return kSize + embedder_field_count * kPointerSize;
3028 }
3029 
get(AccessorComponent component)3030 Object* AccessorPair::get(AccessorComponent component) {
3031   return component == ACCESSOR_GETTER ? getter() : setter();
3032 }
3033 
3034 
set(AccessorComponent component,Object * value)3035 void AccessorPair::set(AccessorComponent component, Object* value) {
3036   if (component == ACCESSOR_GETTER) {
3037     set_getter(value);
3038   } else {
3039     set_setter(value);
3040   }
3041 }
3042 
3043 
SetComponents(Object * getter,Object * setter)3044 void AccessorPair::SetComponents(Object* getter, Object* setter) {
3045   Isolate* isolate = GetIsolate();
3046   if (!getter->IsNull(isolate)) set_getter(getter);
3047   if (!setter->IsNull(isolate)) set_setter(setter);
3048 }
3049 
3050 
Equals(AccessorPair * pair)3051 bool AccessorPair::Equals(AccessorPair* pair) {
3052   return (this == pair) || pair->Equals(getter(), setter());
3053 }
3054 
3055 
Equals(Object * getter_value,Object * setter_value)3056 bool AccessorPair::Equals(Object* getter_value, Object* setter_value) {
3057   return (getter() == getter_value) && (setter() == setter_value);
3058 }
3059 
3060 
ContainsAccessor()3061 bool AccessorPair::ContainsAccessor() {
3062   return IsJSAccessor(getter()) || IsJSAccessor(setter());
3063 }
3064 
3065 
IsJSAccessor(Object * obj)3066 bool AccessorPair::IsJSAccessor(Object* obj) {
3067   return obj->IsCallable() || obj->IsUndefined(GetIsolate());
3068 }
3069 
3070 template <typename Derived, typename Shape>
ClearEntry(int entry)3071 void Dictionary<Derived, Shape>::ClearEntry(int entry) {
3072   Object* the_hole = this->GetHeap()->the_hole_value();
3073   PropertyDetails details = PropertyDetails::Empty();
3074   Derived::cast(this)->SetEntry(entry, the_hole, the_hole, details);
3075 }
3076 
3077 template <typename Derived, typename Shape>
SetEntry(int entry,Object * key,Object * value,PropertyDetails details)3078 void Dictionary<Derived, Shape>::SetEntry(int entry, Object* key, Object* value,
3079                                           PropertyDetails details) {
3080   DCHECK(Dictionary::kEntrySize == 2 || Dictionary::kEntrySize == 3);
3081   DCHECK(!key->IsName() || details.dictionary_index() > 0);
3082   int index = DerivedHashTable::EntryToIndex(entry);
3083   DisallowHeapAllocation no_gc;
3084   WriteBarrierMode mode = this->GetWriteBarrierMode(no_gc);
3085   this->set(index + Derived::kEntryKeyIndex, key, mode);
3086   this->set(index + Derived::kEntryValueIndex, value, mode);
3087   if (Shape::kHasDetails) DetailsAtPut(entry, details);
3088 }
3089 
Unwrap(Object * object)3090 Object* GlobalDictionaryShape::Unwrap(Object* object) {
3091   return PropertyCell::cast(object)->name();
3092 }
3093 
GetMapRootIndex()3094 int GlobalDictionaryShape::GetMapRootIndex() {
3095   return Heap::kGlobalDictionaryMapRootIndex;
3096 }
3097 
NameAt(int entry)3098 Name* NameDictionary::NameAt(int entry) { return Name::cast(KeyAt(entry)); }
3099 
GetMapRootIndex()3100 int NameDictionaryShape::GetMapRootIndex() {
3101   return Heap::kNameDictionaryMapRootIndex;
3102 }
3103 
CellAt(int entry)3104 PropertyCell* GlobalDictionary::CellAt(int entry) {
3105   DCHECK(KeyAt(entry)->IsPropertyCell());
3106   return PropertyCell::cast(KeyAt(entry));
3107 }
3108 
IsLive(Isolate * isolate,Object * k)3109 bool GlobalDictionaryShape::IsLive(Isolate* isolate, Object* k) {
3110   Heap* heap = isolate->heap();
3111   DCHECK_NE(heap->the_hole_value(), k);
3112   return k != heap->undefined_value();
3113 }
3114 
IsKey(Isolate * isolate,Object * k)3115 bool GlobalDictionaryShape::IsKey(Isolate* isolate, Object* k) {
3116   return IsLive(isolate, k) &&
3117          !PropertyCell::cast(k)->value()->IsTheHole(isolate);
3118 }
3119 
NameAt(int entry)3120 Name* GlobalDictionary::NameAt(int entry) { return CellAt(entry)->name(); }
ValueAt(int entry)3121 Object* GlobalDictionary::ValueAt(int entry) { return CellAt(entry)->value(); }
3122 
SetEntry(int entry,Object * key,Object * value,PropertyDetails details)3123 void GlobalDictionary::SetEntry(int entry, Object* key, Object* value,
3124                                 PropertyDetails details) {
3125   DCHECK_EQ(key, PropertyCell::cast(value)->name());
3126   set(EntryToIndex(entry) + kEntryKeyIndex, value);
3127   DetailsAtPut(entry, details);
3128 }
3129 
ValueAtPut(int entry,Object * value)3130 void GlobalDictionary::ValueAtPut(int entry, Object* value) {
3131   set(EntryToIndex(entry), value);
3132 }
3133 
IsMatch(uint32_t key,Object * other)3134 bool NumberDictionaryBaseShape::IsMatch(uint32_t key, Object* other) {
3135   DCHECK(other->IsNumber());
3136   return key == static_cast<uint32_t>(other->Number());
3137 }
3138 
Hash(Isolate * isolate,uint32_t key)3139 uint32_t NumberDictionaryBaseShape::Hash(Isolate* isolate, uint32_t key) {
3140   return ComputeSeededHash(key, isolate->heap()->HashSeed());
3141 }
3142 
HashForObject(Isolate * isolate,Object * other)3143 uint32_t NumberDictionaryBaseShape::HashForObject(Isolate* isolate,
3144                                                   Object* other) {
3145   DCHECK(other->IsNumber());
3146   return ComputeSeededHash(static_cast<uint32_t>(other->Number()),
3147                            isolate->heap()->HashSeed());
3148 }
3149 
AsHandle(Isolate * isolate,uint32_t key)3150 Handle<Object> NumberDictionaryBaseShape::AsHandle(Isolate* isolate,
3151                                                    uint32_t key) {
3152   return isolate->factory()->NewNumberFromUint(key);
3153 }
3154 
GetMapRootIndex()3155 int NumberDictionaryShape::GetMapRootIndex() {
3156   return Heap::kNumberDictionaryMapRootIndex;
3157 }
3158 
GetMapRootIndex()3159 int SimpleNumberDictionaryShape::GetMapRootIndex() {
3160   return Heap::kSimpleNumberDictionaryMapRootIndex;
3161 }
3162 
IsMatch(Handle<Name> key,Object * other)3163 bool NameDictionaryShape::IsMatch(Handle<Name> key, Object* other) {
3164   DCHECK(other->IsTheHole(key->GetIsolate()) ||
3165          Name::cast(other)->IsUniqueName());
3166   DCHECK(key->IsUniqueName());
3167   return *key == other;
3168 }
3169 
Hash(Isolate * isolate,Handle<Name> key)3170 uint32_t NameDictionaryShape::Hash(Isolate* isolate, Handle<Name> key) {
3171   return key->Hash();
3172 }
3173 
HashForObject(Isolate * isolate,Object * other)3174 uint32_t NameDictionaryShape::HashForObject(Isolate* isolate, Object* other) {
3175   return Name::cast(other)->Hash();
3176 }
3177 
IsMatch(Handle<Name> key,Object * other)3178 bool GlobalDictionaryShape::IsMatch(Handle<Name> key, Object* other) {
3179   DCHECK(PropertyCell::cast(other)->name()->IsUniqueName());
3180   return *key == PropertyCell::cast(other)->name();
3181 }
3182 
HashForObject(Isolate * isolate,Object * other)3183 uint32_t GlobalDictionaryShape::HashForObject(Isolate* isolate, Object* other) {
3184   return PropertyCell::cast(other)->name()->Hash();
3185 }
3186 
AsHandle(Isolate * isolate,Handle<Name> key)3187 Handle<Object> NameDictionaryShape::AsHandle(Isolate* isolate,
3188                                              Handle<Name> key) {
3189   DCHECK(key->IsUniqueName());
3190   return key;
3191 }
3192 
3193 
3194 template <typename Dictionary>
DetailsAt(Dictionary * dict,int entry)3195 PropertyDetails GlobalDictionaryShape::DetailsAt(Dictionary* dict, int entry) {
3196   DCHECK_LE(0, entry);  // Not found is -1, which is not caught by get().
3197   return dict->CellAt(entry)->property_details();
3198 }
3199 
3200 
3201 template <typename Dictionary>
DetailsAtPut(Dictionary * dict,int entry,PropertyDetails value)3202 void GlobalDictionaryShape::DetailsAtPut(Dictionary* dict, int entry,
3203                                          PropertyDetails value) {
3204   DCHECK_LE(0, entry);  // Not found is -1, which is not caught by get().
3205   PropertyCell* cell = dict->CellAt(entry);
3206   if (cell->property_details().IsReadOnly() != value.IsReadOnly()) {
3207     cell->dependent_code()->DeoptimizeDependentCodeGroup(
3208         cell->GetIsolate(), DependentCode::kPropertyCellChangedGroup);
3209   }
3210   cell->set_property_details(value);
3211 }
3212 
IsMatch(Handle<Object> key,Object * other)3213 bool ObjectHashTableShape::IsMatch(Handle<Object> key, Object* other) {
3214   return key->SameValue(other);
3215 }
3216 
Hash(Isolate * isolate,Handle<Object> key)3217 uint32_t ObjectHashTableShape::Hash(Isolate* isolate, Handle<Object> key) {
3218   return Smi::ToInt(key->GetHash());
3219 }
3220 
HashForObject(Isolate * isolate,Object * other)3221 uint32_t ObjectHashTableShape::HashForObject(Isolate* isolate, Object* other) {
3222   return Smi::ToInt(other->GetHash());
3223 }
3224 
3225 // static
GetSimpleHash(Object * object)3226 Object* Object::GetSimpleHash(Object* object) {
3227   DisallowHeapAllocation no_gc;
3228   if (object->IsSmi()) {
3229     uint32_t hash = ComputeUnseededHash(Smi::ToInt(object));
3230     return Smi::FromInt(hash & Smi::kMaxValue);
3231   }
3232   if (object->IsHeapNumber()) {
3233     double num = HeapNumber::cast(object)->value();
3234     if (std::isnan(num)) return Smi::FromInt(Smi::kMaxValue);
3235     // Use ComputeUnseededHash for all values in Signed32 range, including -0,
3236     // which is considered equal to 0 because collections use SameValueZero.
3237     uint32_t hash;
3238     // Check range before conversion to avoid undefined behavior.
3239     if (num >= kMinInt && num <= kMaxInt && FastI2D(FastD2I(num)) == num) {
3240       hash = ComputeUnseededHash(FastD2I(num));
3241     } else {
3242       hash = ComputeLongHash(double_to_uint64(num));
3243     }
3244     return Smi::FromInt(hash & Smi::kMaxValue);
3245   }
3246   if (object->IsName()) {
3247     uint32_t hash = Name::cast(object)->Hash();
3248     return Smi::FromInt(hash);
3249   }
3250   if (object->IsOddball()) {
3251     uint32_t hash = Oddball::cast(object)->to_string()->Hash();
3252     return Smi::FromInt(hash);
3253   }
3254   if (object->IsBigInt()) {
3255     uint32_t hash = BigInt::cast(object)->Hash();
3256     return Smi::FromInt(hash & Smi::kMaxValue);
3257   }
3258   DCHECK(object->IsJSReceiver());
3259   return object;
3260 }
3261 
GetHash()3262 Object* Object::GetHash() {
3263   DisallowHeapAllocation no_gc;
3264   Object* hash = GetSimpleHash(this);
3265   if (hash->IsSmi()) return hash;
3266 
3267   DCHECK(IsJSReceiver());
3268   JSReceiver* receiver = JSReceiver::cast(this);
3269   Isolate* isolate = receiver->GetIsolate();
3270   return receiver->GetIdentityHash(isolate);
3271 }
3272 
AsHandle(Isolate * isolate,Handle<Object> key)3273 Handle<Object> ObjectHashTableShape::AsHandle(Isolate* isolate,
3274                                               Handle<Object> key) {
3275   return key;
3276 }
3277 
Shrink(Handle<ObjectHashTable> table)3278 Handle<ObjectHashTable> ObjectHashTable::Shrink(Handle<ObjectHashTable> table) {
3279   return DerivedHashTable::Shrink(table);
3280 }
3281 
Relocatable(Isolate * isolate)3282 Relocatable::Relocatable(Isolate* isolate) {
3283   isolate_ = isolate;
3284   prev_ = isolate->relocatable_top();
3285   isolate->set_relocatable_top(this);
3286 }
3287 
3288 
~Relocatable()3289 Relocatable::~Relocatable() {
3290   DCHECK_EQ(isolate_->relocatable_top(), this);
3291   isolate_->set_relocatable_top(prev_);
3292 }
3293 
3294 
3295 template<class Derived, class TableType>
CurrentKey()3296 Object* OrderedHashTableIterator<Derived, TableType>::CurrentKey() {
3297   TableType* table(TableType::cast(this->table()));
3298   int index = Smi::ToInt(this->index());
3299   Object* key = table->KeyAt(index);
3300   DCHECK(!key->IsTheHole(table->GetIsolate()));
3301   return key;
3302 }
3303 
3304 // Predictably converts HeapObject* or Address to uint32 by calculating
3305 // offset of the address in respective MemoryChunk.
ObjectAddressForHashing(void * object)3306 static inline uint32_t ObjectAddressForHashing(void* object) {
3307   uint32_t value = static_cast<uint32_t>(reinterpret_cast<uintptr_t>(object));
3308   return value & MemoryChunk::kAlignmentMask;
3309 }
3310 
MakeEntryPair(Isolate * isolate,uint32_t index,Handle<Object> value)3311 static inline Handle<Object> MakeEntryPair(Isolate* isolate, uint32_t index,
3312                                            Handle<Object> value) {
3313   Handle<Object> key = isolate->factory()->Uint32ToString(index);
3314   Handle<FixedArray> entry_storage =
3315       isolate->factory()->NewUninitializedFixedArray(2);
3316   {
3317     entry_storage->set(0, *key, SKIP_WRITE_BARRIER);
3318     entry_storage->set(1, *value, SKIP_WRITE_BARRIER);
3319   }
3320   return isolate->factory()->NewJSArrayWithElements(entry_storage,
3321                                                     PACKED_ELEMENTS, 2);
3322 }
3323 
MakeEntryPair(Isolate * isolate,Handle<Object> key,Handle<Object> value)3324 static inline Handle<Object> MakeEntryPair(Isolate* isolate, Handle<Object> key,
3325                                            Handle<Object> value) {
3326   Handle<FixedArray> entry_storage =
3327       isolate->factory()->NewUninitializedFixedArray(2);
3328   {
3329     entry_storage->set(0, *key, SKIP_WRITE_BARRIER);
3330     entry_storage->set(1, *value, SKIP_WRITE_BARRIER);
3331   }
3332   return isolate->factory()->NewJSArrayWithElements(entry_storage,
3333                                                     PACKED_ELEMENTS, 2);
3334 }
3335 
ACCESSORS(JSIteratorResult,value,Object,kValueOffset)3336 ACCESSORS(JSIteratorResult, value, Object, kValueOffset)
3337 ACCESSORS(JSIteratorResult, done, Object, kDoneOffset)
3338 
3339 ACCESSORS(JSAsyncFromSyncIterator, sync_iterator, JSReceiver,
3340           kSyncIteratorOffset)
3341 ACCESSORS(JSAsyncFromSyncIterator, next, Object, kNextOffset)
3342 
3343 ACCESSORS(JSStringIterator, string, String, kStringOffset)
3344 SMI_ACCESSORS(JSStringIterator, index, kNextIndexOffset)
3345 
3346 bool ScopeInfo::IsAsmModule() const { return AsmModuleField::decode(Flags()); }
3347 
HasSimpleParameters()3348 bool ScopeInfo::HasSimpleParameters() const {
3349   return HasSimpleParametersField::decode(Flags());
3350 }
3351 
3352 #define FIELD_ACCESSORS(name)                                                 \
3353   void ScopeInfo::Set##name(int value) { set(k##name, Smi::FromInt(value)); } \
3354   int ScopeInfo::name() const {                                               \
3355     if (length() > 0) {                                                       \
3356       return Smi::ToInt(get(k##name));                                        \
3357     } else {                                                                  \
3358       return 0;                                                               \
3359     }                                                                         \
3360   }
3361 FOR_EACH_SCOPE_INFO_NUMERIC_FIELD(FIELD_ACCESSORS)
3362 #undef FIELD_ACCESSORS
3363 
3364 }  // namespace internal
3365 }  // namespace v8
3366 
3367 #include "src/objects/object-macros-undef.h"
3368 
3369 #endif  // V8_OBJECTS_INL_H_
3370