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/slots-inl.h"
36 : #include "src/objects/smi-inl.h"
37 : #include "src/objects/template-objects.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 4678363971 : 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 1030140449 : int value = value_ << 1;
55 1030140449 : return Smi::FromInt(value >> 1);
56 : }
57 :
58 :
59 16324 : 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 31320444 : return map()->instance_type() == JS_GENERATOR_OBJECT_TYPE ||
76 20878627 : 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 15685270536 : 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 3181441671 : 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 269261758 : 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 558 : return IsNullOrUndefined(GetReadOnlyRoots());
134 : }
135 :
136 : bool HeapObject::IsUniqueName() const {
137 9298676 : return IsInternalizedString() || IsSymbol();
138 : }
139 :
140 : bool HeapObject::IsFunction() const {
141 : STATIC_ASSERT(LAST_FUNCTION_TYPE == LAST_TYPE);
142 929591 : return map()->instance_type() >= FIRST_FUNCTION_TYPE;
143 : }
144 :
145 13840299 : bool HeapObject::IsCallable() const { return map()->is_callable(); }
146 :
147 6401088 : 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 1073523 : return IsObjectTemplateInfo() || IsFunctionTemplateInfo();
155 : }
156 :
157 : bool HeapObject::IsConsString() const {
158 97896601 : if (!IsString()) return false;
159 97896597 : return StringShape(String::cast(*this)).IsCons();
160 : }
161 :
162 : bool HeapObject::IsThinString() const {
163 162559706 : if (!IsString()) return false;
164 162555150 : return StringShape(String::cast(*this)).IsThin();
165 : }
166 :
167 : bool HeapObject::IsSlicedString() const {
168 5934238 : if (!IsString()) return false;
169 5934240 : return StringShape(String::cast(*this)).IsSliced();
170 : }
171 :
172 : bool HeapObject::IsSeqString() const {
173 7495154 : if (!IsString()) return false;
174 7495154 : return StringShape(String::cast(*this)).IsSequential();
175 : }
176 :
177 : bool HeapObject::IsSeqOneByteString() const {
178 71333439 : if (!IsString()) return false;
179 197083458 : return StringShape(String::cast(*this)).IsSequential() &&
180 127619111 : String::cast(*this)->IsOneByteRepresentation();
181 : }
182 :
183 : bool HeapObject::IsSeqTwoByteString() const {
184 1948205 : if (!IsString()) return false;
185 236864 : return StringShape(String::cast(*this)).IsSequential() &&
186 157747 : String::cast(*this)->IsTwoByteRepresentation();
187 : }
188 :
189 : bool HeapObject::IsExternalString() const {
190 361916748 : if (!IsString()) return false;
191 81188395 : return StringShape(String::cast(*this)).IsExternal();
192 : }
193 :
194 : bool HeapObject::IsExternalOneByteString() const {
195 7628400 : if (!IsString()) return false;
196 15264336 : return StringShape(String::cast(*this)).IsExternal() &&
197 7635936 : String::cast(*this)->IsOneByteRepresentation();
198 : }
199 :
200 : bool HeapObject::IsExternalTwoByteString() const {
201 7620931 : if (!IsString()) return false;
202 15241935 : return StringShape(String::cast(*this)).IsExternal() &&
203 7621003 : String::cast(*this)->IsTwoByteRepresentation();
204 : }
205 :
206 190800364 : bool Object::IsNumber() const { return IsSmi() || IsHeapNumber(); }
207 :
208 1566 : bool Object::IsNumeric() const { return IsNumber() || IsBigInt(); }
209 :
210 : bool HeapObject::IsFiller() const {
211 226772323 : InstanceType instance_type = map()->instance_type();
212 226772324 : return instance_type == FREE_SPACE_TYPE || instance_type == FILLER_TYPE;
213 : }
214 :
215 : bool HeapObject::IsJSWeakCollection() const {
216 180104 : return IsJSWeakMap() || IsJSWeakSet();
217 : }
218 :
219 0 : bool HeapObject::IsJSCollection() const { return IsJSMap() || IsJSSet(); }
220 :
221 : bool HeapObject::IsPromiseReactionJobTask() const {
222 2485793 : 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 1923 : return map() == GetReadOnlyRoots().array_list_map() ||
231 1336 : *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 6361207 : return IsBytecodeArray() || IsCode();
277 : }
278 :
279 : bool HeapObject::IsStringWrapper() const {
280 1484289 : return IsJSValue() && JSValue::cast(*this)->value()->IsString();
281 : }
282 :
283 : bool HeapObject::IsBooleanWrapper() const {
284 21338 : 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 21230 : return IsJSValue() && JSValue::cast(*this)->value()->IsNumber();
293 : }
294 :
295 : bool HeapObject::IsBigIntWrapper() const {
296 21178 : return IsJSValue() && JSValue::cast(*this)->value()->IsBigInt();
297 : }
298 :
299 : bool HeapObject::IsSymbolWrapper() const {
300 21155 : return IsJSValue() && JSValue::cast(*this)->value()->IsSymbol();
301 : }
302 :
303 : bool HeapObject::IsJSArrayBufferView() const {
304 281221 : 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 11103181 : return IsSmi() || HeapObject::cast(*this)->map()->IsPrimitiveMap();
326 : }
327 :
328 : // static
329 : Maybe<bool> Object::IsArray(Handle<Object> object) {
330 2391324 : if (object->IsSmi()) return Just(false);
331 1195644 : Handle<HeapObject> heap_object = Handle<HeapObject>::cast(object);
332 2391288 : if (heap_object->IsJSArray()) return Just(true);
333 2331800 : if (!heap_object->IsJSProxy()) return Just(false);
334 1238 : return JSProxy::IsArray(Handle<JSProxy>::cast(object));
335 : }
336 :
337 87934891 : bool HeapObject::IsUndetectable() const { return map()->is_undetectable(); }
338 :
339 : bool HeapObject::IsAccessCheckNeeded() const {
340 35679050 : if (IsJSGlobalProxy()) {
341 56879 : const JSGlobalProxy proxy = JSGlobalProxy::cast(*this);
342 56879 : JSGlobalObject global = proxy->GetIsolate()->context()->global_object();
343 56879 : return proxy->IsDetachedFrom(global);
344 : }
345 35622171 : 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 1333328251 : STRUCT_LIST(MAKE_STRUCT_PREDICATE)
378 : #undef MAKE_STRUCT_PREDICATE
379 :
380 128906282 : double Object::Number() const {
381 : DCHECK(IsNumber());
382 : return IsSmi() ? static_cast<double>(Smi(this->ptr())->value())
383 374126129 : : HeapNumber::unchecked_cast(*this)->value();
384 : }
385 :
386 : bool Object::IsNaN() const {
387 4443 : return this->IsHeapNumber() && std::isnan(HeapNumber::cast(*this)->value());
388 : }
389 :
390 : bool Object::IsMinusZero() const {
391 6860 : return this->IsHeapNumber() &&
392 6860 : i::IsMinusZero(HeapNumber::cast(*this)->value());
393 : }
394 :
395 18214650 : OBJECT_CONSTRUCTORS_IMPL(RegExpMatchInfo, FixedArray)
396 84185059 : OBJECT_CONSTRUCTORS_IMPL(ScopeInfo, FixedArray)
397 : OBJECT_CONSTRUCTORS_IMPL(BigIntBase, HeapObject)
398 531546 : OBJECT_CONSTRUCTORS_IMPL(BigInt, BigIntBase)
399 : OBJECT_CONSTRUCTORS_IMPL(FreshlyAllocatedBigInt, BigIntBase)
400 :
401 8950 : OBJECT_CONSTRUCTORS_IMPL(TemplateObjectDescription, Tuple2)
402 :
403 : // ------------------------------------
404 : // Cast operations
405 :
406 265674 : CAST_ACCESSOR(BigInt)
407 9107325 : CAST_ACCESSOR(RegExpMatchInfo)
408 42092562 : CAST_ACCESSOR(ScopeInfo)
409 4475 : CAST_ACCESSOR(TemplateObjectDescription)
410 :
411 : bool Object::HasValidElements() {
412 : // Dictionary is covered under FixedArray.
413 : return IsFixedArray() || IsFixedDoubleArray() || IsFixedTypedArrayBase();
414 : }
415 :
416 11333749 : bool Object::FilterKey(PropertyFilter filter) {
417 : DCHECK(!IsPropertyCell());
418 11333749 : if (IsSymbol()) {
419 100820 : if (filter & SKIP_SYMBOLS) return true;
420 46270 : if (Symbol::cast(*this)->is_private()) return true;
421 : } else {
422 11232929 : if (filter & SKIP_STRINGS) return true;
423 : }
424 : return false;
425 : }
426 :
427 16870246 : Representation Object::OptimalRepresentation() {
428 16870246 : if (!FLAG_track_fields) return Representation::Tagged();
429 16870252 : if (IsSmi()) {
430 : return Representation::Smi();
431 24176631 : } else if (FLAG_track_double_fields && IsHeapNumber()) {
432 : return Representation::Double();
433 24143691 : } else if (FLAG_track_computed_fields && IsUninitialized()) {
434 : return Representation::None();
435 11856785 : } else if (FLAG_track_heap_object_fields) {
436 : DCHECK(IsHeapObject());
437 : return Representation::HeapObject();
438 : } else {
439 : return Representation::Tagged();
440 : }
441 : }
442 :
443 :
444 13136497 : ElementsKind Object::OptimalElementsKind() {
445 13136497 : if (IsSmi()) return PACKED_SMI_ELEMENTS;
446 2714478 : if (IsNumber()) return PACKED_DOUBLE_ELEMENTS;
447 1564157 : return PACKED_ELEMENTS;
448 : }
449 :
450 :
451 40419321 : bool Object::FitsRepresentation(Representation representation) {
452 40419321 : if (FLAG_track_fields && representation.IsSmi()) {
453 4790932 : return IsSmi();
454 35628389 : } else if (FLAG_track_double_fields && representation.IsDouble()) {
455 69136 : return IsMutableHeapNumber() || IsNumber();
456 35593821 : } else if (FLAG_track_heap_object_fields && representation.IsHeapObject()) {
457 35005551 : return IsHeapObject();
458 588270 : } else if (FLAG_track_fields && representation.IsNone()) {
459 : return false;
460 : }
461 405057 : return true;
462 : }
463 :
464 62976133 : bool Object::ToUint32(uint32_t* value) const {
465 62976134 : if (IsSmi()) {
466 47480931 : int num = Smi::ToInt(*this);
467 47480932 : if (num < 0) return false;
468 47461265 : *value = static_cast<uint32_t>(num);
469 47461265 : return true;
470 : }
471 15495204 : if (IsHeapNumber()) {
472 : double num = HeapNumber::cast(*this)->value();
473 6289 : return DoubleToUint32IfEqualToSelf(num, value);
474 : }
475 : return false;
476 : }
477 :
478 : // static
479 16194697 : MaybeHandle<JSReceiver> Object::ToObject(Isolate* isolate,
480 : Handle<Object> object,
481 : const char* method_name) {
482 32389394 : if (object->IsJSReceiver()) return Handle<JSReceiver>::cast(object);
483 7102 : return ToObjectImpl(isolate, object, method_name);
484 : }
485 :
486 :
487 : // static
488 6376784 : MaybeHandle<Name> Object::ToName(Isolate* isolate, Handle<Object> input) {
489 12753570 : if (input->IsName()) return Handle<Name>::cast(input);
490 77523 : return ConvertToName(isolate, input);
491 : }
492 :
493 : // static
494 262908 : MaybeHandle<Object> Object::ToPropertyKey(Isolate* isolate,
495 : Handle<Object> value) {
496 968692 : if (value->IsSmi() || HeapObject::cast(*value)->IsName()) return value;
497 486 : return ConvertToPropertyKey(isolate, value);
498 : }
499 :
500 : // static
501 135058 : MaybeHandle<Object> Object::ToPrimitive(Handle<Object> input,
502 : ToPrimitiveHint hint) {
503 270116 : if (input->IsPrimitive()) return input;
504 6602 : return JSReceiver::ToPrimitive(Handle<JSReceiver>::cast(input), hint);
505 : }
506 :
507 : // static
508 7481264 : MaybeHandle<Object> Object::ToNumber(Isolate* isolate, Handle<Object> input) {
509 14962528 : if (input->IsNumber()) return input; // Shortcut.
510 2688777 : return ConvertToNumberOrNumeric(isolate, input, Conversion::kToNumber);
511 : }
512 :
513 : // static
514 5490 : MaybeHandle<Object> Object::ToNumeric(Isolate* isolate, Handle<Object> input) {
515 17312 : if (input->IsNumber() || input->IsBigInt()) return input; // Shortcut.
516 1375 : return ConvertToNumberOrNumeric(isolate, input, Conversion::kToNumeric);
517 : }
518 :
519 : // static
520 4071491 : MaybeHandle<Object> Object::ToInteger(Isolate* isolate, Handle<Object> input) {
521 8142986 : if (input->IsSmi()) return input;
522 105511 : return ConvertToInteger(isolate, input);
523 : }
524 :
525 : // static
526 2340 : MaybeHandle<Object> Object::ToInt32(Isolate* isolate, Handle<Object> input) {
527 4680 : if (input->IsSmi()) return input;
528 1316 : return ConvertToInt32(isolate, input);
529 : }
530 :
531 : // static
532 432545 : MaybeHandle<Object> Object::ToUint32(Isolate* isolate, Handle<Object> input) {
533 865126 : if (input->IsSmi()) return handle(Smi::cast(*input)->ToUint32Smi(), isolate);
534 432509 : return ConvertToUint32(isolate, input);
535 : }
536 :
537 : // static
538 15598391 : MaybeHandle<String> Object::ToString(Isolate* isolate, Handle<Object> input) {
539 31196791 : if (input->IsString()) return Handle<String>::cast(input);
540 8268076 : return ConvertToString(isolate, input);
541 : }
542 :
543 : // static
544 64180 : MaybeHandle<Object> Object::ToLength(Isolate* isolate, Handle<Object> input) {
545 128360 : if (input->IsSmi()) {
546 185574 : int value = std::max(Smi::ToInt(*input), 0);
547 61858 : return handle(Smi::FromInt(value), isolate);
548 : }
549 2322 : return ConvertToLength(isolate, input);
550 : }
551 :
552 : // static
553 10895 : MaybeHandle<Object> Object::ToIndex(Isolate* isolate, Handle<Object> input,
554 : MessageTemplate error_index) {
555 31470 : if (input->IsSmi() && Smi::ToInt(*input) >= 0) return input;
556 1273 : return ConvertToIndex(isolate, input, error_index);
557 : }
558 :
559 2397415 : MaybeHandle<Object> Object::GetProperty(Isolate* isolate, Handle<Object> object,
560 : Handle<Name> name) {
561 2397415 : LookupIterator it(isolate, object, name);
562 2492613 : if (!it.IsFound()) return it.factory()->undefined_value();
563 2302217 : return GetProperty(&it);
564 : }
565 :
566 1184905 : MaybeHandle<Object> Object::GetElement(Isolate* isolate, Handle<Object> object,
567 : uint32_t index) {
568 1184905 : LookupIterator it(isolate, object, index);
569 2364832 : if (!it.IsFound()) return it.factory()->undefined_value();
570 4978 : return GetProperty(&it);
571 : }
572 :
573 22635 : MaybeHandle<Object> Object::SetElement(Isolate* isolate, Handle<Object> object,
574 : uint32_t index, Handle<Object> value,
575 : ShouldThrow should_throw) {
576 22635 : LookupIterator it(isolate, object, index);
577 22635 : MAYBE_RETURN_NULL(
578 : SetProperty(&it, value, StoreOrigin::kMaybeKeyed, Just(should_throw)));
579 22443 : return value;
580 : }
581 :
582 23630233 : ObjectSlot HeapObject::RawField(int byte_offset) const {
583 4294065924 : return ObjectSlot(FIELD_ADDR(*this, byte_offset));
584 : }
585 :
586 19399614 : ObjectSlot HeapObject::RawField(const HeapObject obj, int byte_offset) {
587 820944771 : return ObjectSlot(FIELD_ADDR(obj, byte_offset));
588 : }
589 :
590 5824 : MaybeObjectSlot HeapObject::RawMaybeWeakField(int byte_offset) const {
591 2759659935 : return MaybeObjectSlot(FIELD_ADDR(*this, byte_offset));
592 : }
593 :
594 : MaybeObjectSlot HeapObject::RawMaybeWeakField(HeapObject obj, int byte_offset) {
595 72999386 : return MaybeObjectSlot(FIELD_ADDR(obj, byte_offset));
596 : }
597 :
598 228982998 : MapWord MapWord::FromMap(const Map map) { return MapWord(map.ptr()); }
599 :
600 121555945 : Map MapWord::ToMap() const { return Map::unchecked_cast(Object(value_)); }
601 :
602 719590142 : bool MapWord::IsForwardingAddress() const { return HAS_SMI_TAG(value_); }
603 :
604 116649030 : MapWord MapWord::FromForwardingAddress(HeapObject object) {
605 118529091 : return MapWord(object->ptr() - kHeapObjectTag);
606 : }
607 :
608 643746 : HeapObject MapWord::ToForwardingAddress() {
609 : DCHECK(IsForwardingAddress());
610 1287492 : return HeapObject::FromAddress(value_);
611 : }
612 :
613 : #ifdef VERIFY_HEAP
614 : void HeapObject::VerifyObjectField(Isolate* isolate, int offset) {
615 : VerifyPointer(isolate, READ_FIELD(*this, offset));
616 : #ifdef V8_COMPRESS_POINTERS
617 : STATIC_ASSERT(kTaggedSize == kSystemPointerSize);
618 : // Ensure upper 32-bits are zeros.
619 : Address value = *(FullObjectSlot(FIELD_ADDR(*this, offset)).location());
620 : CHECK_EQ(kNullAddress, RoundDown<kPtrComprIsolateRootAlignment>(value));
621 : #endif
622 : }
623 :
624 : void HeapObject::VerifyMaybeObjectField(Isolate* isolate, int offset) {
625 : MaybeObject::VerifyMaybeObjectPointer(isolate,
626 : READ_WEAK_FIELD(*this, offset));
627 : #ifdef V8_COMPRESS_POINTERS
628 : STATIC_ASSERT(kTaggedSize == kSystemPointerSize);
629 : // Ensure upper 32-bits are zeros.
630 : Address value = *(FullObjectSlot(FIELD_ADDR(*this, offset)).location());
631 : CHECK_EQ(kNullAddress, RoundDown<kPtrComprIsolateRootAlignment>(value));
632 : #endif
633 : }
634 :
635 : void HeapObject::VerifySmiField(int offset) {
636 : CHECK(READ_FIELD(*this, offset)->IsSmi());
637 : #ifdef V8_COMPRESS_POINTERS
638 : STATIC_ASSERT(kTaggedSize == kSystemPointerSize);
639 : // Ensure upper 32-bits are zeros.
640 : Address value = *(FullObjectSlot(FIELD_ADDR(*this, offset)).location());
641 : CHECK_EQ(kNullAddress, RoundDown<kPtrComprIsolateRootAlignment>(value));
642 : #endif
643 : }
644 :
645 : #endif
646 :
647 797372169 : ReadOnlyRoots HeapObject::GetReadOnlyRoots() const {
648 : // TODO(v8:7464): When RO_SPACE is embedded, this will access a global
649 : // variable instead.
650 1594744362 : return ReadOnlyRoots(GetHeapFromWritableObject(*this));
651 : }
652 :
653 22841857036 : Map HeapObject::map() const { return map_word().ToMap(); }
654 :
655 6104693 : void HeapObject::set_map(Map value) {
656 : if (!value.is_null()) {
657 : #ifdef VERIFY_HEAP
658 : GetHeapFromWritableObject(*this)->VerifyObjectLayoutChange(*this, value);
659 : #endif
660 : }
661 : set_map_word(MapWord::FromMap(value));
662 6104693 : if (!value.is_null()) {
663 : // TODO(1600) We are passing kNullAddress as a slot because maps can never
664 : // be on an evacuation candidate.
665 6104693 : MarkingBarrier(*this, ObjectSlot(kNullAddress), value);
666 : }
667 6104691 : }
668 :
669 : Map HeapObject::synchronized_map() const {
670 : return synchronized_map_word().ToMap();
671 : }
672 :
673 57696713 : void HeapObject::synchronized_set_map(Map value) {
674 : if (!value.is_null()) {
675 : #ifdef VERIFY_HEAP
676 : GetHeapFromWritableObject(*this)->VerifyObjectLayoutChange(*this, value);
677 : #endif
678 : }
679 : synchronized_set_map_word(MapWord::FromMap(value));
680 57696713 : if (!value.is_null()) {
681 : // TODO(1600) We are passing kNullAddress as a slot because maps can never
682 : // be on an evacuation candidate.
683 57696717 : MarkingBarrier(*this, ObjectSlot(kNullAddress), value);
684 : }
685 57696711 : }
686 :
687 :
688 : // Unsafe accessor omitting write barrier.
689 112 : void HeapObject::set_map_no_write_barrier(Map value) {
690 112 : if (!value.is_null()) {
691 : #ifdef VERIFY_HEAP
692 : GetHeapFromWritableObject(*this)->VerifyObjectLayoutChange(*this, value);
693 : #endif
694 : }
695 112 : set_map_word(MapWord::FromMap(value));
696 112 : }
697 :
698 397687634 : void HeapObject::set_map_after_allocation(Map value, WriteBarrierMode mode) {
699 10416 : set_map_word(MapWord::FromMap(value));
700 397687634 : if (mode != SKIP_WRITE_BARRIER) {
701 : DCHECK(!value.is_null());
702 : // TODO(1600) We are passing kNullAddress as a slot because maps can never
703 : // be on an evacuation candidate.
704 23693975 : MarkingBarrier(*this, ObjectSlot(kNullAddress), value);
705 : }
706 397687642 : }
707 :
708 360300446 : MapWordSlot HeapObject::map_slot() const {
709 24547568086 : return MapWordSlot(FIELD_ADDR(*this, kMapOffset));
710 : }
711 :
712 0 : MapWord HeapObject::map_word() const {
713 0 : return MapWord(map_slot().Relaxed_Load().ptr());
714 : }
715 :
716 116624311 : void HeapObject::set_map_word(MapWord map_word) {
717 116624311 : map_slot().Relaxed_Store(Object(map_word.value_));
718 116624251 : }
719 :
720 :
721 1146003 : MapWord HeapObject::synchronized_map_word() const {
722 1146003 : return MapWord(map_slot().Acquire_Load().ptr());
723 : }
724 :
725 : void HeapObject::synchronized_set_map_word(MapWord map_word) {
726 : map_slot().Release_Store(Object(map_word.value_));
727 : }
728 :
729 1687364622 : int HeapObject::Size() const { return SizeFromMap(map()); }
730 :
731 : inline bool IsSpecialReceiverInstanceType(InstanceType instance_type) {
732 96666 : return instance_type <= LAST_SPECIAL_RECEIVER_TYPE;
733 : }
734 :
735 : // This should be in objects/map-inl.h, but can't, because of a cyclic
736 : // dependency.
737 96666 : bool Map::IsSpecialReceiverMap() const {
738 : bool result = IsSpecialReceiverInstanceType(instance_type());
739 : DCHECK_IMPLIES(!result,
740 : !has_named_interceptor() && !is_access_check_needed());
741 96666 : return result;
742 : }
743 :
744 : inline bool IsCustomElementsReceiverInstanceType(InstanceType instance_type) {
745 419212 : return instance_type <= LAST_CUSTOM_ELEMENTS_RECEIVER;
746 : }
747 :
748 : // This should be in objects/map-inl.h, but can't, because of a cyclic
749 : // dependency.
750 419212 : bool Map::IsCustomElementsReceiverMap() const {
751 419212 : return IsCustomElementsReceiverInstanceType(instance_type());
752 : }
753 :
754 101230 : bool Object::ToArrayLength(uint32_t* index) const {
755 8220392 : return Object::ToUint32(index);
756 : }
757 :
758 2647 : bool Object::ToArrayIndex(uint32_t* index) const {
759 54719385 : return Object::ToUint32(index) && *index != kMaxUInt32;
760 : }
761 :
762 5957920733 : bool Object::GetHeapObjectIfStrong(HeapObject* result) const {
763 5957920733 : return GetHeapObject(result);
764 : }
765 :
766 6973574364 : bool Object::GetHeapObject(HeapObject* result) const {
767 6975615880 : if (!IsHeapObject()) return false;
768 6415171309 : *result = HeapObject::cast(*this);
769 6415171309 : return true;
770 : }
771 :
772 0 : HeapObject Object::GetHeapObject() const {
773 : DCHECK(IsHeapObject());
774 0 : return HeapObject::cast(*this);
775 : }
776 :
777 255359 : int RegExpMatchInfo::NumberOfCaptureRegisters() {
778 : DCHECK_GE(length(), kLastMatchOverhead);
779 255359 : Object obj = get(kNumberOfCapturesIndex);
780 255359 : return Smi::ToInt(obj);
781 : }
782 :
783 : void RegExpMatchInfo::SetNumberOfCaptureRegisters(int value) {
784 : DCHECK_GE(length(), kLastMatchOverhead);
785 : set(kNumberOfCapturesIndex, Smi::FromInt(value));
786 : }
787 :
788 379157 : String RegExpMatchInfo::LastSubject() {
789 : DCHECK_GE(length(), kLastMatchOverhead);
790 379157 : return String::cast(get(kLastSubjectIndex));
791 : }
792 :
793 : void RegExpMatchInfo::SetLastSubject(String value) {
794 : DCHECK_GE(length(), kLastMatchOverhead);
795 4256045 : set(kLastSubjectIndex, value);
796 : }
797 :
798 : Object RegExpMatchInfo::LastInput() {
799 : DCHECK_GE(length(), kLastMatchOverhead);
800 : return get(kLastInputIndex);
801 : }
802 :
803 : void RegExpMatchInfo::SetLastInput(Object value) {
804 : DCHECK_GE(length(), kLastMatchOverhead);
805 4256090 : set(kLastInputIndex, value);
806 : }
807 :
808 636159 : int RegExpMatchInfo::Capture(int i) {
809 : DCHECK_LT(i, NumberOfCaptureRegisters());
810 1272318 : Object obj = get(kFirstCaptureIndex + i);
811 636159 : return Smi::ToInt(obj);
812 : }
813 :
814 10917592 : void RegExpMatchInfo::SetCapture(int i, int value) {
815 : DCHECK_LT(i, NumberOfCaptureRegisters());
816 : set(kFirstCaptureIndex + i, Smi::FromInt(value));
817 10917592 : }
818 :
819 21 : WriteBarrierMode HeapObject::GetWriteBarrierMode(
820 : const DisallowHeapAllocation& promise) {
821 40225367 : return GetWriteBarrierModeForObject(*this, &promise);
822 : }
823 :
824 117518557 : AllocationAlignment HeapObject::RequiredAlignment(Map map) {
825 : #ifdef V8_HOST_ARCH_32_BIT
826 : int instance_type = map->instance_type();
827 : if (instance_type == FIXED_FLOAT64_ARRAY_TYPE ||
828 : instance_type == FIXED_DOUBLE_ARRAY_TYPE) {
829 : return kDoubleAligned;
830 : }
831 : if (instance_type == HEAP_NUMBER_TYPE) return kDoubleUnaligned;
832 : #endif // V8_HOST_ARCH_32_BIT
833 117518557 : return kWordAligned;
834 : }
835 :
836 : Address HeapObject::GetFieldAddress(int field_offset) const {
837 57555 : return FIELD_ADDR(*this, field_offset);
838 : }
839 :
840 16861 : ACCESSORS(TemplateObjectDescription, raw_strings, FixedArray, kRawStringsOffset)
841 16861 : ACCESSORS(TemplateObjectDescription, cooked_strings, FixedArray,
842 : kCookedStringsOffset)
843 :
844 : // static
845 239 : Maybe<bool> Object::GreaterThan(Isolate* isolate, Handle<Object> x,
846 : Handle<Object> y) {
847 239 : Maybe<ComparisonResult> result = Compare(isolate, x, y);
848 239 : if (result.IsJust()) {
849 239 : switch (result.FromJust()) {
850 : case ComparisonResult::kGreaterThan:
851 : return Just(true);
852 : case ComparisonResult::kLessThan:
853 : case ComparisonResult::kEqual:
854 : case ComparisonResult::kUndefined:
855 : return Just(false);
856 : }
857 : }
858 : return Nothing<bool>();
859 : }
860 :
861 :
862 : // static
863 221 : Maybe<bool> Object::GreaterThanOrEqual(Isolate* isolate, Handle<Object> x,
864 : Handle<Object> y) {
865 221 : Maybe<ComparisonResult> result = Compare(isolate, x, y);
866 221 : if (result.IsJust()) {
867 221 : switch (result.FromJust()) {
868 : case ComparisonResult::kEqual:
869 : case ComparisonResult::kGreaterThan:
870 : return Just(true);
871 : case ComparisonResult::kLessThan:
872 : case ComparisonResult::kUndefined:
873 : return Just(false);
874 : }
875 : }
876 : return Nothing<bool>();
877 : }
878 :
879 :
880 : // static
881 257 : Maybe<bool> Object::LessThan(Isolate* isolate, Handle<Object> x,
882 : Handle<Object> y) {
883 257 : Maybe<ComparisonResult> result = Compare(isolate, x, y);
884 257 : if (result.IsJust()) {
885 239 : switch (result.FromJust()) {
886 : case ComparisonResult::kLessThan:
887 : return Just(true);
888 : case ComparisonResult::kEqual:
889 : case ComparisonResult::kGreaterThan:
890 : case ComparisonResult::kUndefined:
891 : return Just(false);
892 : }
893 : }
894 : return Nothing<bool>();
895 : }
896 :
897 :
898 : // static
899 212 : Maybe<bool> Object::LessThanOrEqual(Isolate* isolate, Handle<Object> x,
900 : Handle<Object> y) {
901 212 : Maybe<ComparisonResult> result = Compare(isolate, x, y);
902 212 : if (result.IsJust()) {
903 212 : switch (result.FromJust()) {
904 : case ComparisonResult::kEqual:
905 : case ComparisonResult::kLessThan:
906 : return Just(true);
907 : case ComparisonResult::kGreaterThan:
908 : case ComparisonResult::kUndefined:
909 : return Just(false);
910 : }
911 : }
912 : return Nothing<bool>();
913 : }
914 :
915 925786 : MaybeHandle<Object> Object::GetPropertyOrElement(Isolate* isolate,
916 : Handle<Object> object,
917 : Handle<Name> name) {
918 925786 : LookupIterator it = LookupIterator::PropertyOrElement(isolate, object, name);
919 925786 : return GetProperty(&it);
920 : }
921 :
922 1591 : MaybeHandle<Object> Object::SetPropertyOrElement(
923 : Isolate* isolate, Handle<Object> object, Handle<Name> name,
924 : Handle<Object> value, Maybe<ShouldThrow> should_throw,
925 : StoreOrigin store_origin) {
926 1591 : LookupIterator it = LookupIterator::PropertyOrElement(isolate, object, name);
927 1591 : MAYBE_RETURN_NULL(SetProperty(&it, value, store_origin, should_throw));
928 1537 : return value;
929 : }
930 :
931 16091 : MaybeHandle<Object> Object::GetPropertyOrElement(Handle<Object> receiver,
932 : Handle<Name> name,
933 : Handle<JSReceiver> holder) {
934 : LookupIterator it = LookupIterator::PropertyOrElement(holder->GetIsolate(),
935 16091 : receiver, name, holder);
936 16091 : return GetProperty(&it);
937 : }
938 :
939 : // static
940 34885727 : Object Object::GetSimpleHash(Object object) {
941 : DisallowHeapAllocation no_gc;
942 34885728 : if (object->IsSmi()) {
943 17539764 : uint32_t hash = ComputeUnseededHash(Smi::ToInt(object));
944 35079528 : return Smi::FromInt(hash & Smi::kMaxValue);
945 : }
946 17345964 : if (object->IsHeapNumber()) {
947 : double num = HeapNumber::cast(object)->value();
948 4382 : if (std::isnan(num)) return Smi::FromInt(Smi::kMaxValue);
949 : // Use ComputeUnseededHash for all values in Signed32 range, including -0,
950 : // which is considered equal to 0 because collections use SameValueZero.
951 : uint32_t hash;
952 : // Check range before conversion to avoid undefined behavior.
953 6856 : if (num >= kMinInt && num <= kMaxInt && FastI2D(FastD2I(num)) == num) {
954 521 : hash = ComputeUnseededHash(FastD2I(num));
955 : } else {
956 : hash = ComputeLongHash(double_to_uint64(num));
957 : }
958 7630 : return Smi::FromInt(hash & Smi::kMaxValue);
959 : }
960 17341578 : if (object->IsName()) {
961 17280818 : uint32_t hash = Name::cast(object)->Hash();
962 34561644 : return Smi::FromInt(hash);
963 : }
964 60760 : if (object->IsOddball()) {
965 1998 : uint32_t hash = Oddball::cast(object)->to_string()->Hash();
966 3996 : return Smi::FromInt(hash);
967 : }
968 58762 : if (object->IsBigInt()) {
969 288 : uint32_t hash = BigInt::cast(object)->Hash();
970 576 : return Smi::FromInt(hash & Smi::kMaxValue);
971 : }
972 : DCHECK(object->IsJSReceiver());
973 58474 : return object;
974 : }
975 :
976 24674274 : Object Object::GetHash() {
977 : DisallowHeapAllocation no_gc;
978 24674274 : Object hash = GetSimpleHash(*this);
979 24674273 : if (hash->IsSmi()) return hash;
980 :
981 : DCHECK(IsJSReceiver());
982 38014 : JSReceiver receiver = JSReceiver::cast(*this);
983 38014 : return receiver->GetIdentityHash();
984 : }
985 :
986 : Handle<Object> ObjectHashTableShape::AsHandle(Handle<Object> key) {
987 : return key;
988 : }
989 :
990 13626260 : Relocatable::Relocatable(Isolate* isolate) {
991 6813130 : isolate_ = isolate;
992 6813130 : prev_ = isolate->relocatable_top();
993 : isolate->set_relocatable_top(this);
994 : }
995 :
996 :
997 6813136 : Relocatable::~Relocatable() {
998 : DCHECK_EQ(isolate_->relocatable_top(), this);
999 6813136 : isolate_->set_relocatable_top(prev_);
1000 0 : }
1001 :
1002 : // Predictably converts HeapObject or Address to uint32 by calculating
1003 : // offset of the address in respective MemoryChunk.
1004 : static inline uint32_t ObjectAddressForHashing(Address object) {
1005 12679066 : uint32_t value = static_cast<uint32_t>(object);
1006 12679066 : return value & kPageAlignmentMask;
1007 : }
1008 :
1009 810 : static inline Handle<Object> MakeEntryPair(Isolate* isolate, uint32_t index,
1010 : Handle<Object> value) {
1011 810 : Handle<Object> key = isolate->factory()->Uint32ToString(index);
1012 : Handle<FixedArray> entry_storage =
1013 810 : isolate->factory()->NewUninitializedFixedArray(2);
1014 : {
1015 810 : entry_storage->set(0, *key, SKIP_WRITE_BARRIER);
1016 810 : entry_storage->set(1, *value, SKIP_WRITE_BARRIER);
1017 : }
1018 : return isolate->factory()->NewJSArrayWithElements(entry_storage,
1019 810 : PACKED_ELEMENTS, 2);
1020 : }
1021 :
1022 816 : static inline Handle<Object> MakeEntryPair(Isolate* isolate, Handle<Object> key,
1023 : Handle<Object> value) {
1024 : Handle<FixedArray> entry_storage =
1025 816 : isolate->factory()->NewUninitializedFixedArray(2);
1026 : {
1027 816 : entry_storage->set(0, *key, SKIP_WRITE_BARRIER);
1028 816 : entry_storage->set(1, *value, SKIP_WRITE_BARRIER);
1029 : }
1030 : return isolate->factory()->NewJSArrayWithElements(entry_storage,
1031 816 : PACKED_ELEMENTS, 2);
1032 : }
1033 :
1034 : bool ScopeInfo::IsAsmModule() const {
1035 847921 : return IsAsmModuleField::decode(Flags());
1036 : }
1037 :
1038 : bool ScopeInfo::HasSimpleParameters() const {
1039 63608 : return HasSimpleParametersField::decode(Flags());
1040 : }
1041 :
1042 : #define FIELD_ACCESSORS(name) \
1043 : void ScopeInfo::Set##name(int value) { set(k##name, Smi::FromInt(value)); } \
1044 : int ScopeInfo::name() const { \
1045 : if (length() > 0) { \
1046 : return Smi::ToInt(get(k##name)); \
1047 : } else { \
1048 : return 0; \
1049 : } \
1050 : }
1051 422951813 : FOR_EACH_SCOPE_INFO_NUMERIC_FIELD(FIELD_ACCESSORS)
1052 : #undef FIELD_ACCESSORS
1053 :
1054 : FreshlyAllocatedBigInt FreshlyAllocatedBigInt::cast(Object object) {
1055 : SLOW_DCHECK(object->IsBigInt());
1056 : return FreshlyAllocatedBigInt(object->ptr());
1057 : }
1058 :
1059 : } // namespace internal
1060 : } // namespace v8
1061 :
1062 : #include "src/objects/object-macros-undef.h"
1063 :
1064 : #endif // V8_OBJECTS_INL_H_
|