Line data Source code
1 : // Copyright 2012 the V8 project authors. All rights reserved.
2 : // Use of this source code is governed by a BSD-style license that can be
3 : // found in the LICENSE file.
4 : //
5 : // Review notes:
6 : //
7 : // - The use of macros in these inline functions may seem superfluous
8 : // but it is absolutely needed to make sure gcc generates optimal
9 : // code. gcc is not happy when attempting to inline too deep.
10 : //
11 :
12 : #ifndef V8_OBJECTS_INL_H_
13 : #define V8_OBJECTS_INL_H_
14 :
15 : #include "src/objects.h"
16 :
17 : #include "src/base/bits.h"
18 : #include "src/base/tsan.h"
19 : #include "src/builtins/builtins.h"
20 : #include "src/conversions.h"
21 : #include "src/double.h"
22 : #include "src/handles-inl.h"
23 : #include "src/heap/factory.h"
24 : #include "src/heap/heap-write-barrier-inl.h"
25 : #include "src/keys.h"
26 : #include "src/lookup-inl.h" // TODO(jkummerow): Drop.
27 : #include "src/objects/bigint.h"
28 : #include "src/objects/heap-number-inl.h"
29 : #include "src/objects/heap-object.h"
30 : #include "src/objects/js-proxy-inl.h" // TODO(jkummerow): Drop.
31 : #include "src/objects/literal-objects.h"
32 : #include "src/objects/oddball.h"
33 : #include "src/objects/regexp-match-info.h"
34 : #include "src/objects/scope-info.h"
35 : #include "src/objects/shared-function-info.h"
36 : #include "src/objects/slots-inl.h"
37 : #include "src/objects/smi-inl.h"
38 : #include "src/objects/templates.h"
39 : #include "src/property-details.h"
40 : #include "src/property.h"
41 : #include "src/v8memory.h"
42 :
43 : // Has to be the last include (doesn't have include guards):
44 : #include "src/objects/object-macros.h"
45 :
46 : namespace v8 {
47 : namespace internal {
48 :
49 4696365235 : PropertyDetails::PropertyDetails(Smi smi) { value_ = smi->value(); }
50 :
51 1008 : Smi PropertyDetails::AsSmi() const {
52 : // Ensure the upper 2 bits have the same value by sign extending it. This is
53 : // necessary to be able to use the 31st bit of the property details.
54 1030898209 : int value = value_ << 1;
55 1030898209 : return Smi::FromInt(value >> 1);
56 : }
57 :
58 :
59 : int PropertyDetails::field_width_in_words() const {
60 : DCHECK_EQ(location(), kField);
61 : if (!FLAG_unbox_double_fields) return 1;
62 : if (kDoubleSize == kTaggedSize) return 1;
63 : return representation().IsDouble() ? kDoubleSize / kTaggedSize : 1;
64 : }
65 :
66 : bool HeapObject::IsSloppyArgumentsElements() const {
67 : return IsFixedArrayExact();
68 : }
69 :
70 : bool HeapObject::IsJSSloppyArgumentsObject() const {
71 : return IsJSArgumentsObject();
72 : }
73 :
74 : bool HeapObject::IsJSGeneratorObject() const {
75 12644559 : return map()->instance_type() == JS_GENERATOR_OBJECT_TYPE ||
76 21025945 : IsJSAsyncFunctionObject() || IsJSAsyncGeneratorObject();
77 : }
78 :
79 : bool HeapObject::IsDataHandler() const {
80 : return IsLoadHandler() || IsStoreHandler();
81 : }
82 :
83 : bool HeapObject::IsClassBoilerplate() const { return IsFixedArrayExact(); }
84 :
85 : #define IS_TYPE_FUNCTION_DEF(type_) \
86 : bool Object::Is##type_() const { \
87 : return IsHeapObject() && HeapObject::cast(*this)->Is##type_(); \
88 : }
89 10776843269 : HEAP_OBJECT_TYPE_LIST(IS_TYPE_FUNCTION_DEF)
90 : #undef IS_TYPE_FUNCTION_DEF
91 :
92 : #define IS_TYPE_FUNCTION_DEF(Type, Value) \
93 : bool Object::Is##Type(Isolate* isolate) const { \
94 : return Is##Type(ReadOnlyRoots(isolate->heap())); \
95 : } \
96 : bool Object::Is##Type(ReadOnlyRoots roots) const { \
97 : return *this == roots.Value(); \
98 : } \
99 : bool Object::Is##Type() const { \
100 : return IsHeapObject() && HeapObject::cast(*this)->Is##Type(); \
101 : } \
102 : bool HeapObject::Is##Type(Isolate* isolate) const { \
103 : return Object::Is##Type(isolate); \
104 : } \
105 : bool HeapObject::Is##Type(ReadOnlyRoots roots) const { \
106 : return Object::Is##Type(roots); \
107 : } \
108 : bool HeapObject::Is##Type() const { return Is##Type(GetReadOnlyRoots()); }
109 100952602 : ODDBALL_LIST(IS_TYPE_FUNCTION_DEF)
110 : #undef IS_TYPE_FUNCTION_DEF
111 :
112 : bool Object::IsNullOrUndefined(Isolate* isolate) const {
113 : return IsNullOrUndefined(ReadOnlyRoots(isolate));
114 : }
115 :
116 : bool Object::IsNullOrUndefined(ReadOnlyRoots roots) const {
117 265707532 : return IsNull(roots) || IsUndefined(roots);
118 : }
119 :
120 : bool Object::IsNullOrUndefined() const {
121 : return IsHeapObject() && HeapObject::cast(*this)->IsNullOrUndefined();
122 : }
123 :
124 : bool HeapObject::IsNullOrUndefined(Isolate* isolate) const {
125 : return Object::IsNullOrUndefined(isolate);
126 : }
127 :
128 : bool HeapObject::IsNullOrUndefined(ReadOnlyRoots roots) const {
129 : return Object::IsNullOrUndefined(roots);
130 : }
131 :
132 : bool HeapObject::IsNullOrUndefined() const {
133 : return IsNullOrUndefined(GetReadOnlyRoots());
134 : }
135 :
136 : bool HeapObject::IsUniqueName() const {
137 9299754 : return IsInternalizedString() || IsSymbol();
138 : }
139 :
140 : bool HeapObject::IsFunction() const {
141 : STATIC_ASSERT(LAST_FUNCTION_TYPE == LAST_TYPE);
142 3688 : return map()->instance_type() >= FIRST_FUNCTION_TYPE;
143 : }
144 :
145 7868014 : bool HeapObject::IsCallable() const { return map()->is_callable(); }
146 :
147 12 : bool HeapObject::IsConstructor() const { return map()->is_constructor(); }
148 :
149 : bool HeapObject::IsModuleInfo() const {
150 : return map() == GetReadOnlyRoots().module_info_map();
151 : }
152 :
153 : bool HeapObject::IsTemplateInfo() const {
154 1087281 : return IsObjectTemplateInfo() || IsFunctionTemplateInfo();
155 : }
156 :
157 : bool HeapObject::IsConsString() const {
158 99437918 : if (!IsString()) return false;
159 198875915 : return StringShape(String::cast(*this)).IsCons();
160 : }
161 :
162 : bool HeapObject::IsThinString() const {
163 172529276 : if (!IsString()) return false;
164 345049351 : return StringShape(String::cast(*this)).IsThin();
165 : }
166 :
167 : bool HeapObject::IsSlicedString() const {
168 5956193 : if (!IsString()) return false;
169 11912385 : return StringShape(String::cast(*this)).IsSliced();
170 : }
171 :
172 : bool HeapObject::IsSeqString() const {
173 7617749 : if (!IsString()) return false;
174 15235466 : return StringShape(String::cast(*this)).IsSequential();
175 : }
176 :
177 : bool HeapObject::IsSeqOneByteString() const {
178 65951025 : if (!IsString()) return false;
179 187490034 : return StringShape(String::cast(*this)).IsSequential() &&
180 59388565 : String::cast(*this)->IsOneByteRepresentation();
181 : }
182 :
183 : bool HeapObject::IsSeqTwoByteString() const {
184 1981937 : if (!IsString()) return false;
185 242204 : return StringShape(String::cast(*this)).IsSequential() &&
186 78938 : String::cast(*this)->IsTwoByteRepresentation();
187 : }
188 :
189 : bool HeapObject::IsExternalString() const {
190 378034834 : if (!IsString()) return false;
191 189770858 : return StringShape(String::cast(*this)).IsExternal();
192 : }
193 :
194 : bool HeapObject::IsExternalOneByteString() const {
195 7663848 : if (!IsString()) return false;
196 15337516 : return StringShape(String::cast(*this)).IsExternal() &&
197 9826 : String::cast(*this)->IsOneByteRepresentation();
198 : }
199 :
200 : bool HeapObject::IsExternalTwoByteString() const {
201 7654090 : if (!IsString()) return false;
202 15308250 : return StringShape(String::cast(*this)).IsExternal() &&
203 72 : String::cast(*this)->IsTwoByteRepresentation();
204 : }
205 :
206 193083430 : bool Object::IsNumber() const { return IsSmi() || IsHeapNumber(); }
207 :
208 1566 : bool Object::IsNumeric() const { return IsNumber() || IsBigInt(); }
209 :
210 : bool HeapObject::IsFiller() const {
211 0 : InstanceType instance_type = map()->instance_type();
212 220908168 : return instance_type == FREE_SPACE_TYPE || instance_type == FILLER_TYPE;
213 : }
214 :
215 : bool HeapObject::IsJSWeakCollection() const {
216 180344 : return IsJSWeakMap() || IsJSWeakSet();
217 : }
218 :
219 0 : bool HeapObject::IsJSCollection() const { return IsJSMap() || IsJSSet(); }
220 :
221 : bool HeapObject::IsPromiseReactionJobTask() const {
222 2488787 : return IsPromiseFulfillReactionJobTask() || IsPromiseRejectReactionJobTask();
223 : }
224 :
225 : bool HeapObject::IsEnumCache() const { return IsTuple2(); }
226 :
227 : bool HeapObject::IsFrameArray() const { return IsFixedArrayExact(); }
228 :
229 : bool HeapObject::IsArrayList() const {
230 1366 : return map() == GetReadOnlyRoots().array_list_map() ||
231 : *this == GetReadOnlyRoots().empty_fixed_array();
232 : }
233 :
234 : bool HeapObject::IsRegExpMatchInfo() const { return IsFixedArrayExact(); }
235 :
236 0 : bool Object::IsLayoutDescriptor() const { return IsSmi() || IsByteArray(); }
237 :
238 : bool HeapObject::IsDeoptimizationData() const {
239 : // Must be a fixed array.
240 : if (!IsFixedArrayExact()) return false;
241 :
242 : // There's no sure way to detect the difference between a fixed array and
243 : // a deoptimization data array. Since this is used for asserts we can
244 : // check that the length is zero or else the fixed size plus a multiple of
245 : // the entry size.
246 : int length = FixedArray::cast(*this)->length();
247 : if (length == 0) return true;
248 :
249 : length -= DeoptimizationData::kFirstDeoptEntryIndex;
250 : return length >= 0 && length % DeoptimizationData::kDeoptEntrySize == 0;
251 : }
252 :
253 : bool HeapObject::IsHandlerTable() const {
254 : if (!IsFixedArrayExact()) return false;
255 : // There's actually no way to see the difference between a fixed array and
256 : // a handler table array.
257 : return true;
258 : }
259 :
260 : bool HeapObject::IsTemplateList() const {
261 : if (!IsFixedArrayExact()) return false;
262 : // There's actually no way to see the difference between a fixed array and
263 : // a template list.
264 : if (FixedArray::cast(*this)->length() < 1) return false;
265 : return true;
266 : }
267 :
268 : bool HeapObject::IsDependentCode() const {
269 : if (!IsWeakFixedArray()) return false;
270 : // There's actually no way to see the difference between a weak fixed array
271 : // and a dependent codes array.
272 : return true;
273 : }
274 :
275 : bool HeapObject::IsAbstractCode() const {
276 6552371 : return IsBytecodeArray() || IsCode();
277 : }
278 :
279 : bool HeapObject::IsStringWrapper() const {
280 1565729 : return IsJSValue() && JSValue::cast(*this)->value()->IsString();
281 : }
282 :
283 : bool HeapObject::IsBooleanWrapper() const {
284 21278 : return IsJSValue() && JSValue::cast(*this)->value()->IsBoolean();
285 : }
286 :
287 : bool HeapObject::IsScriptWrapper() const {
288 : return IsJSValue() && JSValue::cast(*this)->value()->IsScript();
289 : }
290 :
291 : bool HeapObject::IsNumberWrapper() const {
292 21200 : return IsJSValue() && JSValue::cast(*this)->value()->IsNumber();
293 : }
294 :
295 : bool HeapObject::IsBigIntWrapper() const {
296 21169 : return IsJSValue() && JSValue::cast(*this)->value()->IsBigInt();
297 : }
298 :
299 : bool HeapObject::IsSymbolWrapper() const {
300 21154 : return IsJSValue() && JSValue::cast(*this)->value()->IsSymbol();
301 : }
302 :
303 : bool HeapObject::IsJSArrayBufferView() const {
304 282027 : return IsJSDataView() || IsJSTypedArray();
305 : }
306 :
307 : bool HeapObject::IsStringSet() const { return IsHashTable(); }
308 :
309 : bool HeapObject::IsObjectHashSet() const { return IsHashTable(); }
310 :
311 : bool HeapObject::IsCompilationCacheTable() const { return IsHashTable(); }
312 :
313 : bool HeapObject::IsMapCache() const { return IsHashTable(); }
314 :
315 : bool HeapObject::IsObjectHashTable() const { return IsHashTable(); }
316 :
317 : bool Object::IsHashTableBase() const { return IsHashTable(); }
318 :
319 : bool Object::IsSmallOrderedHashTable() const {
320 : return IsSmallOrderedHashSet() || IsSmallOrderedHashMap() ||
321 : IsSmallOrderedNameDictionary();
322 : }
323 :
324 : bool Object::IsPrimitive() const {
325 3991940 : return IsSmi() || HeapObject::cast(*this)->map()->IsPrimitiveMap();
326 : }
327 :
328 : // static
329 : Maybe<bool> Object::IsArray(Handle<Object> object) {
330 1181036 : if (object->IsSmi()) return Just(false);
331 : Handle<HeapObject> heap_object = Handle<HeapObject>::cast(object);
332 1181018 : if (heap_object->IsJSArray()) return Just(true);
333 1151908 : if (!heap_object->IsJSProxy()) return Just(false);
334 1238 : return JSProxy::IsArray(Handle<JSProxy>::cast(object));
335 : }
336 :
337 179416439 : bool HeapObject::IsUndetectable() const { return map()->is_undetectable(); }
338 :
339 : bool HeapObject::IsAccessCheckNeeded() const {
340 34370680 : if (IsJSGlobalProxy()) {
341 74808 : const JSGlobalProxy proxy = JSGlobalProxy::cast(*this);
342 74808 : JSGlobalObject global = proxy->GetIsolate()->context()->global_object();
343 74808 : return proxy->IsDetachedFrom(global);
344 : }
345 7659146 : return map()->is_access_check_needed();
346 : }
347 :
348 : bool HeapObject::IsStruct() const {
349 : switch (map()->instance_type()) {
350 : #define MAKE_STRUCT_CASE(TYPE, Name, name) \
351 : case TYPE: \
352 : return true;
353 : STRUCT_LIST(MAKE_STRUCT_CASE)
354 : #undef MAKE_STRUCT_CASE
355 : // It is hard to include ALLOCATION_SITE_TYPE in STRUCT_LIST because
356 : // that macro is used for many things and AllocationSite needs a few
357 : // special cases.
358 : case ALLOCATION_SITE_TYPE:
359 : return true;
360 : case LOAD_HANDLER_TYPE:
361 : case STORE_HANDLER_TYPE:
362 : return true;
363 : case FEEDBACK_CELL_TYPE:
364 : return true;
365 : case CALL_HANDLER_INFO_TYPE:
366 : return true;
367 : default:
368 : return false;
369 : }
370 : }
371 :
372 : #define MAKE_STRUCT_PREDICATE(NAME, Name, name) \
373 : bool Object::Is##Name() const { \
374 : return IsHeapObject() && HeapObject::cast(*this)->Is##Name(); \
375 : } \
376 : TYPE_CHECKER(Name)
377 596666195 : STRUCT_LIST(MAKE_STRUCT_PREDICATE)
378 : #undef MAKE_STRUCT_PREDICATE
379 :
380 : double Object::Number() const {
381 : DCHECK(IsNumber());
382 : return IsSmi() ? static_cast<double>(Smi(this->ptr())->value())
383 228925398 : : HeapNumber::unchecked_cast(*this)->value();
384 : }
385 :
386 : bool Object::IsNaN() const {
387 4470 : return this->IsHeapNumber() && std::isnan(HeapNumber::cast(*this)->value());
388 : }
389 :
390 : bool Object::IsMinusZero() const {
391 6860 : return this->IsHeapNumber() &&
392 : i::IsMinusZero(HeapNumber::cast(*this)->value());
393 : }
394 :
395 : OBJECT_CONSTRUCTORS_IMPL(RegExpMatchInfo, FixedArray)
396 56 : OBJECT_CONSTRUCTORS_IMPL(ScopeInfo, FixedArray)
397 : OBJECT_CONSTRUCTORS_IMPL(BigIntBase, HeapObject)
398 : OBJECT_CONSTRUCTORS_IMPL(BigInt, BigIntBase)
399 : OBJECT_CONSTRUCTORS_IMPL(FreshlyAllocatedBigInt, BigIntBase)
400 :
401 : // ------------------------------------
402 : // Cast operations
403 :
404 : CAST_ACCESSOR(BigInt)
405 : CAST_ACCESSOR(RegExpMatchInfo)
406 56 : CAST_ACCESSOR(ScopeInfo)
407 :
408 : bool Object::HasValidElements() {
409 : // Dictionary is covered under FixedArray.
410 : return IsFixedArray() || IsFixedDoubleArray() || IsFixedTypedArrayBase();
411 : }
412 :
413 13641407 : bool Object::FilterKey(PropertyFilter filter) {
414 : DCHECK(!IsPropertyCell());
415 13641407 : if (filter == PRIVATE_NAMES_ONLY) {
416 2299410 : if (!IsSymbol()) return true;
417 18502 : return !Symbol::cast(*this)->is_private_name();
418 11341997 : } else if (IsSymbol()) {
419 100997 : if (filter & SKIP_SYMBOLS) return true;
420 :
421 46373 : if (Symbol::cast(*this)->is_private()) return true;
422 : } else {
423 11241000 : if (filter & SKIP_STRINGS) return true;
424 : }
425 : return false;
426 : }
427 :
428 17827021 : Representation Object::OptimalRepresentation() {
429 17827021 : if (!FLAG_track_fields) return Representation::Tagged();
430 17827021 : if (IsSmi()) {
431 : return Representation::Smi();
432 25733585 : } else if (FLAG_track_double_fields && IsHeapNumber()) {
433 : return Representation::Double();
434 25700558 : } else if (FLAG_track_computed_fields && IsUninitialized()) {
435 : return Representation::None();
436 12632988 : } else if (FLAG_track_heap_object_fields) {
437 : DCHECK(IsHeapObject());
438 : return Representation::HeapObject();
439 : } else {
440 : return Representation::Tagged();
441 : }
442 : }
443 :
444 :
445 11104744 : ElementsKind Object::OptimalElementsKind() {
446 11104744 : if (IsSmi()) return PACKED_SMI_ELEMENTS;
447 1542112 : if (IsNumber()) return PACKED_DOUBLE_ELEMENTS;
448 385581 : return PACKED_ELEMENTS;
449 : }
450 :
451 :
452 40465225 : bool Object::FitsRepresentation(Representation representation) {
453 40465225 : if (FLAG_track_fields && representation.IsSmi()) {
454 4817532 : return IsSmi();
455 35647693 : } else if (FLAG_track_double_fields && representation.IsDouble()) {
456 70588 : return IsMutableHeapNumber() || IsNumber();
457 35612399 : } else if (FLAG_track_heap_object_fields && representation.IsHeapObject()) {
458 30842979 : return IsHeapObject();
459 4769420 : } else if (FLAG_track_fields && representation.IsNone()) {
460 : return false;
461 : }
462 4584087 : return true;
463 : }
464 :
465 59724703 : bool Object::ToUint32(uint32_t* value) const {
466 59724703 : if (IsSmi()) {
467 : int num = Smi::ToInt(*this);
468 44093829 : if (num < 0) return false;
469 44074323 : *value = static_cast<uint32_t>(num);
470 44074323 : return true;
471 : }
472 15630871 : if (IsHeapNumber()) {
473 : double num = HeapNumber::cast(*this)->value();
474 98063 : return DoubleToUint32IfEqualToSelf(num, value);
475 : }
476 : return false;
477 : }
478 :
479 : // static
480 16782410 : MaybeHandle<JSReceiver> Object::ToObject(Isolate* isolate,
481 : Handle<Object> object,
482 : const char* method_name) {
483 16782410 : if (object->IsJSReceiver()) return Handle<JSReceiver>::cast(object);
484 6813 : return ToObjectImpl(isolate, object, method_name);
485 : }
486 :
487 :
488 : // static
489 6460729 : MaybeHandle<Name> Object::ToName(Isolate* isolate, Handle<Object> input) {
490 6460729 : if (input->IsName()) return Handle<Name>::cast(input);
491 85419 : return ConvertToName(isolate, input);
492 : }
493 :
494 : // static
495 262989 : MaybeHandle<Object> Object::ToPropertyKey(Isolate* isolate,
496 : Handle<Object> value) {
497 484498 : if (value->IsSmi() || HeapObject::cast(*value)->IsName()) return value;
498 486 : return ConvertToPropertyKey(isolate, value);
499 : }
500 :
501 : // static
502 142954 : MaybeHandle<Object> Object::ToPrimitive(Handle<Object> input,
503 : ToPrimitiveHint hint) {
504 142954 : if (input->IsPrimitive()) return input;
505 6636 : return JSReceiver::ToPrimitive(Handle<JSReceiver>::cast(input), hint);
506 : }
507 :
508 : // static
509 7469413 : MaybeHandle<Object> Object::ToNumber(Isolate* isolate, Handle<Object> input) {
510 7469413 : if (input->IsNumber()) return input; // Shortcut.
511 2678631 : return ConvertToNumberOrNumeric(isolate, input, Conversion::kToNumber);
512 : }
513 :
514 : // static
515 5490 : MaybeHandle<Object> Object::ToNumeric(Isolate* isolate, Handle<Object> input) {
516 8656 : if (input->IsNumber() || input->IsBigInt()) return input; // Shortcut.
517 1375 : return ConvertToNumberOrNumeric(isolate, input, Conversion::kToNumeric);
518 : }
519 :
520 : // static
521 : MaybeHandle<Object> Object::ToInteger(Isolate* isolate, Handle<Object> input) {
522 4173479 : if (input->IsSmi()) return input;
523 105654 : return ConvertToInteger(isolate, input);
524 : }
525 :
526 : // static
527 : MaybeHandle<Object> Object::ToInt32(Isolate* isolate, Handle<Object> input) {
528 2600 : if (input->IsSmi()) return input;
529 1576 : return ConvertToInt32(isolate, input);
530 : }
531 :
532 : // static
533 422426 : MaybeHandle<Object> Object::ToUint32(Isolate* isolate, Handle<Object> input) {
534 422462 : if (input->IsSmi()) return handle(Smi::cast(*input)->ToUint32Smi(), isolate);
535 422390 : return ConvertToUint32(isolate, input);
536 : }
537 :
538 : // static
539 11943907 : MaybeHandle<String> Object::ToString(Isolate* isolate, Handle<Object> input) {
540 11943907 : if (input->IsString()) return Handle<String>::cast(input);
541 4580284 : return ConvertToString(isolate, input);
542 : }
543 :
544 : // static
545 63423 : MaybeHandle<Object> Object::ToLength(Isolate* isolate, Handle<Object> input) {
546 63423 : if (input->IsSmi()) {
547 183465 : int value = std::max(Smi::ToInt(*input), 0);
548 61155 : return handle(Smi::FromInt(value), isolate);
549 : }
550 2268 : return ConvertToLength(isolate, input);
551 : }
552 :
553 : // static
554 10947 : MaybeHandle<Object> Object::ToIndex(Isolate* isolate, Handle<Object> input,
555 : MessageTemplate error_index) {
556 20643 : if (input->IsSmi() && Smi::ToInt(*input) >= 0) return input;
557 1309 : return ConvertToIndex(isolate, input, error_index);
558 : }
559 :
560 2397745 : MaybeHandle<Object> Object::GetProperty(Isolate* isolate, Handle<Object> object,
561 : Handle<Name> name) {
562 2397745 : LookupIterator it(isolate, object, name);
563 2492991 : if (!it.IsFound()) return it.factory()->undefined_value();
564 2302499 : return GetProperty(&it);
565 : }
566 :
567 1184275 : MaybeHandle<Object> Object::GetElement(Isolate* isolate, Handle<Object> object,
568 : uint32_t index) {
569 1184275 : LookupIterator it(isolate, object, index);
570 2363977 : if (!it.IsFound()) return it.factory()->undefined_value();
571 4573 : return GetProperty(&it);
572 : }
573 :
574 22684 : MaybeHandle<Object> Object::SetElement(Isolate* isolate, Handle<Object> object,
575 : uint32_t index, Handle<Object> value,
576 : ShouldThrow should_throw) {
577 22684 : LookupIterator it(isolate, object, index);
578 45368 : MAYBE_RETURN_NULL(
579 : SetProperty(&it, value, StoreOrigin::kMaybeKeyed, Just(should_throw)));
580 22448 : return value;
581 : }
582 :
583 22459897 : ObjectSlot HeapObject::RawField(int byte_offset) const {
584 4586518312 : return ObjectSlot(FIELD_ADDR(*this, byte_offset));
585 : }
586 :
587 5824 : MaybeObjectSlot HeapObject::RawMaybeWeakField(int byte_offset) const {
588 2855372333 : return MaybeObjectSlot(FIELD_ADDR(*this, byte_offset));
589 : }
590 :
591 10304 : MapWord MapWord::FromMap(const Map map) { return MapWord(map.ptr()); }
592 :
593 0 : Map MapWord::ToMap() const { return Map::unchecked_cast(Object(value_)); }
594 :
595 668271826 : bool MapWord::IsForwardingAddress() const { return HAS_SMI_TAG(value_); }
596 :
597 : MapWord MapWord::FromForwardingAddress(HeapObject object) {
598 19322569 : return MapWord(object->ptr() - kHeapObjectTag);
599 : }
600 :
601 2 : HeapObject MapWord::ToForwardingAddress() {
602 : DCHECK(IsForwardingAddress());
603 4 : return HeapObject::FromAddress(value_);
604 : }
605 :
606 : #ifdef VERIFY_HEAP
607 : void HeapObject::VerifyObjectField(Isolate* isolate, int offset) {
608 : VerifyPointer(isolate, READ_FIELD(*this, offset));
609 : STATIC_ASSERT(!COMPRESS_POINTERS_BOOL || kTaggedSize == kInt32Size);
610 : }
611 :
612 : void HeapObject::VerifyMaybeObjectField(Isolate* isolate, int offset) {
613 : MaybeObject::VerifyMaybeObjectPointer(isolate,
614 : READ_WEAK_FIELD(*this, offset));
615 : STATIC_ASSERT(!COMPRESS_POINTERS_BOOL || kTaggedSize == kInt32Size);
616 : }
617 :
618 : void HeapObject::VerifySmiField(int offset) {
619 : CHECK(READ_FIELD(*this, offset)->IsSmi());
620 : STATIC_ASSERT(!COMPRESS_POINTERS_BOOL || kTaggedSize == kInt32Size);
621 : }
622 :
623 : #endif
624 :
625 : ReadOnlyRoots HeapObject::GetReadOnlyRoots() const {
626 : // TODO(v8:7464): When RO_SPACE is embedded, this will access a global
627 : // variable instead.
628 : return ReadOnlyRoots(GetHeapFromWritableObject(*this));
629 : }
630 :
631 5564685044 : Map HeapObject::map() const { return map_word().ToMap(); }
632 :
633 6154288 : void HeapObject::set_map(Map value) {
634 : if (!value.is_null()) {
635 : #ifdef VERIFY_HEAP
636 : GetHeapFromWritableObject(*this)->VerifyObjectLayoutChange(*this, value);
637 : #endif
638 : }
639 : set_map_word(MapWord::FromMap(value));
640 6154288 : if (!value.is_null()) {
641 : // TODO(1600) We are passing kNullAddress as a slot because maps can never
642 : // be on an evacuation candidate.
643 6154292 : MarkingBarrier(*this, ObjectSlot(kNullAddress), value);
644 : }
645 6154287 : }
646 :
647 : Map HeapObject::synchronized_map() const {
648 : return synchronized_map_word().ToMap();
649 : }
650 :
651 70359961 : void HeapObject::synchronized_set_map(Map value) {
652 : if (!value.is_null()) {
653 : #ifdef VERIFY_HEAP
654 : GetHeapFromWritableObject(*this)->VerifyObjectLayoutChange(*this, value);
655 : #endif
656 : }
657 : synchronized_set_map_word(MapWord::FromMap(value));
658 70359961 : if (!value.is_null()) {
659 : // TODO(1600) We are passing kNullAddress as a slot because maps can never
660 : // be on an evacuation candidate.
661 70359978 : MarkingBarrier(*this, ObjectSlot(kNullAddress), value);
662 : }
663 70359968 : }
664 :
665 :
666 : // Unsafe accessor omitting write barrier.
667 112 : void HeapObject::set_map_no_write_barrier(Map value) {
668 112 : if (!value.is_null()) {
669 : #ifdef VERIFY_HEAP
670 : GetHeapFromWritableObject(*this)->VerifyObjectLayoutChange(*this, value);
671 : #endif
672 : }
673 112 : set_map_word(MapWord::FromMap(value));
674 112 : }
675 :
676 71600395 : void HeapObject::set_map_after_allocation(Map value, WriteBarrierMode mode) {
677 10192 : set_map_word(MapWord::FromMap(value));
678 71600395 : if (mode != SKIP_WRITE_BARRIER) {
679 : DCHECK(!value.is_null());
680 : // TODO(1600) We are passing kNullAddress as a slot because maps can never
681 : // be on an evacuation candidate.
682 26656721 : MarkingBarrier(*this, ObjectSlot(kNullAddress), value);
683 : }
684 71600385 : }
685 :
686 17480420 : MapWordSlot HeapObject::map_slot() const {
687 24089376888 : return MapWordSlot(FIELD_ADDR(*this, kMapOffset));
688 : }
689 :
690 35056 : MapWord HeapObject::map_word() const {
691 35056 : return MapWord(map_slot().Relaxed_Load().ptr());
692 : }
693 :
694 17481096 : void HeapObject::set_map_word(MapWord map_word) {
695 17481096 : map_slot().Relaxed_Store(Object(map_word.value_));
696 17481096 : }
697 :
698 :
699 2 : MapWord HeapObject::synchronized_map_word() const {
700 2 : return MapWord(map_slot().Acquire_Load().ptr());
701 : }
702 :
703 : void HeapObject::synchronized_set_map_word(MapWord map_word) {
704 : map_slot().Release_Store(Object(map_word.value_));
705 : }
706 :
707 1617220128 : int HeapObject::Size() const { return SizeFromMap(map()); }
708 :
709 : inline bool IsSpecialReceiverInstanceType(InstanceType instance_type) {
710 : return instance_type <= LAST_SPECIAL_RECEIVER_TYPE;
711 : }
712 :
713 : // This should be in objects/map-inl.h, but can't, because of a cyclic
714 : // dependency.
715 : bool Map::IsSpecialReceiverMap() const {
716 : bool result = IsSpecialReceiverInstanceType(instance_type());
717 : DCHECK_IMPLIES(!result,
718 : !has_named_interceptor() && !is_access_check_needed());
719 : return result;
720 : }
721 :
722 : inline bool IsCustomElementsReceiverInstanceType(InstanceType instance_type) {
723 128238 : return instance_type <= LAST_CUSTOM_ELEMENTS_RECEIVER;
724 : }
725 :
726 : // This should be in objects/map-inl.h, but can't, because of a cyclic
727 : // dependency.
728 128238 : bool Map::IsCustomElementsReceiverMap() const {
729 128238 : return IsCustomElementsReceiverInstanceType(instance_type());
730 : }
731 :
732 6396 : bool Object::ToArrayLength(uint32_t* index) const {
733 5754808 : return Object::ToUint32(index);
734 : }
735 :
736 : bool Object::ToArrayIndex(uint32_t* index) const {
737 53931905 : return Object::ToUint32(index) && *index != kMaxUInt32;
738 : }
739 :
740 3579673 : bool Object::GetHeapObjectIfStrong(HeapObject* result) const {
741 3579673 : return GetHeapObject(result);
742 : }
743 :
744 312227 : bool Object::GetHeapObject(HeapObject* result) const {
745 8877231196 : if (!IsHeapObject()) return false;
746 2749876756 : *result = HeapObject::cast(*this);
747 27842 : return true;
748 : }
749 :
750 0 : HeapObject Object::GetHeapObject() const {
751 : DCHECK(IsHeapObject());
752 0 : return HeapObject::cast(*this);
753 : }
754 :
755 : int RegExpMatchInfo::NumberOfCaptureRegisters() {
756 : DCHECK_GE(length(), kLastMatchOverhead);
757 : Object obj = get(kNumberOfCapturesIndex);
758 : return Smi::ToInt(obj);
759 : }
760 :
761 : void RegExpMatchInfo::SetNumberOfCaptureRegisters(int value) {
762 : DCHECK_GE(length(), kLastMatchOverhead);
763 : set(kNumberOfCapturesIndex, Smi::FromInt(value));
764 : }
765 :
766 : String RegExpMatchInfo::LastSubject() {
767 : DCHECK_GE(length(), kLastMatchOverhead);
768 : return String::cast(get(kLastSubjectIndex));
769 : }
770 :
771 : void RegExpMatchInfo::SetLastSubject(String value) {
772 : DCHECK_GE(length(), kLastMatchOverhead);
773 4257687 : set(kLastSubjectIndex, value);
774 : }
775 :
776 : Object RegExpMatchInfo::LastInput() {
777 : DCHECK_GE(length(), kLastMatchOverhead);
778 : return get(kLastInputIndex);
779 : }
780 :
781 : void RegExpMatchInfo::SetLastInput(Object value) {
782 : DCHECK_GE(length(), kLastMatchOverhead);
783 4257732 : set(kLastInputIndex, value);
784 : }
785 :
786 : int RegExpMatchInfo::Capture(int i) {
787 : DCHECK_LT(i, NumberOfCaptureRegisters());
788 499288 : Object obj = get(kFirstCaptureIndex + i);
789 : return Smi::ToInt(obj);
790 : }
791 :
792 : void RegExpMatchInfo::SetCapture(int i, int value) {
793 : DCHECK_LT(i, NumberOfCaptureRegisters());
794 : set(kFirstCaptureIndex + i, Smi::FromInt(value));
795 : }
796 :
797 : WriteBarrierMode HeapObject::GetWriteBarrierMode(
798 : const DisallowHeapAllocation& promise) {
799 : return GetWriteBarrierModeForObject(*this, &promise);
800 : }
801 :
802 : // static
803 : AllocationAlignment HeapObject::RequiredAlignment(Map map) {
804 : #ifdef V8_COMPRESS_POINTERS
805 : // TODO(ishell, v8:8875): Consider using aligned allocations once the
806 : // allocation alignment inconsistency is fixed. For now we keep using
807 : // unaligned access since both x64 and arm64 architectures (where pointer
808 : // compression is supported) allow unaligned access to doubles and full words.
809 : #endif // V8_COMPRESS_POINTERS
810 : #ifdef V8_HOST_ARCH_32_BIT
811 : int instance_type = map->instance_type();
812 : if (instance_type == FIXED_FLOAT64_ARRAY_TYPE ||
813 : instance_type == FIXED_DOUBLE_ARRAY_TYPE) {
814 : return kDoubleAligned;
815 : }
816 : if (instance_type == HEAP_NUMBER_TYPE) return kDoubleUnaligned;
817 : #endif // V8_HOST_ARCH_32_BIT
818 : return kWordAligned;
819 : }
820 :
821 : Address HeapObject::GetFieldAddress(int field_offset) const {
822 : return FIELD_ADDR(*this, field_offset);
823 : }
824 :
825 : // static
826 239 : Maybe<bool> Object::GreaterThan(Isolate* isolate, Handle<Object> x,
827 : Handle<Object> y) {
828 239 : Maybe<ComparisonResult> result = Compare(isolate, x, y);
829 239 : if (result.IsJust()) {
830 239 : switch (result.FromJust()) {
831 : case ComparisonResult::kGreaterThan:
832 : return Just(true);
833 : case ComparisonResult::kLessThan:
834 : case ComparisonResult::kEqual:
835 : case ComparisonResult::kUndefined:
836 : return Just(false);
837 : }
838 : }
839 : return Nothing<bool>();
840 : }
841 :
842 :
843 : // static
844 221 : Maybe<bool> Object::GreaterThanOrEqual(Isolate* isolate, Handle<Object> x,
845 : Handle<Object> y) {
846 221 : Maybe<ComparisonResult> result = Compare(isolate, x, y);
847 221 : if (result.IsJust()) {
848 221 : switch (result.FromJust()) {
849 : case ComparisonResult::kEqual:
850 : case ComparisonResult::kGreaterThan:
851 : return Just(true);
852 : case ComparisonResult::kLessThan:
853 : case ComparisonResult::kUndefined:
854 : return Just(false);
855 : }
856 : }
857 : return Nothing<bool>();
858 : }
859 :
860 :
861 : // static
862 257 : Maybe<bool> Object::LessThan(Isolate* isolate, Handle<Object> x,
863 : Handle<Object> y) {
864 257 : Maybe<ComparisonResult> result = Compare(isolate, x, y);
865 257 : if (result.IsJust()) {
866 239 : switch (result.FromJust()) {
867 : case ComparisonResult::kLessThan:
868 : return Just(true);
869 : case ComparisonResult::kEqual:
870 : case ComparisonResult::kGreaterThan:
871 : case ComparisonResult::kUndefined:
872 : return Just(false);
873 : }
874 : }
875 : return Nothing<bool>();
876 : }
877 :
878 :
879 : // static
880 212 : Maybe<bool> Object::LessThanOrEqual(Isolate* isolate, Handle<Object> x,
881 : Handle<Object> y) {
882 212 : Maybe<ComparisonResult> result = Compare(isolate, x, y);
883 212 : if (result.IsJust()) {
884 212 : switch (result.FromJust()) {
885 : case ComparisonResult::kEqual:
886 : case ComparisonResult::kLessThan:
887 : return Just(true);
888 : case ComparisonResult::kGreaterThan:
889 : case ComparisonResult::kUndefined:
890 : return Just(false);
891 : }
892 : }
893 : return Nothing<bool>();
894 : }
895 :
896 919933 : MaybeHandle<Object> Object::GetPropertyOrElement(Isolate* isolate,
897 : Handle<Object> object,
898 : Handle<Name> name) {
899 919933 : LookupIterator it = LookupIterator::PropertyOrElement(isolate, object, name);
900 919938 : return GetProperty(&it);
901 : }
902 :
903 1059 : MaybeHandle<Object> Object::SetPropertyOrElement(
904 : Isolate* isolate, Handle<Object> object, Handle<Name> name,
905 : Handle<Object> value, Maybe<ShouldThrow> should_throw,
906 : StoreOrigin store_origin) {
907 1059 : LookupIterator it = LookupIterator::PropertyOrElement(isolate, object, name);
908 2118 : MAYBE_RETURN_NULL(SetProperty(&it, value, store_origin, should_throw));
909 987 : return value;
910 : }
911 :
912 16678 : MaybeHandle<Object> Object::GetPropertyOrElement(Handle<Object> receiver,
913 : Handle<Name> name,
914 : Handle<JSReceiver> holder) {
915 : LookupIterator it = LookupIterator::PropertyOrElement(holder->GetIsolate(),
916 16678 : receiver, name, holder);
917 16678 : return GetProperty(&it);
918 : }
919 :
920 : // static
921 34887838 : Object Object::GetSimpleHash(Object object) {
922 : DisallowHeapAllocation no_gc;
923 34887838 : if (object->IsSmi()) {
924 17538782 : uint32_t hash = ComputeUnseededHash(Smi::ToInt(object));
925 35077564 : return Smi::FromInt(hash & Smi::kMaxValue);
926 : }
927 17349056 : if (object->IsHeapNumber()) {
928 : double num = HeapNumber::cast(object)->value();
929 5779 : if (std::isnan(num)) return Smi::FromInt(Smi::kMaxValue);
930 : // Use ComputeUnseededHash for all values in Signed32 range, including -0,
931 : // which is considered equal to 0 because collections use SameValueZero.
932 : uint32_t hash;
933 : // Check range before conversion to avoid undefined behavior.
934 9650 : if (num >= kMinInt && num <= kMaxInt && FastI2D(FastD2I(num)) == num) {
935 1918 : hash = ComputeUnseededHash(FastD2I(num));
936 : } else {
937 : hash = ComputeLongHash(double_to_uint64(num));
938 : }
939 10424 : return Smi::FromInt(hash & Smi::kMaxValue);
940 : }
941 17343279 : if (object->IsName()) {
942 17281821 : uint32_t hash = Name::cast(object)->Hash();
943 34563642 : return Smi::FromInt(hash);
944 : }
945 61458 : if (object->IsOddball()) {
946 1998 : uint32_t hash = Oddball::cast(object)->to_string()->Hash();
947 3996 : return Smi::FromInt(hash);
948 : }
949 59460 : if (object->IsBigInt()) {
950 288 : uint32_t hash = BigInt::cast(object)->Hash();
951 576 : return Smi::FromInt(hash & Smi::kMaxValue);
952 : }
953 59172 : if (object->IsSharedFunctionInfo()) {
954 664 : uint32_t hash = SharedFunctionInfo::cast(object)->Hash();
955 1328 : return Smi::FromInt(hash & Smi::kMaxValue);
956 : }
957 : DCHECK(object->IsJSReceiver());
958 58508 : return object;
959 : }
960 :
961 24670589 : Object Object::GetHash() {
962 : DisallowHeapAllocation no_gc;
963 24670589 : Object hash = GetSimpleHash(*this);
964 24670593 : if (hash->IsSmi()) return hash;
965 :
966 : DCHECK(IsJSReceiver());
967 38014 : JSReceiver receiver = JSReceiver::cast(*this);
968 38014 : return receiver->GetIdentityHash();
969 : }
970 :
971 : Handle<Object> ObjectHashTableShape::AsHandle(Handle<Object> key) {
972 : return key;
973 : }
974 :
975 6983514 : Relocatable::Relocatable(Isolate* isolate) {
976 6983514 : isolate_ = isolate;
977 6983514 : prev_ = isolate->relocatable_top();
978 : isolate->set_relocatable_top(this);
979 : }
980 :
981 :
982 13967046 : Relocatable::~Relocatable() {
983 : DCHECK_EQ(isolate_->relocatable_top(), this);
984 6983523 : isolate_->set_relocatable_top(prev_);
985 0 : }
986 :
987 : // Predictably converts HeapObject or Address to uint32 by calculating
988 : // offset of the address in respective MemoryChunk.
989 : static inline uint32_t ObjectAddressForHashing(Address object) {
990 11933594 : uint32_t value = static_cast<uint32_t>(object);
991 11933594 : return value & kPageAlignmentMask;
992 : }
993 :
994 810 : static inline Handle<Object> MakeEntryPair(Isolate* isolate, uint32_t index,
995 : Handle<Object> value) {
996 810 : Handle<Object> key = isolate->factory()->Uint32ToString(index);
997 : Handle<FixedArray> entry_storage =
998 810 : isolate->factory()->NewUninitializedFixedArray(2);
999 : {
1000 : entry_storage->set(0, *key, SKIP_WRITE_BARRIER);
1001 : entry_storage->set(1, *value, SKIP_WRITE_BARRIER);
1002 : }
1003 : return isolate->factory()->NewJSArrayWithElements(entry_storage,
1004 810 : PACKED_ELEMENTS, 2);
1005 : }
1006 :
1007 816 : static inline Handle<Object> MakeEntryPair(Isolate* isolate, Handle<Object> key,
1008 : Handle<Object> value) {
1009 : Handle<FixedArray> entry_storage =
1010 816 : isolate->factory()->NewUninitializedFixedArray(2);
1011 : {
1012 : entry_storage->set(0, *key, SKIP_WRITE_BARRIER);
1013 : entry_storage->set(1, *value, SKIP_WRITE_BARRIER);
1014 : }
1015 : return isolate->factory()->NewJSArrayWithElements(entry_storage,
1016 816 : PACKED_ELEMENTS, 2);
1017 : }
1018 :
1019 : bool ScopeInfo::IsAsmModule() const {
1020 850176 : return IsAsmModuleField::decode(Flags());
1021 : }
1022 :
1023 : bool ScopeInfo::HasSimpleParameters() const {
1024 64246 : return HasSimpleParametersField::decode(Flags());
1025 : }
1026 :
1027 : #define FIELD_ACCESSORS(name) \
1028 : void ScopeInfo::Set##name(int value) { set(k##name, Smi::FromInt(value)); } \
1029 : int ScopeInfo::name() const { \
1030 : if (length() > 0) { \
1031 : return Smi::ToInt(get(k##name)); \
1032 : } else { \
1033 : return 0; \
1034 : } \
1035 : }
1036 425927545 : FOR_EACH_SCOPE_INFO_NUMERIC_FIELD(FIELD_ACCESSORS)
1037 : #undef FIELD_ACCESSORS
1038 :
1039 : FreshlyAllocatedBigInt FreshlyAllocatedBigInt::cast(Object object) {
1040 : SLOW_DCHECK(object->IsBigInt());
1041 : return FreshlyAllocatedBigInt(object->ptr());
1042 : }
1043 :
1044 : } // namespace internal
1045 : } // namespace v8
1046 :
1047 : #include "src/objects/object-macros-undef.h"
1048 :
1049 : #endif // V8_OBJECTS_INL_H_
|