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