• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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