1 // Copyright 2015 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 #ifndef V8_OBJECTS_OBJECTS_H_
6 #define V8_OBJECTS_OBJECTS_H_
7
8 #include <iosfwd>
9 #include <memory>
10
11 #include "include/v8-internal.h"
12 #include "include/v8config.h"
13 #include "src/base/bits.h"
14 #include "src/base/build_config.h"
15 #include "src/base/flags.h"
16 #include "src/base/logging.h"
17 #include "src/base/memory.h"
18 #include "src/codegen/constants-arch.h"
19 #include "src/common/assert-scope.h"
20 #include "src/common/checks.h"
21 #include "src/common/message-template.h"
22 #include "src/common/operation.h"
23 #include "src/common/ptr-compr.h"
24 #include "src/flags/flags.h"
25 #include "src/objects/elements-kind.h"
26 #include "src/objects/field-index.h"
27 #include "src/objects/object-list-macros.h"
28 #include "src/objects/objects-definitions.h"
29 #include "src/objects/property-details.h"
30 #include "src/objects/tagged-impl.h"
31 #include "src/utils/utils.h"
32
33 // Has to be the last include (doesn't have include guards):
34 #include "src/objects/object-macros.h"
35
36 //
37 // Most object types in the V8 JavaScript are described in this file.
38 //
39 // Inheritance hierarchy:
40 // - Object
41 // - Smi (immediate small integer)
42 // - TaggedIndex (properly sign-extended immediate small integer)
43 // - HeapObject (superclass for everything allocated in the heap)
44 // - JSReceiver (suitable for property access)
45 // - JSObject
46 // - JSArray
47 // - JSArrayBuffer
48 // - JSArrayBufferView
49 // - JSTypedArray
50 // - JSDataView
51 // - JSCollection
52 // - JSSet
53 // - JSMap
54 // - JSCustomElementsObject (may have elements despite empty FixedArray)
55 // - JSSpecialObject (requires custom property lookup handling)
56 // - JSGlobalObject
57 // - JSGlobalProxy
58 // - JSModuleNamespace
59 // - JSPrimitiveWrapper
60 // - JSDate
61 // - JSFunctionOrBoundFunctionOrWrappedFunction
62 // - JSBoundFunction
63 // - JSFunction
64 // - JSWrappedFunction
65 // - JSGeneratorObject
66 // - JSMapIterator
67 // - JSMessageObject
68 // - JSRegExp
69 // - JSSetIterator
70 // - JSShadowRealm
71 // - JSSharedStruct
72 // - JSStringIterator
73 // - JSTemporalCalendar
74 // - JSTemporalDuration
75 // - JSTemporalInstant
76 // - JSTemporalPlainDate
77 // - JSTemporalPlainDateTime
78 // - JSTemporalPlainMonthDay
79 // - JSTemporalPlainTime
80 // - JSTemporalPlainYearMonth
81 // - JSTemporalTimeZone
82 // - JSTemporalZonedDateTime
83 // - JSWeakCollection
84 // - JSWeakMap
85 // - JSWeakSet
86 // - JSCollator // If V8_INTL_SUPPORT enabled.
87 // - JSDateTimeFormat // If V8_INTL_SUPPORT enabled.
88 // - JSDisplayNames // If V8_INTL_SUPPORT enabled.
89 // - JSListFormat // If V8_INTL_SUPPORT enabled.
90 // - JSLocale // If V8_INTL_SUPPORT enabled.
91 // - JSNumberFormat // If V8_INTL_SUPPORT enabled.
92 // - JSPluralRules // If V8_INTL_SUPPORT enabled.
93 // - JSRelativeTimeFormat // If V8_INTL_SUPPORT enabled.
94 // - JSSegmenter // If V8_INTL_SUPPORT enabled.
95 // - JSSegments // If V8_INTL_SUPPORT enabled.
96 // - JSSegmentIterator // If V8_INTL_SUPPORT enabled.
97 // - JSV8BreakIterator // If V8_INTL_SUPPORT enabled.
98 // - WasmTagObject
99 // - WasmGlobalObject
100 // - WasmInstanceObject
101 // - WasmMemoryObject
102 // - WasmModuleObject
103 // - WasmTableObject
104 // - WasmSuspenderObject
105 // - JSProxy
106 // - FixedArrayBase
107 // - ByteArray
108 // - BytecodeArray
109 // - FixedArray
110 // - HashTable
111 // - Dictionary
112 // - StringTable
113 // - StringSet
114 // - CompilationCacheTable
115 // - MapCache
116 // - OrderedHashTable
117 // - OrderedHashSet
118 // - OrderedHashMap
119 // - FeedbackMetadata
120 // - TemplateList
121 // - TransitionArray
122 // - ScopeInfo
123 // - SourceTextModuleInfo
124 // - ScriptContextTable
125 // - ClosureFeedbackCellArray
126 // - FixedDoubleArray
127 // - PrimitiveHeapObject
128 // - BigInt
129 // - HeapNumber
130 // - Name
131 // - String
132 // - SeqString
133 // - SeqOneByteString
134 // - SeqTwoByteString
135 // - SlicedString
136 // - ConsString
137 // - ThinString
138 // - ExternalString
139 // - ExternalOneByteString
140 // - ExternalTwoByteString
141 // - InternalizedString
142 // - SeqInternalizedString
143 // - SeqOneByteInternalizedString
144 // - SeqTwoByteInternalizedString
145 // - ConsInternalizedString
146 // - ExternalInternalizedString
147 // - ExternalOneByteInternalizedString
148 // - ExternalTwoByteInternalizedString
149 // - Symbol
150 // - Oddball
151 // - Context
152 // - NativeContext
153 // - Cell
154 // - DescriptorArray
155 // - PropertyCell
156 // - PropertyArray
157 // - Code
158 // - AbstractCode, a wrapper around Code or BytecodeArray
159 // - Map
160 // - Foreign
161 // - SmallOrderedHashTable
162 // - SmallOrderedHashMap
163 // - SmallOrderedHashSet
164 // - SharedFunctionInfo
165 // - Struct
166 // - AccessorInfo
167 // - AsmWasmData
168 // - PromiseReaction
169 // - PromiseCapability
170 // - AccessorPair
171 // - AccessCheckInfo
172 // - InterceptorInfo
173 // - CallHandlerInfo
174 // - EnumCache
175 // - TemplateInfo
176 // - FunctionTemplateInfo
177 // - ObjectTemplateInfo
178 // - Script
179 // - DebugInfo
180 // - BreakPoint
181 // - BreakPointInfo
182 // - CachedTemplateObject
183 // - CallSiteInfo
184 // - CodeCache
185 // - PropertyDescriptorObject
186 // - PromiseOnStack
187 // - PrototypeInfo
188 // - Microtask
189 // - CallbackTask
190 // - CallableTask
191 // - PromiseReactionJobTask
192 // - PromiseFulfillReactionJobTask
193 // - PromiseRejectReactionJobTask
194 // - PromiseResolveThenableJobTask
195 // - Module
196 // - SourceTextModule
197 // - SyntheticModule
198 // - SourceTextModuleInfoEntry
199 // - StackFrameInfo
200 // - FeedbackCell
201 // - FeedbackVector
202 // - PreparseData
203 // - UncompiledData
204 // - UncompiledDataWithoutPreparseData
205 // - UncompiledDataWithPreparseData
206 // - SwissNameDictionary
207 //
208 // Formats of Object::ptr_:
209 // Smi: [31 bit signed int] 0
210 // HeapObject: [32 bit direct pointer] (4 byte aligned) | 01
211
212 namespace v8 {
213 namespace internal {
214
215 struct InliningPosition;
216 class PropertyDescriptorObject;
217
218 // UNSAFE_SKIP_WRITE_BARRIER skips the write barrier.
219 // SKIP_WRITE_BARRIER skips the write barrier and asserts that this is safe in
220 // the MemoryOptimizer
221 // UPDATE_WEAK_WRITE_BARRIER skips the marking part of the write barrier and
222 // only performs the generational part.
223 // UPDATE_WRITE_BARRIER is doing the full barrier, marking and generational.
224 enum WriteBarrierMode {
225 SKIP_WRITE_BARRIER,
226 UNSAFE_SKIP_WRITE_BARRIER,
227 UPDATE_WEAK_WRITE_BARRIER,
228 UPDATE_EPHEMERON_KEY_WRITE_BARRIER,
229 UPDATE_WRITE_BARRIER
230 };
231
232 // PropertyNormalizationMode is used to specify whether to keep
233 // inobject properties when normalizing properties of a JSObject.
234 enum PropertyNormalizationMode {
235 CLEAR_INOBJECT_PROPERTIES,
236 KEEP_INOBJECT_PROPERTIES
237 };
238
239 // Indicates whether transitions can be added to a source map or not.
240 enum TransitionFlag { INSERT_TRANSITION, OMIT_TRANSITION };
241
242 // Indicates whether the transition is simple: the target map of the transition
243 // either extends the current map with a new property, or it modifies the
244 // property that was added last to the current map.
245 enum SimpleTransitionFlag {
246 SIMPLE_PROPERTY_TRANSITION,
247 PROPERTY_TRANSITION,
248 SPECIAL_TRANSITION
249 };
250
251 // Indicates whether we are only interested in the descriptors of a particular
252 // map, or in all descriptors in the descriptor array.
253 enum DescriptorFlag { ALL_DESCRIPTORS, OWN_DESCRIPTORS };
254
255 // Instance size sentinel for objects of variable size.
256 const int kVariableSizeSentinel = 0;
257
258 // We may store the unsigned bit field as signed Smi value and do not
259 // use the sign bit.
260 const int kStubMajorKeyBits = 8;
261 const int kStubMinorKeyBits = kSmiValueSize - kStubMajorKeyBits - 1;
262
263 // Result of an abstract relational comparison of x and y, implemented according
264 // to ES6 section 7.2.11 Abstract Relational Comparison.
265 enum class ComparisonResult {
266 kLessThan, // x < y
267 kEqual, // x = y
268 kGreaterThan, // x > y
269 kUndefined // at least one of x or y was undefined or NaN
270 };
271
272 // (Returns false whenever {result} is kUndefined.)
273 bool ComparisonResultToBool(Operation op, ComparisonResult result);
274
275 enum class OnNonExistent { kThrowReferenceError, kReturnUndefined };
276
277 // The element types selection for CreateListFromArrayLike.
278 enum class ElementTypes { kAll, kStringAndSymbol };
279
280 // Currently DefineOwnPropertyIgnoreAttributes invokes the setter
281 // interceptor and user-defined setters during define operations,
282 // even in places where it makes more sense to invoke the definer
283 // interceptor and not invoke the setter: e.g. both the definer and
284 // the setter interceptors are called in Object.defineProperty().
285 // kDefine allows us to implement the define semantics correctly
286 // in selected locations.
287 // TODO(joyee): see if we can deprecate the old behavior.
288 enum class EnforceDefineSemantics { kSet, kDefine };
289
290 // TODO(mythria): Move this to a better place.
291 ShouldThrow GetShouldThrow(Isolate* isolate, Maybe<ShouldThrow> should_throw);
292
293 // Object is the abstract superclass for all classes in the
294 // object hierarchy.
295 // Object does not use any virtual functions to avoid the
296 // allocation of the C++ vtable.
297 // There must only be a single data member in Object: the Address ptr,
298 // containing the tagged heap pointer that this Object instance refers to.
299 // For a design overview, see https://goo.gl/Ph4CGz.
300 class Object : public TaggedImpl<HeapObjectReferenceType::STRONG, Address> {
301 public:
Object()302 constexpr Object() : TaggedImpl(kNullAddress) {}
Object(Address ptr)303 explicit constexpr Object(Address ptr) : TaggedImpl(ptr) {}
304
305 V8_INLINE bool IsTaggedIndex() const;
306
307 // Whether the object is in the RO heap and the RO heap is shared, or in the
308 // writable shared heap.
309 V8_INLINE bool InSharedHeap() const;
310
311 V8_INLINE bool InSharedWritableHeap() const;
312
313 #define IS_TYPE_FUNCTION_DECL(Type) \
314 V8_INLINE bool Is##Type() const; \
315 V8_INLINE bool Is##Type(PtrComprCageBase cage_base) const;
316 OBJECT_TYPE_LIST(IS_TYPE_FUNCTION_DECL)
317 HEAP_OBJECT_TYPE_LIST(IS_TYPE_FUNCTION_DECL)
318 IS_TYPE_FUNCTION_DECL(HashTableBase)
319 IS_TYPE_FUNCTION_DECL(SmallOrderedHashTable)
320 IS_TYPE_FUNCTION_DECL(CodeT)
321 #undef IS_TYPE_FUNCTION_DECL
322 V8_INLINE bool IsNumber(ReadOnlyRoots roots) const;
323
324 // Oddball checks are faster when they are raw pointer comparisons, so the
325 // isolate/read-only roots overloads should be preferred where possible.
326 #define IS_TYPE_FUNCTION_DECL(Type, Value) \
327 V8_INLINE bool Is##Type(Isolate* isolate) const; \
328 V8_INLINE bool Is##Type(LocalIsolate* isolate) const; \
329 V8_INLINE bool Is##Type(ReadOnlyRoots roots) const; \
330 V8_INLINE bool Is##Type() const;
331 ODDBALL_LIST(IS_TYPE_FUNCTION_DECL)
332 IS_TYPE_FUNCTION_DECL(NullOrUndefined, /* unused */)
333 #undef IS_TYPE_FUNCTION_DECL
334
335 V8_INLINE bool IsZero() const;
336 V8_INLINE bool IsNoSharedNameSentinel() const;
337 V8_INLINE bool IsPrivateSymbol() const;
338 V8_INLINE bool IsPublicSymbol() const;
339
340 enum class Conversion { kToNumber, kToNumeric };
341
342 #define DECL_STRUCT_PREDICATE(NAME, Name, name) \
343 V8_INLINE bool Is##Name() const; \
344 V8_INLINE bool Is##Name(PtrComprCageBase cage_base) const;
345 STRUCT_LIST(DECL_STRUCT_PREDICATE)
346 #undef DECL_STRUCT_PREDICATE
347
348 // ES6, #sec-isarray. NOT to be confused with %_IsArray.
349 V8_INLINE
350 V8_WARN_UNUSED_RESULT static Maybe<bool> IsArray(Handle<Object> object);
351
352 // Extract the number.
353 inline double Number() const;
354 V8_INLINE bool IsNaN() const;
355 V8_INLINE bool IsMinusZero() const;
356 V8_EXPORT_PRIVATE bool ToInt32(int32_t* value);
357 inline bool ToUint32(uint32_t* value) const;
358
359 inline Representation OptimalRepresentation(PtrComprCageBase cage_base) const;
360
361 inline ElementsKind OptimalElementsKind(PtrComprCageBase cage_base) const;
362
363 // If {allow_coercion} is true, then a Smi will be considered to fit
364 // a Double representation, since it can be converted to a HeapNumber
365 // and stored.
366 inline bool FitsRepresentation(Representation representation,
367 bool allow_coercion = true) const;
368
369 inline bool FilterKey(PropertyFilter filter);
370
371 Handle<FieldType> OptimalType(Isolate* isolate,
372 Representation representation);
373
374 V8_EXPORT_PRIVATE static Handle<Object> NewStorageFor(
375 Isolate* isolate, Handle<Object> object, Representation representation);
376
377 template <AllocationType allocation_type = AllocationType::kYoung,
378 typename IsolateT>
379 static Handle<Object> WrapForRead(IsolateT* isolate, Handle<Object> object,
380 Representation representation);
381
382 // Returns true if the object is of the correct type to be used as a
383 // implementation of a JSObject's elements.
384 inline bool HasValidElements();
385
386 // ECMA-262 9.2.
387 V8_EXPORT_PRIVATE bool BooleanValue(Isolate* isolate);
388 Object ToBoolean(Isolate* isolate);
389
390 // ES6 section 7.2.11 Abstract Relational Comparison
391 V8_EXPORT_PRIVATE V8_WARN_UNUSED_RESULT static Maybe<ComparisonResult>
392 Compare(Isolate* isolate, Handle<Object> x, Handle<Object> y);
393
394 // ES6 section 7.2.12 Abstract Equality Comparison
395 V8_EXPORT_PRIVATE V8_WARN_UNUSED_RESULT static Maybe<bool> Equals(
396 Isolate* isolate, Handle<Object> x, Handle<Object> y);
397
398 // ES6 section 7.2.13 Strict Equality Comparison
399 V8_EXPORT_PRIVATE bool StrictEquals(Object that);
400
401 // ES6 section 7.1.13 ToObject
402 // Convert to a JSObject if needed.
403 // native_context is used when creating wrapper object.
404 //
405 // Passing a non-null method_name allows us to give a more informative
406 // error message for those cases where ToObject is being called on
407 // the receiver of a built-in method.
408 V8_WARN_UNUSED_RESULT static inline MaybeHandle<JSReceiver> ToObject(
409 Isolate* isolate, Handle<Object> object,
410 const char* method_name = nullptr);
411 V8_WARN_UNUSED_RESULT static MaybeHandle<JSReceiver> ToObjectImpl(
412 Isolate* isolate, Handle<Object> object,
413 const char* method_name = nullptr);
414
415 // ES6 section 9.2.1.2, OrdinaryCallBindThis for sloppy callee.
416 V8_WARN_UNUSED_RESULT static MaybeHandle<JSReceiver> ConvertReceiver(
417 Isolate* isolate, Handle<Object> object);
418
419 // ES6 section 7.1.14 ToPropertyKey
420 V8_WARN_UNUSED_RESULT static inline MaybeHandle<Name> ToName(
421 Isolate* isolate, Handle<Object> input);
422
423 // ES6 section 7.1.1 ToPrimitive
424 V8_WARN_UNUSED_RESULT static inline MaybeHandle<Object> ToPrimitive(
425 Isolate* isolate, Handle<Object> input,
426 ToPrimitiveHint hint = ToPrimitiveHint::kDefault);
427
428 // ES6 section 7.1.3 ToNumber
429 V8_WARN_UNUSED_RESULT static inline MaybeHandle<Object> ToNumber(
430 Isolate* isolate, Handle<Object> input);
431
432 V8_WARN_UNUSED_RESULT static inline MaybeHandle<Object> ToNumeric(
433 Isolate* isolate, Handle<Object> input);
434
435 // ES6 section 7.1.4 ToInteger
436 V8_WARN_UNUSED_RESULT static inline MaybeHandle<Object> ToInteger(
437 Isolate* isolate, Handle<Object> input);
438
439 // ES6 section 7.1.5 ToInt32
440 V8_WARN_UNUSED_RESULT static inline MaybeHandle<Object> ToInt32(
441 Isolate* isolate, Handle<Object> input);
442
443 // ES6 section 7.1.6 ToUint32
444 V8_WARN_UNUSED_RESULT inline static MaybeHandle<Object> ToUint32(
445 Isolate* isolate, Handle<Object> input);
446
447 // ES6 section 7.1.12 ToString
448 V8_WARN_UNUSED_RESULT static inline MaybeHandle<String> ToString(
449 Isolate* isolate, Handle<Object> input);
450
451 V8_EXPORT_PRIVATE static MaybeHandle<String> NoSideEffectsToMaybeString(
452 Isolate* isolate, Handle<Object> input);
453
454 V8_EXPORT_PRIVATE static Handle<String> NoSideEffectsToString(
455 Isolate* isolate, Handle<Object> input);
456
457 // ES6 section 7.1.14 ToPropertyKey
458 V8_WARN_UNUSED_RESULT static inline MaybeHandle<Object> ToPropertyKey(
459 Isolate* isolate, Handle<Object> value);
460
461 // ES6 section 7.1.15 ToLength
462 V8_WARN_UNUSED_RESULT static inline MaybeHandle<Object> ToLength(
463 Isolate* isolate, Handle<Object> input);
464
465 // ES6 section 7.1.17 ToIndex
466 V8_WARN_UNUSED_RESULT static inline MaybeHandle<Object> ToIndex(
467 Isolate* isolate, Handle<Object> input, MessageTemplate error_index);
468
469 // ES6 section 7.3.9 GetMethod
470 V8_WARN_UNUSED_RESULT static MaybeHandle<Object> GetMethod(
471 Handle<JSReceiver> receiver, Handle<Name> name);
472
473 // ES6 section 7.3.17 CreateListFromArrayLike
474 V8_WARN_UNUSED_RESULT static MaybeHandle<FixedArray> CreateListFromArrayLike(
475 Isolate* isolate, Handle<Object> object, ElementTypes element_types);
476
477 // Get length property and apply ToLength.
478 V8_WARN_UNUSED_RESULT static MaybeHandle<Object> GetLengthFromArrayLike(
479 Isolate* isolate, Handle<JSReceiver> object);
480
481 // ES6 section 12.5.6 The typeof Operator
482 static Handle<String> TypeOf(Isolate* isolate, Handle<Object> object);
483
484 // ES6 section 12.7 Additive Operators
485 V8_WARN_UNUSED_RESULT static MaybeHandle<Object> Add(Isolate* isolate,
486 Handle<Object> lhs,
487 Handle<Object> rhs);
488
489 // ES6 section 12.9 Relational Operators
490 V8_WARN_UNUSED_RESULT static inline Maybe<bool> GreaterThan(Isolate* isolate,
491 Handle<Object> x,
492 Handle<Object> y);
493 V8_WARN_UNUSED_RESULT static inline Maybe<bool> GreaterThanOrEqual(
494 Isolate* isolate, Handle<Object> x, Handle<Object> y);
495 V8_WARN_UNUSED_RESULT static inline Maybe<bool> LessThan(Isolate* isolate,
496 Handle<Object> x,
497 Handle<Object> y);
498 V8_WARN_UNUSED_RESULT static inline Maybe<bool> LessThanOrEqual(
499 Isolate* isolate, Handle<Object> x, Handle<Object> y);
500
501 // ES6 section 7.3.19 OrdinaryHasInstance (C, O).
502 V8_WARN_UNUSED_RESULT static MaybeHandle<Object> OrdinaryHasInstance(
503 Isolate* isolate, Handle<Object> callable, Handle<Object> object);
504
505 // ES6 section 12.10.4 Runtime Semantics: InstanceofOperator(O, C)
506 V8_WARN_UNUSED_RESULT static MaybeHandle<Object> InstanceOf(
507 Isolate* isolate, Handle<Object> object, Handle<Object> callable);
508
509 V8_EXPORT_PRIVATE V8_WARN_UNUSED_RESULT static MaybeHandle<Object>
510 GetProperty(LookupIterator* it, bool is_global_reference = false);
511
512 // ES6 [[Set]] (when passed kDontThrow)
513 // Invariants for this and related functions (unless stated otherwise):
514 // 1) When the result is Nothing, an exception is pending.
515 // 2) When passed kThrowOnError, the result is never Just(false).
516 // In some cases, an exception is thrown regardless of the ShouldThrow
517 // argument. These cases are either in accordance with the spec or not
518 // covered by it (eg., concerning API callbacks).
519 V8_EXPORT_PRIVATE V8_WARN_UNUSED_RESULT static Maybe<bool> SetProperty(
520 LookupIterator* it, Handle<Object> value, StoreOrigin store_origin,
521 Maybe<ShouldThrow> should_throw = Nothing<ShouldThrow>());
522 V8_EXPORT_PRIVATE V8_WARN_UNUSED_RESULT static MaybeHandle<Object>
523 SetProperty(Isolate* isolate, Handle<Object> object, Handle<Name> name,
524 Handle<Object> value,
525 StoreOrigin store_origin = StoreOrigin::kMaybeKeyed,
526 Maybe<ShouldThrow> should_throw = Nothing<ShouldThrow>());
527 V8_WARN_UNUSED_RESULT static inline MaybeHandle<Object> SetPropertyOrElement(
528 Isolate* isolate, Handle<Object> object, Handle<Name> name,
529 Handle<Object> value,
530 Maybe<ShouldThrow> should_throw = Nothing<ShouldThrow>(),
531 StoreOrigin store_origin = StoreOrigin::kMaybeKeyed);
532
533 V8_WARN_UNUSED_RESULT static Maybe<bool> SetSuperProperty(
534 LookupIterator* it, Handle<Object> value, StoreOrigin store_origin,
535 Maybe<ShouldThrow> should_throw = Nothing<ShouldThrow>());
536
537 V8_WARN_UNUSED_RESULT static Maybe<bool> CannotCreateProperty(
538 Isolate* isolate, Handle<Object> receiver, Handle<Object> name,
539 Handle<Object> value, Maybe<ShouldThrow> should_throw);
540 V8_WARN_UNUSED_RESULT static Maybe<bool> WriteToReadOnlyProperty(
541 LookupIterator* it, Handle<Object> value,
542 Maybe<ShouldThrow> should_throw);
543 V8_WARN_UNUSED_RESULT static Maybe<bool> WriteToReadOnlyProperty(
544 Isolate* isolate, Handle<Object> receiver, Handle<Object> name,
545 Handle<Object> value, ShouldThrow should_throw);
546 V8_WARN_UNUSED_RESULT static Maybe<bool> RedefineIncompatibleProperty(
547 Isolate* isolate, Handle<Object> name, Handle<Object> value,
548 Maybe<ShouldThrow> should_throw);
549 V8_WARN_UNUSED_RESULT static Maybe<bool> SetDataProperty(
550 LookupIterator* it, Handle<Object> value);
551 V8_WARN_UNUSED_RESULT static Maybe<bool> AddDataProperty(
552 LookupIterator* it, Handle<Object> value, PropertyAttributes attributes,
553 Maybe<ShouldThrow> should_throw, StoreOrigin store_origin,
554 EnforceDefineSemantics semantics = EnforceDefineSemantics::kSet);
555
556 V8_WARN_UNUSED_RESULT static Maybe<bool> TransitionAndWriteDataProperty(
557 LookupIterator* it, Handle<Object> value, PropertyAttributes attributes,
558 Maybe<ShouldThrow> should_throw, StoreOrigin store_origin);
559
560 V8_WARN_UNUSED_RESULT static inline MaybeHandle<Object> GetPropertyOrElement(
561 Isolate* isolate, Handle<Object> object, Handle<Name> name);
562 V8_WARN_UNUSED_RESULT static inline MaybeHandle<Object> GetPropertyOrElement(
563 Handle<Object> receiver, Handle<Name> name, Handle<JSReceiver> holder);
564 V8_WARN_UNUSED_RESULT static inline MaybeHandle<Object> GetProperty(
565 Isolate* isolate, Handle<Object> object, Handle<Name> name);
566
567 V8_WARN_UNUSED_RESULT static MaybeHandle<Object> GetPropertyWithAccessor(
568 LookupIterator* it);
569 V8_WARN_UNUSED_RESULT static Maybe<bool> SetPropertyWithAccessor(
570 LookupIterator* it, Handle<Object> value,
571 Maybe<ShouldThrow> should_throw);
572
573 V8_WARN_UNUSED_RESULT static MaybeHandle<Object> GetPropertyWithDefinedGetter(
574 Handle<Object> receiver, Handle<JSReceiver> getter);
575 V8_WARN_UNUSED_RESULT static Maybe<bool> SetPropertyWithDefinedSetter(
576 Handle<Object> receiver, Handle<JSReceiver> setter, Handle<Object> value,
577 Maybe<ShouldThrow> should_throw);
578
579 V8_WARN_UNUSED_RESULT static inline MaybeHandle<Object> GetElement(
580 Isolate* isolate, Handle<Object> object, uint32_t index);
581
582 V8_WARN_UNUSED_RESULT static inline MaybeHandle<Object> SetElement(
583 Isolate* isolate, Handle<Object> object, uint32_t index,
584 Handle<Object> value, ShouldThrow should_throw);
585
586 // Returns the permanent hash code associated with this object. May return
587 // undefined if not yet created.
588 inline Object GetHash();
589
590 // Returns the permanent hash code associated with this object depending on
591 // the actual object type. May create and store a hash code if needed and none
592 // exists.
593 V8_EXPORT_PRIVATE Smi GetOrCreateHash(Isolate* isolate);
594
595 // Checks whether this object has the same value as the given one. This
596 // function is implemented according to ES5, section 9.12 and can be used
597 // to implement the Object.is function.
598 V8_EXPORT_PRIVATE bool SameValue(Object other);
599
600 // A part of SameValue which handles Number vs. Number case.
601 // Treats NaN == NaN and +0 != -0.
602 inline static bool SameNumberValue(double number1, double number2);
603
604 // Checks whether this object has the same value as the given one.
605 // +0 and -0 are treated equal. Everything else is the same as SameValue.
606 // This function is implemented according to ES6, section 7.2.4 and is used
607 // by ES6 Map and Set.
608 bool SameValueZero(Object other);
609
610 // ES6 section 9.4.2.3 ArraySpeciesCreate (part of it)
611 V8_WARN_UNUSED_RESULT static MaybeHandle<Object> ArraySpeciesConstructor(
612 Isolate* isolate, Handle<Object> original_array);
613
614 // ES6 section 7.3.20 SpeciesConstructor ( O, defaultConstructor )
615 V8_WARN_UNUSED_RESULT static MaybeHandle<Object> SpeciesConstructor(
616 Isolate* isolate, Handle<JSReceiver> recv,
617 Handle<JSFunction> default_ctor);
618
619 // Tries to convert an object to an array length. Returns true and sets the
620 // output parameter if it succeeds.
621 inline bool ToArrayLength(uint32_t* index) const;
622
623 // Tries to convert an object to an array index. Returns true and sets the
624 // output parameter if it succeeds. Equivalent to ToArrayLength, but does not
625 // allow kMaxUInt32.
626 V8_WARN_UNUSED_RESULT inline bool ToArrayIndex(uint32_t* index) const;
627
628 // Tries to convert an object to an index (in the range 0..size_t::max).
629 // Returns true and sets the output parameter if it succeeds.
630 inline bool ToIntegerIndex(size_t* index) const;
631
632 // Returns true if the result of iterating over the object is the same
633 // (including observable effects) as simply accessing the properties between 0
634 // and length.
635 V8_EXPORT_PRIVATE bool IterationHasObservableEffects();
636
637 // TC39 "Dynamic Code Brand Checks"
638 bool IsCodeLike(Isolate* isolate) const;
639
640 EXPORT_DECL_VERIFIER(Object)
641
642 #ifdef VERIFY_HEAP
643 // Verify a pointer is a valid (non-Code) object pointer.
644 // When V8_EXTERNAL_CODE_SPACE is enabled Code objects are not allowed.
645 static void VerifyPointer(Isolate* isolate, Object p);
646 // Verify a pointer is a valid object pointer.
647 // Code objects are allowed regardless of the V8_EXTERNAL_CODE_SPACE mode.
648 static void VerifyAnyTagged(Isolate* isolate, Object p);
649 #endif
650
651 inline void VerifyApiCallResultType();
652
653 // Prints this object without details.
654 V8_EXPORT_PRIVATE void ShortPrint(FILE* out = stdout) const;
655
656 // Prints this object without details to a message accumulator.
657 V8_EXPORT_PRIVATE void ShortPrint(StringStream* accumulator) const;
658
659 V8_EXPORT_PRIVATE void ShortPrint(std::ostream& os) const;
660
cast(Object object)661 inline static Object cast(Object object) { return object; }
unchecked_cast(Object object)662 inline static Object unchecked_cast(Object object) { return object; }
663
664 // Layout description.
665 static const int kHeaderSize = 0; // Object does not take up any space.
666
667 #ifdef OBJECT_PRINT
668 // For our gdb macros, we should perhaps change these in the future.
669 V8_EXPORT_PRIVATE void Print() const;
670
671 // Prints this object with details.
672 V8_EXPORT_PRIVATE void Print(std::ostream& os) const;
673 #else
Print()674 void Print() const { ShortPrint(); }
Print(std::ostream & os)675 void Print(std::ostream& os) const { ShortPrint(os); }
676 #endif
677
678 // For use with std::unordered_set.
679 struct Hasher {
operatorHasher680 size_t operator()(const Object o) const {
681 return std::hash<v8::internal::Address>{}(static_cast<Tagged_t>(o.ptr()));
682 }
683 };
684
685 // For use with std::map.
686 struct Comparer {
operatorComparer687 bool operator()(const Object a, const Object b) const { return a < b; }
688 };
689
690 template <class T, typename std::enable_if<std::is_arithmetic<T>::value ||
691 std::is_enum<T>::value,
692 int>::type = 0>
ReadField(size_t offset)693 inline T ReadField(size_t offset) const {
694 return ReadMaybeUnalignedValue<T>(field_address(offset));
695 }
696
697 template <class T, typename std::enable_if<std::is_arithmetic<T>::value ||
698 std::is_enum<T>::value,
699 int>::type = 0>
WriteField(size_t offset,T value)700 inline void WriteField(size_t offset, T value) const {
701 return WriteMaybeUnalignedValue<T>(field_address(offset), value);
702 }
703
704 // Atomically reads a field using relaxed memory ordering. Can only be used
705 // with integral types whose size is <= kTaggedSize (to guarantee alignment).
706 template <class T,
707 typename std::enable_if<(std::is_arithmetic<T>::value ||
708 std::is_enum<T>::value) &&
709 !std::is_floating_point<T>::value,
710 int>::type = 0>
711 inline T Relaxed_ReadField(size_t offset) const;
712
713 // Atomically writes a field using relaxed memory ordering. Can only be used
714 // with integral types whose size is <= kTaggedSize (to guarantee alignment).
715 template <class T,
716 typename std::enable_if<(std::is_arithmetic<T>::value ||
717 std::is_enum<T>::value) &&
718 !std::is_floating_point<T>::value,
719 int>::type = 0>
720 inline void Relaxed_WriteField(size_t offset, T value);
721
722 //
723 // SandboxedPointer_t field accessors.
724 //
725 inline Address ReadSandboxedPointerField(size_t offset,
726 PtrComprCageBase cage_base) const;
727 inline void WriteSandboxedPointerField(size_t offset,
728 PtrComprCageBase cage_base,
729 Address value);
730 inline void WriteSandboxedPointerField(size_t offset, Isolate* isolate,
731 Address value);
732
733 //
734 // ExternalPointer_t field accessors.
735 //
736 inline void InitExternalPointerField(size_t offset, Isolate* isolate,
737 ExternalPointerTag tag);
738 inline void InitExternalPointerField(size_t offset, Isolate* isolate,
739 Address value, ExternalPointerTag tag);
740 inline Address ReadExternalPointerField(size_t offset, Isolate* isolate,
741 ExternalPointerTag tag) const;
742 inline void WriteExternalPointerField(size_t offset, Isolate* isolate,
743 Address value, ExternalPointerTag tag);
744
745 // If the receiver is the JSGlobalObject, the store was contextual. In case
746 // the property did not exist yet on the global object itself, we have to
747 // throw a reference error in strict mode. In sloppy mode, we continue.
748 // Returns false if the exception was thrown, otherwise true.
749 static bool CheckContextualStoreToJSGlobalObject(
750 LookupIterator* it, Maybe<ShouldThrow> should_throw);
751
752 // Returns whether the object is safe to share across Isolates.
753 //
754 // Currently, the following kinds of values can be safely shared across
755 // Isolates:
756 // - Smis
757 // - Objects in RO space when the RO space is shared
758 // - HeapNumbers in the shared old space
759 // - Strings for which String::IsShared() is true
760 // - JSSharedStructs
761 inline bool IsShared() const;
762
763 // Returns an equivalent value that's safe to share across Isolates if
764 // possible. Acts as the identity function when value->IsShared().
765 static inline MaybeHandle<Object> Share(
766 Isolate* isolate, Handle<Object> value,
767 ShouldThrow throw_if_cannot_be_shared);
768
769 static MaybeHandle<Object> ShareSlow(Isolate* isolate,
770 Handle<HeapObject> value,
771 ShouldThrow throw_if_cannot_be_shared);
772
773 // Whether this Object can be held weakly, i.e. whether it can be used as a
774 // key in WeakMap, as a key in WeakSet, as the target of a WeakRef, or as a
775 // target or unregister token of a FinalizationRegistry.
776 inline bool CanBeHeldWeakly() const;
777
778 protected:
field_address(size_t offset)779 inline Address field_address(size_t offset) const {
780 return ptr() + offset - kHeapObjectTag;
781 }
782
783 private:
784 friend class CompressedObjectSlot;
785 friend class FullObjectSlot;
786 friend class LookupIterator;
787 friend class StringStream;
788
789 // Return the map of the root of object's prototype chain.
790 Map GetPrototypeChainRootMap(Isolate* isolate) const;
791
792 // Returns a non-SMI for JSReceivers, but returns the hash code for
793 // simple objects. This avoids a double lookup in the cases where
794 // we know we will add the hash to the JSReceiver if it does not
795 // already exist.
796 //
797 // Despite its size, this needs to be inlined for performance
798 // reasons.
799 static inline Object GetSimpleHash(Object object);
800
801 // Helper for SetProperty and SetSuperProperty.
802 // Return value is only meaningful if [found] is set to true on return.
803 V8_WARN_UNUSED_RESULT static Maybe<bool> SetPropertyInternal(
804 LookupIterator* it, Handle<Object> value, Maybe<ShouldThrow> should_throw,
805 StoreOrigin store_origin, bool* found);
806
807 V8_WARN_UNUSED_RESULT static MaybeHandle<Name> ConvertToName(
808 Isolate* isolate, Handle<Object> input);
809 V8_WARN_UNUSED_RESULT static MaybeHandle<Object> ConvertToPropertyKey(
810 Isolate* isolate, Handle<Object> value);
811 V8_EXPORT_PRIVATE V8_WARN_UNUSED_RESULT static MaybeHandle<String>
812 ConvertToString(Isolate* isolate, Handle<Object> input);
813 V8_WARN_UNUSED_RESULT static MaybeHandle<Object> ConvertToNumberOrNumeric(
814 Isolate* isolate, Handle<Object> input, Conversion mode);
815 V8_EXPORT_PRIVATE V8_WARN_UNUSED_RESULT static MaybeHandle<Object>
816 ConvertToInteger(Isolate* isolate, Handle<Object> input);
817 V8_WARN_UNUSED_RESULT static MaybeHandle<Object> ConvertToInt32(
818 Isolate* isolate, Handle<Object> input);
819 V8_WARN_UNUSED_RESULT static MaybeHandle<Object> ConvertToUint32(
820 Isolate* isolate, Handle<Object> input);
821 V8_EXPORT_PRIVATE V8_WARN_UNUSED_RESULT static MaybeHandle<Object>
822 ConvertToLength(Isolate* isolate, Handle<Object> input);
823 V8_EXPORT_PRIVATE V8_WARN_UNUSED_RESULT static MaybeHandle<Object>
824 ConvertToIndex(Isolate* isolate, Handle<Object> input,
825 MessageTemplate error_index);
826 };
827
828 V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os, const Object& obj);
829
830 struct Brief {
831 template <typename TObject>
BriefBrief832 explicit Brief(TObject v) : value{v.ptr()} {}
833 // {value} is a tagged heap object reference (weak or strong), equivalent to
834 // a MaybeObject's payload. It has a plain Address type to keep #includes
835 // lightweight.
836 const Address value;
837 };
838
839 V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os, const Brief& v);
840
841 // Objects should never have the weak tag; this variant is for overzealous
842 // checking.
HasWeakHeapObjectTag(const Object value)843 V8_INLINE static bool HasWeakHeapObjectTag(const Object value) {
844 return HAS_WEAK_HEAP_OBJECT_TAG(value.ptr());
845 }
846
847 // Heap objects typically have a map pointer in their first word. However,
848 // during GC other data (e.g. mark bits, forwarding addresses) is sometimes
849 // encoded in the first word. The class MapWord is an abstraction of the
850 // value in a heap object's first word.
851 class MapWord {
852 public:
853 // Normal state: the map word contains a map pointer.
854
855 // Create a map word from a map pointer.
856 static inline MapWord FromMap(const Map map);
857
858 // View this map word as a map pointer.
859 inline Map ToMap() const;
860
861 // Scavenge collection: the map word of live objects in the from space
862 // contains a forwarding address (a heap object pointer in the to space).
863
864 // True if this map word is a forwarding address for a scavenge
865 // collection. Only valid during a scavenge collection (specifically,
866 // when all map words are heap object pointers, i.e. not during a full GC).
867 inline bool IsForwardingAddress() const;
868
869 // Create a map word from a forwarding address.
870 static inline MapWord FromForwardingAddress(HeapObject object);
871
872 // View this map word as a forwarding address. The parameterless version
873 // is allowed to be used for objects allocated in the main pointer compression
874 // cage, while the second variant uses the value of the cage base explicitly
875 // and thus can be used in situations where one has to deal with both cases.
876 // Note, that the parameterless version is preferred because it avoids
877 // unnecessary recompressions.
878 inline HeapObject ToForwardingAddress();
879 inline HeapObject ToForwardingAddress(PtrComprCageBase host_cage_base);
880
ptr()881 inline Address ptr() { return value_; }
882
883 #ifdef V8_MAP_PACKING
Pack(Address map)884 static constexpr Address Pack(Address map) {
885 return map ^ Internals::kMapWordXorMask;
886 }
Unpack(Address mapword)887 static constexpr Address Unpack(Address mapword) {
888 // TODO(wenyuzhao): Clear header metadata.
889 return mapword ^ Internals::kMapWordXorMask;
890 }
IsPacked(Address mapword)891 static constexpr bool IsPacked(Address mapword) {
892 return (static_cast<intptr_t>(mapword) & Internals::kMapWordXorMask) ==
893 Internals::kMapWordSignature &&
894 (0xffffffff00000000 & static_cast<intptr_t>(mapword)) != 0;
895 }
896 #else
IsPacked(Address)897 static constexpr bool IsPacked(Address) { return false; }
898 #endif
899
900 private:
901 // HeapObject calls the private constructor and directly reads the value.
902 friend class HeapObject;
903 template <typename TFieldType, int kFieldOffset>
904 friend class TaggedField;
905
MapWord(Address value)906 explicit MapWord(Address value) : value_(value) {}
907
908 Address value_;
909 };
910
911 template <int start_offset, int end_offset, int size>
912 class FixedBodyDescriptor;
913
914 template <int start_offset>
915 class FlexibleBodyDescriptor;
916
917 template <int start_offset>
918 class FlexibleWeakBodyDescriptor;
919
920 template <class ParentBodyDescriptor, class ChildBodyDescriptor>
921 class SubclassBodyDescriptor;
922
923 enum EnsureElementsMode {
924 DONT_ALLOW_DOUBLE_ELEMENTS,
925 ALLOW_COPIED_DOUBLE_ELEMENTS,
926 ALLOW_CONVERTED_DOUBLE_ELEMENTS
927 };
928
929 // Indicator for one component of an AccessorPair.
930 enum AccessorComponent { ACCESSOR_GETTER, ACCESSOR_SETTER };
931
932 // Utility superclass for stack-allocated objects that must be updated
933 // on gc. It provides two ways for the gc to update instances, either
934 // iterating or updating after gc.
935 class Relocatable {
936 public:
937 explicit inline Relocatable(Isolate* isolate);
938 inline virtual ~Relocatable();
IterateInstance(RootVisitor * v)939 virtual void IterateInstance(RootVisitor* v) {}
PostGarbageCollection()940 virtual void PostGarbageCollection() {}
941
942 static void PostGarbageCollectionProcessing(Isolate* isolate);
943 static int ArchiveSpacePerThread();
944 static char* ArchiveState(Isolate* isolate, char* to);
945 static char* RestoreState(Isolate* isolate, char* from);
946 static void Iterate(Isolate* isolate, RootVisitor* v);
947 static void Iterate(RootVisitor* v, Relocatable* top);
948 static char* Iterate(RootVisitor* v, char* t);
949
950 private:
951 Isolate* isolate_;
952 Relocatable* prev_;
953 };
954
955 // BooleanBit is a helper class for setting and getting a bit in an integer.
956 class BooleanBit : public AllStatic {
957 public:
get(int value,int bit_position)958 static inline bool get(int value, int bit_position) {
959 return (value & (1 << bit_position)) != 0;
960 }
961
set(int value,int bit_position,bool v)962 static inline int set(int value, int bit_position, bool v) {
963 if (v) {
964 value |= (1 << bit_position);
965 } else {
966 value &= ~(1 << bit_position);
967 }
968 return value;
969 }
970 };
971
972 } // namespace internal
973 } // namespace v8
974
975 #include "src/objects/object-macros-undef.h"
976
977 #endif // V8_OBJECTS_OBJECTS_H_
978