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 4862873093 : PropertyDetails::PropertyDetails(Smi smi) { value_ = smi->value(); }
50 :
51 : 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 1080960593 : int value = value_ << 1;
55 1080960593 : 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 12671342 : return map()->instance_type() == JS_GENERATOR_OBJECT_TYPE ||
76 21079179 : 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 10769793885 : 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 101610299 : 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 267992365 : 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 9298855 : return IsInternalizedString() || IsSymbol();
138 : }
139 :
140 : bool HeapObject::IsFunction() const {
141 : STATIC_ASSERT(LAST_FUNCTION_TYPE == LAST_TYPE);
142 3706 : return map()->instance_type() >= FIRST_FUNCTION_TYPE;
143 : }
144 :
145 7868228 : 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 99810704 : if (!IsString()) return false;
159 13318390 : return StringShape(String::cast(*this)).IsCons();
160 : }
161 :
162 : bool HeapObject::IsThinString() const {
163 172707868 : if (!IsString()) return false;
164 234788 : return StringShape(String::cast(*this)).IsThin();
165 : }
166 :
167 : bool HeapObject::IsSlicedString() const {
168 5979851 : if (!IsString()) return false;
169 223110 : return StringShape(String::cast(*this)).IsSliced();
170 : }
171 :
172 : bool HeapObject::IsSeqString() const {
173 7618503 : if (!IsString()) return false;
174 0 : return StringShape(String::cast(*this)).IsSequential();
175 : }
176 :
177 : bool HeapObject::IsSeqOneByteString() const {
178 72662038 : if (!IsString()) return false;
179 130362304 : return StringShape(String::cast(*this)).IsSequential() &&
180 111486 : String::cast(*this)->IsOneByteRepresentation();
181 : }
182 :
183 : bool HeapObject::IsSeqTwoByteString() const {
184 1984649 : if (!IsString()) return false;
185 229476 : return StringShape(String::cast(*this)).IsSequential() &&
186 70612 : String::cast(*this)->IsTwoByteRepresentation();
187 : }
188 :
189 : bool HeapObject::IsExternalString() const {
190 384239424 : if (!IsString()) return false;
191 0 : return StringShape(String::cast(*this)).IsExternal();
192 : }
193 :
194 : bool HeapObject::IsExternalOneByteString() const {
195 7737504 : if (!IsString()) return false;
196 7749030 : return StringShape(String::cast(*this)).IsExternal() &&
197 3856 : String::cast(*this)->IsOneByteRepresentation();
198 : }
199 :
200 : bool HeapObject::IsExternalTwoByteString() const {
201 7729895 : if (!IsString()) return false;
202 7729970 : return StringShape(String::cast(*this)).IsExternal() &&
203 : String::cast(*this)->IsTwoByteRepresentation();
204 : }
205 :
206 208158347 : 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 413387294 : 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 2499513 : 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 6571733 : return IsBytecodeArray() || IsCode();
277 : }
278 :
279 : bool HeapObject::IsStringWrapper() const {
280 1597994 : 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 3993625 : return IsSmi() || HeapObject::cast(*this)->map()->IsPrimitiveMap();
326 : }
327 :
328 : // static
329 : Maybe<bool> Object::IsArray(Handle<Object> object) {
330 1181824 : if (object->IsSmi()) return Just(false);
331 : Handle<HeapObject> heap_object = Handle<HeapObject>::cast(object);
332 1181806 : if (heap_object->IsJSArray()) return Just(true);
333 1152300 : if (!heap_object->IsJSProxy()) return Just(false);
334 1238 : return JSProxy::IsArray(Handle<JSProxy>::cast(object));
335 : }
336 :
337 179828284 : bool HeapObject::IsUndetectable() const { return map()->is_undetectable(); }
338 :
339 : bool HeapObject::IsAccessCheckNeeded() const {
340 34455596 : if (IsJSGlobalProxy()) {
341 74833 : const JSGlobalProxy proxy = JSGlobalProxy::cast(*this);
342 74833 : JSGlobalObject global = proxy->GetIsolate()->context()->global_object();
343 74833 : return proxy->IsDetachedFrom(global);
344 : }
345 284894 : 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 734564639 : 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 350048625 : : HeapNumber::unchecked_cast(*this)->value();
384 : }
385 :
386 : // static
387 39177 : bool Object::SameNumberValue(double value1, double value2) {
388 : // SameNumberValue(NaN, NaN) is true.
389 39177 : if (value1 != value2) {
390 36577 : return std::isnan(value1) && std::isnan(value2);
391 : }
392 : // SameNumberValue(0.0, -0.0) is false.
393 2600 : return (std::signbit(value1) == std::signbit(value2));
394 : }
395 :
396 : bool Object::IsNaN() const {
397 4561 : return this->IsHeapNumber() && std::isnan(HeapNumber::cast(*this)->value());
398 : }
399 :
400 : bool Object::IsMinusZero() const {
401 6860 : return this->IsHeapNumber() &&
402 : i::IsMinusZero(HeapNumber::cast(*this)->value());
403 : }
404 :
405 : OBJECT_CONSTRUCTORS_IMPL(RegExpMatchInfo, FixedArray)
406 : OBJECT_CONSTRUCTORS_IMPL(ScopeInfo, FixedArray)
407 : OBJECT_CONSTRUCTORS_IMPL(BigIntBase, HeapObject)
408 : OBJECT_CONSTRUCTORS_IMPL(BigInt, BigIntBase)
409 : OBJECT_CONSTRUCTORS_IMPL(FreshlyAllocatedBigInt, BigIntBase)
410 :
411 : // ------------------------------------
412 : // Cast operations
413 :
414 : CAST_ACCESSOR(BigInt)
415 : CAST_ACCESSOR(RegExpMatchInfo)
416 : CAST_ACCESSOR(ScopeInfo)
417 :
418 : bool Object::HasValidElements() {
419 : // Dictionary is covered under FixedArray.
420 : return IsFixedArray() || IsFixedDoubleArray() || IsFixedTypedArrayBase();
421 : }
422 :
423 15346535 : bool Object::FilterKey(PropertyFilter filter) {
424 : DCHECK(!IsPropertyCell());
425 15346535 : if (filter == PRIVATE_NAMES_ONLY) {
426 2299410 : if (!IsSymbol()) return true;
427 18502 : return !Symbol::cast(*this)->is_private_name();
428 13047125 : } else if (IsSymbol()) {
429 101250 : if (filter & SKIP_SYMBOLS) return true;
430 :
431 46373 : if (Symbol::cast(*this)->is_private()) return true;
432 : } else {
433 12945875 : if (filter & SKIP_STRINGS) return true;
434 : }
435 : return false;
436 : }
437 :
438 18014167 : Representation Object::OptimalRepresentation() {
439 18014167 : if (!FLAG_track_fields) return Representation::Tagged();
440 18014167 : if (IsSmi()) {
441 : return Representation::Smi();
442 26108385 : } else if (FLAG_track_double_fields && IsHeapNumber()) {
443 : return Representation::Double();
444 26075157 : } else if (FLAG_track_computed_fields && IsUninitialized()) {
445 : return Representation::None();
446 12820656 : } else if (FLAG_track_heap_object_fields) {
447 : DCHECK(IsHeapObject());
448 : return Representation::HeapObject();
449 : } else {
450 : return Representation::Tagged();
451 : }
452 : }
453 :
454 :
455 11769839 : ElementsKind Object::OptimalElementsKind() {
456 11769839 : if (IsSmi()) return PACKED_SMI_ELEMENTS;
457 1550037 : if (IsNumber()) return PACKED_DOUBLE_ELEMENTS;
458 399510 : return PACKED_ELEMENTS;
459 : }
460 :
461 :
462 40446669 : bool Object::FitsRepresentation(Representation representation) {
463 40446669 : if (FLAG_track_fields && representation.IsSmi()) {
464 4807309 : return IsSmi();
465 35639360 : } else if (FLAG_track_double_fields && representation.IsDouble()) {
466 70352 : return IsMutableHeapNumber() || IsNumber();
467 35604184 : } else if (FLAG_track_heap_object_fields && representation.IsHeapObject()) {
468 30849915 : return IsHeapObject();
469 4754269 : } else if (FLAG_track_fields && representation.IsNone()) {
470 : return false;
471 : }
472 4570034 : return true;
473 : }
474 :
475 60392114 : bool Object::ToUint32(uint32_t* value) const {
476 60392114 : if (IsSmi()) {
477 : int num = Smi::ToInt(*this);
478 44764811 : if (num < 0) return false;
479 44745129 : *value = static_cast<uint32_t>(num);
480 44745129 : return true;
481 : }
482 15627302 : if (IsHeapNumber()) {
483 : double num = HeapNumber::cast(*this)->value();
484 5794 : return DoubleToUint32IfEqualToSelf(num, value);
485 : }
486 : return false;
487 : }
488 :
489 : // static
490 16773923 : MaybeHandle<JSReceiver> Object::ToObject(Isolate* isolate,
491 : Handle<Object> object,
492 : const char* method_name) {
493 16773923 : if (object->IsJSReceiver()) return Handle<JSReceiver>::cast(object);
494 6831 : return ToObjectImpl(isolate, object, method_name);
495 : }
496 :
497 :
498 : // static
499 6529374 : MaybeHandle<Name> Object::ToName(Isolate* isolate, Handle<Object> input) {
500 6529374 : if (input->IsName()) return Handle<Name>::cast(input);
501 86544 : return ConvertToName(isolate, input);
502 : }
503 :
504 : // static
505 263106 : MaybeHandle<Object> Object::ToPropertyKey(Isolate* isolate,
506 : Handle<Object> value) {
507 484714 : if (value->IsSmi() || HeapObject::cast(*value)->IsName()) return value;
508 540 : return ConvertToPropertyKey(isolate, value);
509 : }
510 :
511 : // static
512 144223 : MaybeHandle<Object> Object::ToPrimitive(Handle<Object> input,
513 : ToPrimitiveHint hint) {
514 144223 : if (input->IsPrimitive()) return input;
515 6663 : return JSReceiver::ToPrimitive(Handle<JSReceiver>::cast(input), hint);
516 : }
517 :
518 : // static
519 7480624 : MaybeHandle<Object> Object::ToNumber(Isolate* isolate, Handle<Object> input) {
520 7480624 : if (input->IsNumber()) return input; // Shortcut.
521 2687615 : return ConvertToNumberOrNumeric(isolate, input, Conversion::kToNumber);
522 : }
523 :
524 : // static
525 5490 : MaybeHandle<Object> Object::ToNumeric(Isolate* isolate, Handle<Object> input) {
526 8656 : if (input->IsNumber() || input->IsBigInt()) return input; // Shortcut.
527 1375 : return ConvertToNumberOrNumeric(isolate, input, Conversion::kToNumeric);
528 : }
529 :
530 : // static
531 : MaybeHandle<Object> Object::ToInteger(Isolate* isolate, Handle<Object> input) {
532 4183921 : if (input->IsSmi()) return input;
533 105749 : return ConvertToInteger(isolate, input);
534 : }
535 :
536 : // static
537 : MaybeHandle<Object> Object::ToInt32(Isolate* isolate, Handle<Object> input) {
538 2377 : if (input->IsSmi()) return input;
539 1352 : return ConvertToInt32(isolate, input);
540 : }
541 :
542 : // static
543 430546 : MaybeHandle<Object> Object::ToUint32(Isolate* isolate, Handle<Object> input) {
544 430582 : if (input->IsSmi()) return handle(Smi::cast(*input)->ToUint32Smi(), isolate);
545 430510 : return ConvertToUint32(isolate, input);
546 : }
547 :
548 : // static
549 11976999 : MaybeHandle<String> Object::ToString(Isolate* isolate, Handle<Object> input) {
550 11976999 : if (input->IsString()) return Handle<String>::cast(input);
551 4592670 : return ConvertToString(isolate, input);
552 : }
553 :
554 : // static
555 63486 : MaybeHandle<Object> Object::ToLength(Isolate* isolate, Handle<Object> input) {
556 63486 : if (input->IsSmi()) {
557 183654 : int value = std::max(Smi::ToInt(*input), 0);
558 61218 : return handle(Smi::FromInt(value), isolate);
559 : }
560 2268 : return ConvertToLength(isolate, input);
561 : }
562 :
563 : // static
564 10950 : MaybeHandle<Object> Object::ToIndex(Isolate* isolate, Handle<Object> input,
565 : MessageTemplate error_index) {
566 20649 : if (input->IsSmi() && Smi::ToInt(*input) >= 0) return input;
567 1309 : return ConvertToIndex(isolate, input, error_index);
568 : }
569 :
570 2398901 : MaybeHandle<Object> Object::GetProperty(Isolate* isolate, Handle<Object> object,
571 : Handle<Name> name) {
572 2398901 : LookupIterator it(isolate, object, name);
573 2494173 : if (!it.IsFound()) return it.factory()->undefined_value();
574 2303629 : return GetProperty(&it);
575 : }
576 :
577 1184278 : MaybeHandle<Object> Object::GetElement(Isolate* isolate, Handle<Object> object,
578 : uint32_t index) {
579 1184278 : LookupIterator it(isolate, object, index);
580 2363980 : if (!it.IsFound()) return it.factory()->undefined_value();
581 4576 : return GetProperty(&it);
582 : }
583 :
584 22693 : MaybeHandle<Object> Object::SetElement(Isolate* isolate, Handle<Object> object,
585 : uint32_t index, Handle<Object> value,
586 : ShouldThrow should_throw) {
587 22693 : LookupIterator it(isolate, object, index);
588 45386 : MAYBE_RETURN_NULL(
589 : SetProperty(&it, value, StoreOrigin::kMaybeKeyed, Just(should_throw)));
590 22457 : return value;
591 : }
592 :
593 23009053 : ObjectSlot HeapObject::RawField(int byte_offset) const {
594 4721924328 : return ObjectSlot(FIELD_ADDR(*this, byte_offset));
595 : }
596 :
597 : MaybeObjectSlot HeapObject::RawMaybeWeakField(int byte_offset) const {
598 2959732341 : return MaybeObjectSlot(FIELD_ADDR(*this, byte_offset));
599 : }
600 :
601 : MapWord MapWord::FromMap(const Map map) { return MapWord(map.ptr()); }
602 :
603 : Map MapWord::ToMap() const { return Map::unchecked_cast(Object(value_)); }
604 :
605 706596840 : bool MapWord::IsForwardingAddress() const { return HAS_SMI_TAG(value_); }
606 :
607 : MapWord MapWord::FromForwardingAddress(HeapObject object) {
608 26979939 : return MapWord(object->ptr() - kHeapObjectTag);
609 : }
610 :
611 46981 : HeapObject MapWord::ToForwardingAddress() {
612 : DCHECK(IsForwardingAddress());
613 93962 : return HeapObject::FromAddress(value_);
614 : }
615 :
616 : #ifdef VERIFY_HEAP
617 : void HeapObject::VerifyObjectField(Isolate* isolate, int offset) {
618 : VerifyPointer(isolate, READ_FIELD(*this, offset));
619 : STATIC_ASSERT(!COMPRESS_POINTERS_BOOL || kTaggedSize == kInt32Size);
620 : }
621 :
622 : void HeapObject::VerifyMaybeObjectField(Isolate* isolate, int offset) {
623 : MaybeObject::VerifyMaybeObjectPointer(isolate,
624 : READ_WEAK_FIELD(*this, offset));
625 : STATIC_ASSERT(!COMPRESS_POINTERS_BOOL || kTaggedSize == kInt32Size);
626 : }
627 :
628 : void HeapObject::VerifySmiField(int offset) {
629 : CHECK(READ_FIELD(*this, offset)->IsSmi());
630 : STATIC_ASSERT(!COMPRESS_POINTERS_BOOL || kTaggedSize == kInt32Size);
631 : }
632 :
633 : #endif
634 :
635 : ReadOnlyRoots HeapObject::GetReadOnlyRoots() const {
636 : // TODO(v8:7464): When RO_SPACE is embedded, this will access a global
637 : // variable instead.
638 : return ReadOnlyRoots(GetHeapFromWritableObject(*this));
639 : }
640 :
641 5328450438 : Map HeapObject::map() const { return map_word().ToMap(); }
642 :
643 6217339 : void HeapObject::set_map(Map value) {
644 : if (!value.is_null()) {
645 : #ifdef VERIFY_HEAP
646 : GetHeapFromWritableObject(*this)->VerifyObjectLayoutChange(*this, value);
647 : #endif
648 : }
649 : set_map_word(MapWord::FromMap(value));
650 6217339 : if (!value.is_null()) {
651 : // TODO(1600) We are passing kNullAddress as a slot because maps can never
652 : // be on an evacuation candidate.
653 6217342 : MarkingBarrier(*this, ObjectSlot(kNullAddress), value);
654 : }
655 6217341 : }
656 :
657 : Map HeapObject::synchronized_map() const {
658 : return synchronized_map_word().ToMap();
659 : }
660 :
661 71133363 : void HeapObject::synchronized_set_map(Map value) {
662 : if (!value.is_null()) {
663 : #ifdef VERIFY_HEAP
664 : GetHeapFromWritableObject(*this)->VerifyObjectLayoutChange(*this, value);
665 : #endif
666 : }
667 : synchronized_set_map_word(MapWord::FromMap(value));
668 71133363 : if (!value.is_null()) {
669 : // TODO(1600) We are passing kNullAddress as a slot because maps can never
670 : // be on an evacuation candidate.
671 71133367 : MarkingBarrier(*this, ObjectSlot(kNullAddress), value);
672 : }
673 71133348 : }
674 :
675 :
676 : // Unsafe accessor omitting write barrier.
677 : void HeapObject::set_map_no_write_barrier(Map value) {
678 : if (!value.is_null()) {
679 : #ifdef VERIFY_HEAP
680 : GetHeapFromWritableObject(*this)->VerifyObjectLayoutChange(*this, value);
681 : #endif
682 : }
683 : set_map_word(MapWord::FromMap(value));
684 : }
685 :
686 71146400 : void HeapObject::set_map_after_allocation(Map value, WriteBarrierMode mode) {
687 : set_map_word(MapWord::FromMap(value));
688 71146400 : if (mode != SKIP_WRITE_BARRIER) {
689 : DCHECK(!value.is_null());
690 : // TODO(1600) We are passing kNullAddress as a slot because maps can never
691 : // be on an evacuation candidate.
692 27098773 : MarkingBarrier(*this, ObjectSlot(kNullAddress), value);
693 : }
694 71146397 : }
695 :
696 25103809 : MapWordSlot HeapObject::map_slot() const {
697 24939340392 : return MapWordSlot(FIELD_ADDR(*this, kMapOffset));
698 : }
699 :
700 68144 : MapWord HeapObject::map_word() const {
701 68144 : return MapWord(map_slot().Relaxed_Load().ptr());
702 : }
703 :
704 25109166 : void HeapObject::set_map_word(MapWord map_word) {
705 25109166 : map_slot().Relaxed_Store(Object(map_word.value_));
706 25109166 : }
707 :
708 :
709 46981 : MapWord HeapObject::synchronized_map_word() const {
710 46981 : return MapWord(map_slot().Acquire_Load().ptr());
711 : }
712 :
713 : void HeapObject::synchronized_set_map_word(MapWord map_word) {
714 : map_slot().Release_Store(Object(map_word.value_));
715 : }
716 :
717 1714605310 : int HeapObject::Size() const { return SizeFromMap(map()); }
718 :
719 : inline bool IsSpecialReceiverInstanceType(InstanceType instance_type) {
720 : return instance_type <= LAST_SPECIAL_RECEIVER_TYPE;
721 : }
722 :
723 : // This should be in objects/map-inl.h, but can't, because of a cyclic
724 : // dependency.
725 : bool Map::IsSpecialReceiverMap() const {
726 : bool result = IsSpecialReceiverInstanceType(instance_type());
727 : DCHECK_IMPLIES(!result,
728 : !has_named_interceptor() && !is_access_check_needed());
729 : return result;
730 : }
731 :
732 : inline bool IsCustomElementsReceiverInstanceType(InstanceType instance_type) {
733 128121 : return instance_type <= LAST_CUSTOM_ELEMENTS_RECEIVER;
734 : }
735 :
736 : // This should be in objects/map-inl.h, but can't, because of a cyclic
737 : // dependency.
738 128121 : bool Map::IsCustomElementsReceiverMap() const {
739 128121 : return IsCustomElementsReceiverInstanceType(instance_type());
740 : }
741 :
742 6413 : bool Object::ToArrayLength(uint32_t* index) const {
743 5498278 : return Object::ToUint32(index);
744 : }
745 :
746 : bool Object::ToArrayIndex(uint32_t* index) const {
747 54855956 : return Object::ToUint32(index) && *index != kMaxUInt32;
748 : }
749 :
750 3993746 : bool Object::GetHeapObjectIfStrong(HeapObject* result) const {
751 3993746 : return GetHeapObject(result);
752 : }
753 :
754 612388 : bool Object::GetHeapObject(HeapObject* result) const {
755 7501531334 : if (!IsHeapObject()) return false;
756 2029154825 : *result = HeapObject::cast(*this);
757 464926 : return true;
758 : }
759 :
760 0 : HeapObject Object::GetHeapObject() const {
761 : DCHECK(IsHeapObject());
762 0 : return HeapObject::cast(*this);
763 : }
764 :
765 : int RegExpMatchInfo::NumberOfCaptureRegisters() {
766 : DCHECK_GE(length(), kLastMatchOverhead);
767 : Object obj = get(kNumberOfCapturesIndex);
768 : return Smi::ToInt(obj);
769 : }
770 :
771 : void RegExpMatchInfo::SetNumberOfCaptureRegisters(int value) {
772 : DCHECK_GE(length(), kLastMatchOverhead);
773 : set(kNumberOfCapturesIndex, Smi::FromInt(value));
774 : }
775 :
776 : String RegExpMatchInfo::LastSubject() {
777 : DCHECK_GE(length(), kLastMatchOverhead);
778 : return String::cast(get(kLastSubjectIndex));
779 : }
780 :
781 : void RegExpMatchInfo::SetLastSubject(String value) {
782 : DCHECK_GE(length(), kLastMatchOverhead);
783 4256358 : set(kLastSubjectIndex, value);
784 : }
785 :
786 : Object RegExpMatchInfo::LastInput() {
787 : DCHECK_GE(length(), kLastMatchOverhead);
788 : return get(kLastInputIndex);
789 : }
790 :
791 : void RegExpMatchInfo::SetLastInput(Object value) {
792 : DCHECK_GE(length(), kLastMatchOverhead);
793 4256403 : set(kLastInputIndex, value);
794 : }
795 :
796 : int RegExpMatchInfo::Capture(int i) {
797 : DCHECK_LT(i, NumberOfCaptureRegisters());
798 499320 : Object obj = get(kFirstCaptureIndex + i);
799 : return Smi::ToInt(obj);
800 : }
801 :
802 : void RegExpMatchInfo::SetCapture(int i, int value) {
803 : DCHECK_LT(i, NumberOfCaptureRegisters());
804 : set(kFirstCaptureIndex + i, Smi::FromInt(value));
805 : }
806 :
807 : WriteBarrierMode HeapObject::GetWriteBarrierMode(
808 : const DisallowHeapAllocation& promise) {
809 : return GetWriteBarrierModeForObject(*this, &promise);
810 : }
811 :
812 : // static
813 : AllocationAlignment HeapObject::RequiredAlignment(Map map) {
814 : #ifdef V8_COMPRESS_POINTERS
815 : // TODO(ishell, v8:8875): Consider using aligned allocations once the
816 : // allocation alignment inconsistency is fixed. For now we keep using
817 : // unaligned access since both x64 and arm64 architectures (where pointer
818 : // compression is supported) allow unaligned access to doubles and full words.
819 : #endif // V8_COMPRESS_POINTERS
820 : #ifdef V8_HOST_ARCH_32_BIT
821 : int instance_type = map->instance_type();
822 : if (instance_type == FIXED_FLOAT64_ARRAY_TYPE ||
823 : instance_type == FIXED_DOUBLE_ARRAY_TYPE) {
824 : return kDoubleAligned;
825 : }
826 : if (instance_type == HEAP_NUMBER_TYPE) return kDoubleUnaligned;
827 : #endif // V8_HOST_ARCH_32_BIT
828 : return kWordAligned;
829 : }
830 :
831 : Address HeapObject::GetFieldAddress(int field_offset) const {
832 57555 : return FIELD_ADDR(*this, field_offset);
833 : }
834 :
835 : // static
836 239 : Maybe<bool> Object::GreaterThan(Isolate* isolate, Handle<Object> x,
837 : Handle<Object> y) {
838 239 : Maybe<ComparisonResult> result = Compare(isolate, x, y);
839 239 : if (result.IsJust()) {
840 239 : switch (result.FromJust()) {
841 : case ComparisonResult::kGreaterThan:
842 : return Just(true);
843 : case ComparisonResult::kLessThan:
844 : case ComparisonResult::kEqual:
845 : case ComparisonResult::kUndefined:
846 : return Just(false);
847 : }
848 : }
849 : return Nothing<bool>();
850 : }
851 :
852 :
853 : // static
854 221 : Maybe<bool> Object::GreaterThanOrEqual(Isolate* isolate, Handle<Object> x,
855 : Handle<Object> y) {
856 221 : Maybe<ComparisonResult> result = Compare(isolate, x, y);
857 221 : if (result.IsJust()) {
858 221 : switch (result.FromJust()) {
859 : case ComparisonResult::kEqual:
860 : case ComparisonResult::kGreaterThan:
861 : return Just(true);
862 : case ComparisonResult::kLessThan:
863 : case ComparisonResult::kUndefined:
864 : return Just(false);
865 : }
866 : }
867 : return Nothing<bool>();
868 : }
869 :
870 :
871 : // static
872 257 : Maybe<bool> Object::LessThan(Isolate* isolate, Handle<Object> x,
873 : Handle<Object> y) {
874 257 : Maybe<ComparisonResult> result = Compare(isolate, x, y);
875 257 : if (result.IsJust()) {
876 239 : switch (result.FromJust()) {
877 : case ComparisonResult::kLessThan:
878 : return Just(true);
879 : case ComparisonResult::kEqual:
880 : case ComparisonResult::kGreaterThan:
881 : case ComparisonResult::kUndefined:
882 : return Just(false);
883 : }
884 : }
885 : return Nothing<bool>();
886 : }
887 :
888 :
889 : // static
890 212 : Maybe<bool> Object::LessThanOrEqual(Isolate* isolate, Handle<Object> x,
891 : Handle<Object> y) {
892 212 : Maybe<ComparisonResult> result = Compare(isolate, x, y);
893 212 : if (result.IsJust()) {
894 212 : switch (result.FromJust()) {
895 : case ComparisonResult::kEqual:
896 : case ComparisonResult::kLessThan:
897 : return Just(true);
898 : case ComparisonResult::kGreaterThan:
899 : case ComparisonResult::kUndefined:
900 : return Just(false);
901 : }
902 : }
903 : return Nothing<bool>();
904 : }
905 :
906 929361 : MaybeHandle<Object> Object::GetPropertyOrElement(Isolate* isolate,
907 : Handle<Object> object,
908 : Handle<Name> name) {
909 929361 : LookupIterator it = LookupIterator::PropertyOrElement(isolate, object, name);
910 929367 : return GetProperty(&it);
911 : }
912 :
913 1059 : MaybeHandle<Object> Object::SetPropertyOrElement(
914 : Isolate* isolate, Handle<Object> object, Handle<Name> name,
915 : Handle<Object> value, Maybe<ShouldThrow> should_throw,
916 : StoreOrigin store_origin) {
917 1059 : LookupIterator it = LookupIterator::PropertyOrElement(isolate, object, name);
918 2118 : MAYBE_RETURN_NULL(SetProperty(&it, value, store_origin, should_throw));
919 987 : return value;
920 : }
921 :
922 16696 : MaybeHandle<Object> Object::GetPropertyOrElement(Handle<Object> receiver,
923 : Handle<Name> name,
924 : Handle<JSReceiver> holder) {
925 : LookupIterator it = LookupIterator::PropertyOrElement(holder->GetIsolate(),
926 16696 : receiver, name, holder);
927 16696 : return GetProperty(&it);
928 : }
929 :
930 : // static
931 34973579 : Object Object::GetSimpleHash(Object object) {
932 : DisallowHeapAllocation no_gc;
933 34973579 : if (object->IsSmi()) {
934 17540167 : uint32_t hash = ComputeUnseededHash(Smi::ToInt(object));
935 35080334 : return Smi::FromInt(hash & Smi::kMaxValue);
936 : }
937 17433411 : if (object->IsHeapNumber()) {
938 : double num = HeapNumber::cast(object)->value();
939 4382 : if (std::isnan(num)) return Smi::FromInt(Smi::kMaxValue);
940 : // Use ComputeUnseededHash for all values in Signed32 range, including -0,
941 : // which is considered equal to 0 because collections use SameValueZero.
942 : uint32_t hash;
943 : // Check range before conversion to avoid undefined behavior.
944 6856 : if (num >= kMinInt && num <= kMaxInt && FastI2D(FastD2I(num)) == num) {
945 521 : hash = ComputeUnseededHash(FastD2I(num));
946 : } else {
947 : hash = ComputeLongHash(double_to_uint64(num));
948 : }
949 7630 : return Smi::FromInt(hash & Smi::kMaxValue);
950 : }
951 17429029 : if (object->IsName()) {
952 17285643 : uint32_t hash = Name::cast(object)->Hash();
953 34571288 : return Smi::FromInt(hash);
954 : }
955 143386 : if (object->IsOddball()) {
956 2187 : uint32_t hash = Oddball::cast(object)->to_string()->Hash();
957 4374 : return Smi::FromInt(hash);
958 : }
959 141199 : if (object->IsBigInt()) {
960 288 : uint32_t hash = BigInt::cast(object)->Hash();
961 576 : return Smi::FromInt(hash & Smi::kMaxValue);
962 : }
963 140911 : if (object->IsSharedFunctionInfo()) {
964 82375 : uint32_t hash = SharedFunctionInfo::cast(object)->Hash();
965 164750 : return Smi::FromInt(hash & Smi::kMaxValue);
966 : }
967 : DCHECK(object->IsJSReceiver());
968 58536 : return object;
969 : }
970 :
971 24717136 : Object Object::GetHash() {
972 : DisallowHeapAllocation no_gc;
973 24717136 : Object hash = GetSimpleHash(*this);
974 24717135 : if (hash->IsSmi()) return hash;
975 :
976 : DCHECK(IsJSReceiver());
977 38014 : JSReceiver receiver = JSReceiver::cast(*this);
978 38014 : return receiver->GetIdentityHash();
979 : }
980 :
981 : Handle<Object> ObjectHashTableShape::AsHandle(Handle<Object> key) {
982 : return key;
983 : }
984 :
985 7161623 : Relocatable::Relocatable(Isolate* isolate) {
986 7161623 : isolate_ = isolate;
987 7161623 : prev_ = isolate->relocatable_top();
988 : isolate->set_relocatable_top(this);
989 : }
990 :
991 :
992 14323250 : Relocatable::~Relocatable() {
993 : DCHECK_EQ(isolate_->relocatable_top(), this);
994 7161625 : isolate_->set_relocatable_top(prev_);
995 0 : }
996 :
997 : // Predictably converts HeapObject or Address to uint32 by calculating
998 : // offset of the address in respective MemoryChunk.
999 : static inline uint32_t ObjectAddressForHashing(Address object) {
1000 13312456 : uint32_t value = static_cast<uint32_t>(object);
1001 13312456 : return value & kPageAlignmentMask;
1002 : }
1003 :
1004 810 : static inline Handle<Object> MakeEntryPair(Isolate* isolate, uint32_t index,
1005 : Handle<Object> value) {
1006 810 : Handle<Object> key = isolate->factory()->Uint32ToString(index);
1007 : Handle<FixedArray> entry_storage =
1008 810 : isolate->factory()->NewUninitializedFixedArray(2);
1009 : {
1010 : entry_storage->set(0, *key, SKIP_WRITE_BARRIER);
1011 : entry_storage->set(1, *value, SKIP_WRITE_BARRIER);
1012 : }
1013 : return isolate->factory()->NewJSArrayWithElements(entry_storage,
1014 810 : PACKED_ELEMENTS, 2);
1015 : }
1016 :
1017 816 : static inline Handle<Object> MakeEntryPair(Isolate* isolate, Handle<Object> key,
1018 : Handle<Object> value) {
1019 : Handle<FixedArray> entry_storage =
1020 816 : isolate->factory()->NewUninitializedFixedArray(2);
1021 : {
1022 : entry_storage->set(0, *key, SKIP_WRITE_BARRIER);
1023 : entry_storage->set(1, *value, SKIP_WRITE_BARRIER);
1024 : }
1025 : return isolate->factory()->NewJSArrayWithElements(entry_storage,
1026 816 : PACKED_ELEMENTS, 2);
1027 : }
1028 :
1029 : bool ScopeInfo::IsAsmModule() const {
1030 855136 : return IsAsmModuleField::decode(Flags());
1031 : }
1032 :
1033 : bool ScopeInfo::HasSimpleParameters() const {
1034 64272 : return HasSimpleParametersField::decode(Flags());
1035 : }
1036 :
1037 : #define FIELD_ACCESSORS(name) \
1038 : void ScopeInfo::Set##name(int value) { set(k##name, Smi::FromInt(value)); } \
1039 : int ScopeInfo::name() const { \
1040 : if (length() > 0) { \
1041 : return Smi::ToInt(get(k##name)); \
1042 : } else { \
1043 : return 0; \
1044 : } \
1045 : }
1046 430794102 : FOR_EACH_SCOPE_INFO_NUMERIC_FIELD(FIELD_ACCESSORS)
1047 : #undef FIELD_ACCESSORS
1048 :
1049 : FreshlyAllocatedBigInt FreshlyAllocatedBigInt::cast(Object object) {
1050 : SLOW_DCHECK(object->IsBigInt());
1051 : return FreshlyAllocatedBigInt(object->ptr());
1052 : }
1053 :
1054 : } // namespace internal
1055 : } // namespace v8
1056 :
1057 : #include "src/objects/object-macros-undef.h"
1058 :
1059 : #endif // V8_OBJECTS_INL_H_
|