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