objects.h 37.9 KB
Newer Older
1
// Copyright 2015 the V8 project authors. All rights reserved.
2 3
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
4

5 6
#ifndef V8_OBJECTS_OBJECTS_H_
#define V8_OBJECTS_OBJECTS_H_
7

8
#include <iosfwd>
9
#include <memory>
10

11
#include "include/v8-internal.h"
Marja Hölttä's avatar
Marja Hölttä committed
12
#include "include/v8config.h"
13
#include "src/base/bits.h"
Marja Hölttä's avatar
Marja Hölttä committed
14
#include "src/base/build_config.h"
15
#include "src/base/flags.h"
Marja Hölttä's avatar
Marja Hölttä committed
16
#include "src/base/logging.h"
17
#include "src/base/memory.h"
18
#include "src/codegen/constants-arch.h"
19 20
#include "src/common/assert-scope.h"
#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 26
#include "src/objects/elements-kind.h"
#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 34
// Has to be the last include (doesn't have include guards):
#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 41
// - Object
//   - Smi          (immediate small integer)
42
//   - TaggedIndex  (properly sign-extended immediate small integer)
43 44 45 46 47 48 49 50
//   - HeapObject   (superclass for everything allocated in the heap)
//     - JSReceiver  (suitable for property access)
//       - JSObject
//         - JSArray
//         - JSArrayBuffer
//         - JSArrayBufferView
//           - JSTypedArray
//           - JSDataView
51 52 53
//         - JSCollection
//           - JSSet
//           - JSMap
54 55 56 57 58 59
//         - JSCustomElementsObject (may have elements despite empty FixedArray)
//           - JSSpecialObject (requires custom property lookup handling)
//             - JSGlobalObject
//             - JSGlobalProxy
//             - JSModuleNamespace
//           - JSPrimitiveWrapper
60
//         - JSDate
61
//         - JSFunctionOrBoundFunctionOrWrappedFunction
62 63
//           - JSBoundFunction
//           - JSFunction
64
//           - JSWrappedFunction
65
//         - JSGeneratorObject
66
//         - JSMapIterator
67
//         - JSMessageObject
68 69
//         - JSRegExp
//         - JSSetIterator
70
//         - JSShadowRealm
71
//         - JSSharedStruct
72
//         - JSStringIterator
73 74 75 76 77 78 79 80 81 82
//         - JSTemporalCalendar
//         - JSTemporalDuration
//         - JSTemporalInstant
//         - JSTemporalPlainDate
//         - JSTemporalPlainDateTime
//         - JSTemporalPlainMonthDay
//         - JSTemporalPlainTime
//         - JSTemporalPlainYearMonth
//         - JSTemporalTimeZone
//         - JSTemporalZonedDateTime
83 84 85
//         - JSWeakCollection
//           - JSWeakMap
//           - JSWeakSet
86
//         - JSCollator            // If V8_INTL_SUPPORT enabled.
87
//         - JSDateTimeFormat      // If V8_INTL_SUPPORT enabled.
88
//         - JSDisplayNames        // If V8_INTL_SUPPORT enabled.
89 90
//         - JSListFormat          // If V8_INTL_SUPPORT enabled.
//         - 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 97
//         - JSSegmentIterator     // If V8_INTL_SUPPORT enabled.
//         - JSV8BreakIterator     // If V8_INTL_SUPPORT enabled.
98
//         - WasmTagObject
99
//         - WasmGlobalObject
100 101 102 103
//         - WasmInstanceObject
//         - WasmMemoryObject
//         - WasmModuleObject
//         - WasmTableObject
104
//         - WasmSuspenderObject
105 106 107
//       - JSProxy
//     - FixedArrayBase
//       - ByteArray
108
//       - BytecodeArray
109 110 111 112
//       - FixedArray
//         - HashTable
//           - Dictionary
//           - StringTable
113
//           - StringSet
114 115 116 117 118
//           - CompilationCacheTable
//           - MapCache
//         - OrderedHashTable
//           - OrderedHashSet
//           - OrderedHashMap
119
//         - FeedbackMetadata
120
//         - TemplateList
121
//         - TransitionArray
122
//         - ScopeInfo
123
//         - SourceTextModuleInfo
124
//         - ScriptContextTable
125
//         - ClosureFeedbackCellArray
126
//       - FixedDoubleArray
127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150
//     - PrimitiveHeapObject
//       - BigInt
//       - HeapNumber
//       - Name
//         - String
//           - SeqString
//             - SeqOneByteString
//             - SeqTwoByteString
//           - SlicedString
//           - ConsString
//           - ThinString
//           - ExternalString
//             - ExternalOneByteString
//             - ExternalTwoByteString
//           - InternalizedString
//             - SeqInternalizedString
//               - SeqOneByteInternalizedString
//               - SeqTwoByteInternalizedString
//             - ConsInternalizedString
//             - ExternalInternalizedString
//               - ExternalOneByteInternalizedString
//               - ExternalTwoByteInternalizedString
//         - Symbol
//       - Oddball
151 152
//     - Context
//       - NativeContext
153
//     - Cell
154
//     - DescriptorArray
155
//     - PropertyCell
156
//     - PropertyArray
157
//     - Code
158
//     - AbstractCode, a wrapper around Code or BytecodeArray
159 160
//     - Map
//     - Foreign
161 162 163
//     - SmallOrderedHashTable
//       - SmallOrderedHashMap
//       - SmallOrderedHashSet
164 165 166
//     - SharedFunctionInfo
//     - Struct
//       - AccessorInfo
167
//       - AsmWasmData
168
//       - PromiseReaction
169
//       - PromiseCapability
170 171 172 173
//       - AccessorPair
//       - AccessCheckInfo
//       - InterceptorInfo
//       - CallHandlerInfo
174
//       - EnumCache
175 176 177 178 179
//       - TemplateInfo
//         - FunctionTemplateInfo
//         - ObjectTemplateInfo
//       - Script
//       - DebugInfo
180
//       - BreakPoint
181
//       - BreakPointInfo
182
//       - CachedTemplateObject
183
//       - CallSiteInfo
184
//       - CodeCache
185
//       - PropertyDescriptorObject
186
//       - PromiseOnStack
187
//       - PrototypeInfo
188 189 190 191 192 193 194
//       - Microtask
//         - CallbackTask
//         - CallableTask
//         - PromiseReactionJobTask
//           - PromiseFulfillReactionJobTask
//           - PromiseRejectReactionJobTask
//         - PromiseResolveThenableJobTask
195
//       - Module
196
//         - SourceTextModule
197
//         - SyntheticModule
198
//       - SourceTextModuleInfoEntry
199
//       - StackFrameInfo
200
//     - FeedbackCell
201
//     - FeedbackVector
202
//     - PreparseData
203
//     - UncompiledData
204 205
//       - UncompiledDataWithoutPreparseData
//       - UncompiledDataWithPreparseData
206
//     - SwissNameDictionary
207
//
208
// Formats of Object::ptr_:
209 210 211
//  Smi:        [31 bit signed int] 0
//  HeapObject: [32 bit direct pointer] (4 byte aligned) | 01

212 213
namespace v8 {
namespace internal {
214

215
struct InliningPosition;
216
class PropertyDescriptorObject;
217

218 219 220
// UNSAFE_SKIP_WRITE_BARRIER skips the write barrier.
// SKIP_WRITE_BARRIER skips the write barrier and asserts that this is safe in
// the MemoryOptimizer
221 222 223 224 225
// UPDATE_WEAK_WRITE_BARRIER skips the marking part of the write barrier and
// only performs the generational part.
// UPDATE_WRITE_BARRIER is doing the full barrier, marking and generational.
enum WriteBarrierMode {
  SKIP_WRITE_BARRIER,
226
  UNSAFE_SKIP_WRITE_BARRIER,
227
  UPDATE_WEAK_WRITE_BARRIER,
228
  UPDATE_EPHEMERON_KEY_WRITE_BARRIER,
229 230
  UPDATE_WRITE_BARRIER
};
231

ager@chromium.org's avatar
ager@chromium.org committed
232 233
// PropertyNormalizationMode is used to specify whether to keep
// inobject properties when normalizing properties of a JSObject.
234 235 236 237 238
enum PropertyNormalizationMode {
  CLEAR_INOBJECT_PROPERTIES,
  KEEP_INOBJECT_PROPERTIES
};

239
// Indicates whether transitions can be added to a source map or not.
240
enum TransitionFlag { INSERT_TRANSITION, OMIT_TRANSITION };
241 242 243 244

// Indicates whether the transition is simple: the target map of the transition
// either extends the current map with a new property, or it modifies the
// property that was added last to the current map.
245 246 247
enum SimpleTransitionFlag {
  SIMPLE_PROPERTY_TRANSITION,
  PROPERTY_TRANSITION,
248
  SPECIAL_TRANSITION
249
};
250

251 252
// Indicates whether we are only interested in the descriptors of a particular
// 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 259
// We may store the unsigned bit field as signed Smi value and do not
// use the sign bit.
260
const int kStubMajorKeyBits = 8;
261
const int kStubMinorKeyBits = kSmiValueSize - kStubMajorKeyBits - 1;
262

263 264 265 266 267
// Result of an abstract relational comparison of x and y, implemented according
// to ES6 section 7.2.11 Abstract Relational Comparison.
enum class ComparisonResult {
  kLessThan,     // x < y
  kEqual,        // x = y
268
  kGreaterThan,  // x > y
269 270 271
  kUndefined     // at least one of x or y was undefined or NaN
};

272
// (Returns false whenever {result} is kUndefined.)
273
bool ComparisonResultToBool(Operation op, ComparisonResult result);
274

275 276
enum class OnNonExistent { kThrowReferenceError, kReturnUndefined };

277 278 279
// The element types selection for CreateListFromArrayLike.
enum class ElementTypes { kAll, kStringAndSymbol };

280 281 282 283 284 285 286 287 288 289
// Currently DefineOwnPropertyIgnoreAttributes invokes the setter
// interceptor and user-defined setters during define operations,
// even in places where it makes more sense to invoke the definer
// interceptor and not invoke the setter: e.g. both the definer and
// the setter interceptors are called in Object.defineProperty().
// kDefine allows us to implement the define semantics correctly
// in selected locations.
// TODO(joyee): see if we can deprecate the old behavior.
enum class EnforceDefineSemantics { kSet, kDefine };

290
// TODO(mythria): Move this to a better place.
291
ShouldThrow GetShouldThrow(Isolate* isolate, Maybe<ShouldThrow> should_throw);
292

293 294 295 296
// Object is the abstract superclass for all classes in the
// object hierarchy.
// Object does not use any virtual functions to avoid the
// allocation of the C++ vtable.
297 298 299
// There must only be a single data member in Object: the Address ptr,
// containing the tagged heap pointer that this Object instance refers to.
// For a design overview, see https://goo.gl/Ph4CGz.
300
class Object : public TaggedImpl<HeapObjectReferenceType::STRONG, Address> {
301
 public:
302 303
  constexpr Object() : TaggedImpl(kNullAddress) {}
  explicit constexpr Object(Address ptr) : TaggedImpl(ptr) {}
304

305 306
  V8_INLINE bool IsTaggedIndex() const;

307 308 309 310 311 312
  // Whether the object is in the RO heap and the RO heap is shared, or in the
  // writable shared heap.
  V8_INLINE bool InSharedHeap() const;

  V8_INLINE bool InSharedWritableHeap() const;

313 314
#define IS_TYPE_FUNCTION_DECL(Type) \
  V8_INLINE bool Is##Type() const;  \
315
  V8_INLINE bool Is##Type(PtrComprCageBase cage_base) const;
316 317
  OBJECT_TYPE_LIST(IS_TYPE_FUNCTION_DECL)
  HEAP_OBJECT_TYPE_LIST(IS_TYPE_FUNCTION_DECL)
318 319
  IS_TYPE_FUNCTION_DECL(HashTableBase)
  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 325
// Oddball checks are faster when they are raw pointer comparisons, so the
// isolate/read-only roots overloads should be preferred where possible.
326 327 328 329
#define IS_TYPE_FUNCTION_DECL(Type, Value)              \
  V8_INLINE bool Is##Type(Isolate* isolate) const;      \
  V8_INLINE bool Is##Type(LocalIsolate* isolate) const; \
  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 336
  V8_INLINE bool IsZero() const;
  V8_INLINE bool IsNoSharedNameSentinel() const;
337 338
  V8_INLINE bool IsPrivateSymbol() const;
  V8_INLINE bool IsPublicSymbol() const;
339

340 341
  enum class Conversion { kToNumber, kToNumeric };

342 343
#define DECL_STRUCT_PREDICATE(NAME, Name, name) \
  V8_INLINE bool Is##Name() const;              \
344
  V8_INLINE bool Is##Name(PtrComprCageBase cage_base) const;
345 346
  STRUCT_LIST(DECL_STRUCT_PREDICATE)
#undef DECL_STRUCT_PREDICATE
347

348
  // ES6, #sec-isarray.  NOT to be confused with %_IsArray.
349 350
  V8_INLINE
  V8_WARN_UNUSED_RESULT static Maybe<bool> IsArray(Handle<Object> object);
351

352
  // Extract the number.
353
  inline double Number() const;
354 355
  V8_INLINE bool IsNaN() const;
  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 364 365 366 367
  // If {allow_coercion} is true, then a Smi will be considered to fit
  // a Double representation, since it can be converted to a HeapNumber
  // and stored.
  inline bool FitsRepresentation(Representation representation,
                                 bool allow_coercion = true) const;
368

369
  inline bool FilterKey(PropertyFilter filter);
370

371 372
  Handle<FieldType> OptimalType(Isolate* isolate,
                                Representation representation);
373

374 375
  V8_EXPORT_PRIVATE static Handle<Object> NewStorageFor(
      Isolate* isolate, Handle<Object> object, Representation representation);
376

377 378 379
  template <AllocationType allocation_type = AllocationType::kYoung,
            typename IsolateT>
  static Handle<Object> WrapForRead(IsolateT* isolate, Handle<Object> object,
380
                                    Representation representation);
381

382 383 384 385
  // Returns true if the object is of the correct type to be used as a
  // implementation of a JSObject's elements.
  inline bool HasValidElements();

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 392
  V8_EXPORT_PRIVATE V8_WARN_UNUSED_RESULT static Maybe<ComparisonResult>
  Compare(Isolate* isolate, Handle<Object> x, Handle<Object> y);
393

394
  // ES6 section 7.2.12 Abstract Equality Comparison
395 396
  V8_EXPORT_PRIVATE V8_WARN_UNUSED_RESULT static Maybe<bool> Equals(
      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 406 407
  //
  // Passing a non-null method_name allows us to give a more informative
  // error message for those cases where ToObject is being called on
  // the receiver of a built-in method.
408
  V8_WARN_UNUSED_RESULT static inline MaybeHandle<JSReceiver> ToObject(
409 410
      Isolate* isolate, Handle<Object> object,
      const char* method_name = nullptr);
411 412
  V8_WARN_UNUSED_RESULT static MaybeHandle<JSReceiver> ToObjectImpl(
      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 418
      Isolate* isolate, Handle<Object> object);

419
  // ES6 section 7.1.14 ToPropertyKey
420 421
  V8_WARN_UNUSED_RESULT static inline MaybeHandle<Name> ToName(
      Isolate* isolate, Handle<Object> input);
422 423

  // ES6 section 7.1.1 ToPrimitive
424
  V8_WARN_UNUSED_RESULT static inline MaybeHandle<Object> ToPrimitive(
425 426
      Isolate* isolate, Handle<Object> input,
      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 452 453
  V8_EXPORT_PRIVATE static MaybeHandle<String> NoSideEffectsToMaybeString(
      Isolate* isolate, Handle<Object> input);

454 455
  V8_EXPORT_PRIVATE static Handle<String> NoSideEffectsToString(
      Isolate* isolate, Handle<Object> input);
456

457
  // ES6 section 7.1.14 ToPropertyKey
458
  V8_WARN_UNUSED_RESULT static inline MaybeHandle<Object> ToPropertyKey(
459 460
      Isolate* isolate, Handle<Object> value);

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 476
      Isolate* isolate, Handle<Object> object, ElementTypes element_types);

477
  // Get length property and apply ToLength.
478
  V8_WARN_UNUSED_RESULT static MaybeHandle<Object> GetLengthFromArrayLike(
479
      Isolate* isolate, Handle<JSReceiver> object);
480

481 482 483
  // ES6 section 12.5.6 The typeof Operator
  static Handle<String> TypeOf(Isolate* isolate, Handle<Object> object);

484
  // ES6 section 12.7 Additive Operators
485 486 487
  V8_WARN_UNUSED_RESULT static MaybeHandle<Object> Add(Isolate* isolate,
                                                       Handle<Object> lhs,
                                                       Handle<Object> rhs);
488

489
  // ES6 section 12.9 Relational Operators
490 491
  V8_WARN_UNUSED_RESULT static inline Maybe<bool> GreaterThan(Isolate* isolate,
                                                              Handle<Object> x,
492 493
                                                              Handle<Object> y);
  V8_WARN_UNUSED_RESULT static inline Maybe<bool> GreaterThanOrEqual(
494 495 496
      Isolate* isolate, Handle<Object> x, Handle<Object> y);
  V8_WARN_UNUSED_RESULT static inline Maybe<bool> LessThan(Isolate* isolate,
                                                           Handle<Object> x,
497 498
                                                           Handle<Object> y);
  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 504 505
      Isolate* isolate, Handle<Object> callable, Handle<Object> object);

  // ES6 section 12.10.4 Runtime Semantics: InstanceofOperator(O, C)
506
  V8_WARN_UNUSED_RESULT static MaybeHandle<Object> InstanceOf(
507 508
      Isolate* isolate, Handle<Object> object, Handle<Object> callable);

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 514
  // Invariants for this and related functions (unless stated otherwise):
  // 1) When the result is Nothing, an exception is pending.
515
  // 2) When passed kThrowOnError, the result is never Just(false).
516 517 518
  // In some cases, an exception is thrown regardless of the ShouldThrow
  // argument.  These cases are either in accordance with the spec or not
  // 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 523 524 525 526
  V8_EXPORT_PRIVATE V8_WARN_UNUSED_RESULT static MaybeHandle<Object>
  SetProperty(Isolate* isolate, Handle<Object> object, Handle<Name> name,
              Handle<Object> value,
              StoreOrigin store_origin = StoreOrigin::kMaybeKeyed,
              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);
arv's avatar
arv committed
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>());
arv's avatar
arv committed
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 542
      LookupIterator* it, Handle<Object> value,
      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(
arv's avatar
arv committed
547
      Isolate* isolate, Handle<Object> name, Handle<Object> value,
548
      Maybe<ShouldThrow> should_throw);
549 550 551
  V8_WARN_UNUSED_RESULT static Maybe<bool> SetDataProperty(
      LookupIterator* it, Handle<Object> value);
  V8_WARN_UNUSED_RESULT static Maybe<bool> AddDataProperty(
552 553 554 555 556
      LookupIterator* it, Handle<Object> value, PropertyAttributes attributes,
      Maybe<ShouldThrow> should_throw, StoreOrigin store_origin,
      EnforceDefineSemantics semantics = EnforceDefineSemantics::kSet);

  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 571
      LookupIterator* it, Handle<Object> value,
      Maybe<ShouldThrow> should_throw);
572

573 574 575
  V8_WARN_UNUSED_RESULT static MaybeHandle<Object> GetPropertyWithDefinedGetter(
      Handle<Object> receiver, Handle<JSReceiver> getter);
  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 587
  // Returns the permanent hash code associated with this object. May return
  // undefined if not yet created.
588
  inline Object GetHash();
589

590
  // Returns the permanent hash code associated with this object depending on
591 592
  // the actual object type. May create and store a hash code if needed and none
  // exists.
593
  V8_EXPORT_PRIVATE Smi GetOrCreateHash(Isolate* isolate);
594 595 596

  // Checks whether this object has the same value as the given one.  This
  // 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 601 602 603
  // A part of SameValue which handles Number vs. Number case.
  // Treats NaN == NaN and +0 != -0.
  inline static bool SameNumberValue(double number1, double number2);

604 605 606 607
  // Checks whether this object has the same value as the given one.
  // +0 and -0 are treated equal. Everything else is the same as SameValue.
  // This function is implemented according to ES6, section 7.2.4 and is used
  // 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 613
      Isolate* isolate, Handle<Object> original_array);

614
  // ES6 section 7.3.20 SpeciesConstructor ( O, defaultConstructor )
615
  V8_WARN_UNUSED_RESULT static MaybeHandle<Object> SpeciesConstructor(
616 617 618
      Isolate* isolate, Handle<JSReceiver> recv,
      Handle<JSFunction> default_ctor);

619 620
  // Tries to convert an object to an array length. Returns true and sets the
  // output parameter if it succeeds.
621
  inline bool ToArrayLength(uint32_t* index) const;
622 623 624 625

  // Tries to convert an object to an array index. Returns true and sets the
  // output parameter if it succeeds. Equivalent to ToArrayLength, but does not
  // allow kMaxUInt32.
626
  V8_WARN_UNUSED_RESULT inline bool ToArrayIndex(uint32_t* index) const;
627

628 629 630 631
  // Tries to convert an object to an index (in the range 0..size_t::max).
  // Returns true and sets the output parameter if it succeeds.
  inline bool ToIntegerIndex(size_t* index) const;

632 633 634
  // Returns true if the result of iterating over the object is the same
  // (including observable effects) as simply accessing the properties between 0
  // 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 644
  // Verify a pointer is a valid (non-Code) object pointer.
  // When V8_EXTERNAL_CODE_SPACE is enabled Code objects are not allowed.
645
  static void VerifyPointer(Isolate* isolate, Object p);
646 647 648
  // Verify a pointer is a valid object pointer.
  // Code objects are allowed regardless of the V8_EXTERNAL_CODE_SPACE mode.
  static void VerifyAnyTagged(Isolate* isolate, Object p);
649 650
#endif

651 652
  inline void VerifyApiCallResultType();

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

661 662
  inline static Object cast(Object object) { return object; }
  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
674
  void Print() const { ShortPrint(); }
675
  void Print(std::ostream& os) const { ShortPrint(os); }
676 677
#endif

678 679 680
  // For use with std::unordered_set.
  struct Hasher {
    size_t operator()(const Object o) const {
681
      return std::hash<v8::internal::Address>{}(static_cast<Tagged_t>(o.ptr()));
682 683 684 685 686
    }
  };

  // For use with std::map.
  struct Comparer {
687
    bool operator()(const Object a, const Object b) const { return a < b; }
688 689
  };

690 691
  template <class T, typename std::enable_if<std::is_arithmetic<T>::value ||
                                                 std::is_enum<T>::value,
692 693
                                             int>::type = 0>
  inline T ReadField(size_t offset) const {
694
    return ReadMaybeUnalignedValue<T>(field_address(offset));
695 696
  }

697 698 699 700 701 702 703
  template <class T, typename std::enable_if<std::is_arithmetic<T>::value ||
                                                 std::is_enum<T>::value,
                                             int>::type = 0>
  inline void WriteField(size_t offset, T value) const {
    return WriteMaybeUnalignedValue<T>(field_address(offset), value);
  }

704 705 706 707 708 709 710 711 712
  // Atomically reads a field using relaxed memory ordering. Can only be used
  // with integral types whose size is <= kTaggedSize (to guarantee alignment).
  template <class T,
            typename std::enable_if<(std::is_arithmetic<T>::value ||
                                     std::is_enum<T>::value) &&
                                        !std::is_floating_point<T>::value,
                                    int>::type = 0>
  inline T Relaxed_ReadField(size_t offset) const;

713 714 715 716 717 718 719 720
  // Atomically writes a field using relaxed memory ordering. Can only be used
  // with integral types whose size is <= kTaggedSize (to guarantee alignment).
  template <class T,
            typename std::enable_if<(std::is_arithmetic<T>::value ||
                                     std::is_enum<T>::value) &&
                                        !std::is_floating_point<T>::value,
                                    int>::type = 0>
  inline void Relaxed_WriteField(size_t offset, T value);
721

Samuel Groß's avatar
Samuel Groß committed
722
  //
Samuel Groß's avatar
Samuel Groß committed
723
  // SandboxedPointer_t field accessors.
Samuel Groß's avatar
Samuel Groß committed
724
  //
Samuel Groß's avatar
Samuel Groß committed
725 726 727 728 729 730 731
  inline Address ReadSandboxedPointerField(size_t offset,
                                           PtrComprCageBase cage_base) const;
  inline void WriteSandboxedPointerField(size_t offset,
                                         PtrComprCageBase cage_base,
                                         Address value);
  inline void WriteSandboxedPointerField(size_t offset, Isolate* isolate,
                                         Address value);
Samuel Groß's avatar
Samuel Groß committed
732

733 734 735
  //
  // ExternalPointer_t field accessors.
  //
736 737
  inline void InitExternalPointerField(size_t offset, Isolate* isolate,
                                       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 746 747 748 749 750 751
  // If the receiver is the JSGlobalObject, the store was contextual. In case
  // the property did not exist yet on the global object itself, we have to
  // throw a reference error in strict mode.  In sloppy mode, we continue.
  // Returns false if the exception was thrown, otherwise true.
  static bool CheckContextualStoreToJSGlobalObject(
      LookupIterator* it, Maybe<ShouldThrow> should_throw);

752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772
  // Returns whether the object is safe to share across Isolates.
  //
  // Currently, the following kinds of values can be safely shared across
  // Isolates:
  // - Smis
  // - Objects in RO space when the RO space is shared
  // - HeapNumbers in the shared old space
  // - Strings for which String::IsShared() is true
  // - JSSharedStructs
  inline bool IsShared() const;

  // Returns an equivalent value that's safe to share across Isolates if
  // possible. Acts as the identity function when value->IsShared().
  static inline MaybeHandle<Object> Share(
      Isolate* isolate, Handle<Object> value,
      ShouldThrow throw_if_cannot_be_shared);

  static MaybeHandle<Object> ShareSlow(Isolate* isolate,
                                       Handle<HeapObject> value,
                                       ShouldThrow throw_if_cannot_be_shared);

773 774 775 776 777
 protected:
  inline Address field_address(size_t offset) const {
    return ptr() + offset - kHeapObjectTag;
  }

778
 private:
779 780
  friend class CompressedObjectSlot;
  friend class FullObjectSlot;
781
  friend class LookupIterator;
782
  friend class StringStream;
783 784

  // Return the map of the root of object's prototype chain.
785
  Map GetPrototypeChainRootMap(Isolate* isolate) const;
786

787 788 789 790 791 792 793
  // Returns a non-SMI for JSReceivers, but returns the hash code for
  // simple objects.  This avoids a double lookup in the cases where
  // we know we will add the hash to the JSReceiver if it does not
  // already exist.
  //
  // Despite its size, this needs to be inlined for performance
  // reasons.
794
  static inline Object GetSimpleHash(Object object);
795

arv's avatar
arv committed
796
  // Helper for SetProperty and SetSuperProperty.
797
  // Return value is only meaningful if [found] is set to true on return.
798
  V8_WARN_UNUSED_RESULT static Maybe<bool> SetPropertyInternal(
799
      LookupIterator* it, Handle<Object> value, Maybe<ShouldThrow> should_throw,
800
      StoreOrigin store_origin, bool* found);
arv's avatar
arv committed
801

802 803 804
  V8_WARN_UNUSED_RESULT static MaybeHandle<Name> ConvertToName(
      Isolate* isolate, Handle<Object> input);
  V8_WARN_UNUSED_RESULT static MaybeHandle<Object> ConvertToPropertyKey(
805
      Isolate* isolate, Handle<Object> value);
806 807
  V8_EXPORT_PRIVATE V8_WARN_UNUSED_RESULT static MaybeHandle<String>
  ConvertToString(Isolate* isolate, Handle<Object> input);
808
  V8_WARN_UNUSED_RESULT static MaybeHandle<Object> ConvertToNumberOrNumeric(
809
      Isolate* isolate, Handle<Object> input, Conversion mode);
810 811
  V8_EXPORT_PRIVATE V8_WARN_UNUSED_RESULT static MaybeHandle<Object>
  ConvertToInteger(Isolate* isolate, Handle<Object> input);
812
  V8_WARN_UNUSED_RESULT static MaybeHandle<Object> ConvertToInt32(
813
      Isolate* isolate, Handle<Object> input);
814
  V8_WARN_UNUSED_RESULT static MaybeHandle<Object> ConvertToUint32(
815
      Isolate* isolate, Handle<Object> input);
816 817 818 819 820
  V8_EXPORT_PRIVATE V8_WARN_UNUSED_RESULT static MaybeHandle<Object>
  ConvertToLength(Isolate* isolate, Handle<Object> input);
  V8_EXPORT_PRIVATE V8_WARN_UNUSED_RESULT static MaybeHandle<Object>
  ConvertToIndex(Isolate* isolate, Handle<Object> input,
                 MessageTemplate error_index);
821 822
};

823
V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os, const Object& obj);
824

825
struct Brief {
826 827
  template <typename TObject>
  explicit Brief(TObject v) : value{v.ptr()} {}
828 829 830 831
  // {value} is a tagged heap object reference (weak or strong), equivalent to
  // a MaybeObject's payload. It has a plain Address type to keep #includes
  // lightweight.
  const Address value;
832 833
};

834
V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os, const Brief& v);
835

836 837 838
// Objects should never have the weak tag; this variant is for overzealous
// checking.
V8_INLINE static bool HasWeakHeapObjectTag(const Object value) {
839
  return HAS_WEAK_HEAP_OBJECT_TAG(value.ptr());
840 841
}

842
// Heap objects typically have a map pointer in their first word.  However,
843
// during GC other data (e.g. mark bits, forwarding addresses) is sometimes
844 845
// encoded in the first word.  The class MapWord is an abstraction of the
// value in a heap object's first word.
846
class MapWord {
847 848 849 850
 public:
  // Normal state: the map word contains a map pointer.

  // Create a map word from a map pointer.
851
  static inline MapWord FromMap(const Map map);
852 853

  // View this map word as a map pointer.
854
  inline Map ToMap() const;
855 856 857 858 859 860

  // Scavenge collection: the map word of live objects in the from space
  // contains a forwarding address (a heap object pointer in the to space).

  // True if this map word is a forwarding address for a scavenge
  // collection.  Only valid during a scavenge collection (specifically,
861
  // when all map words are heap object pointers, i.e. not during a full GC).
862
  inline bool IsForwardingAddress() const;
863 864

  // Create a map word from a forwarding address.
865
  static inline MapWord FromForwardingAddress(HeapObject object);
866

867 868 869 870 871 872
  // View this map word as a forwarding address. The parameterless version
  // is allowed to be used for objects allocated in the main pointer compression
  // cage, while the second variant uses the value of the cage base explicitly
  // and thus can be used in situations where one has to deal with both cases.
  // Note, that the parameterless version is preferred because it avoids
  // unnecessary recompressions.
873
  inline HeapObject ToForwardingAddress();
874
  inline HeapObject ToForwardingAddress(PtrComprCageBase host_cage_base);
875

876
  inline Address ptr() { return value_; }
877

878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894
#ifdef V8_MAP_PACKING
  static constexpr Address Pack(Address map) {
    return map ^ Internals::kMapWordXorMask;
  }
  static constexpr Address Unpack(Address mapword) {
    // TODO(wenyuzhao): Clear header metadata.
    return mapword ^ Internals::kMapWordXorMask;
  }
  static constexpr bool IsPacked(Address mapword) {
    return (static_cast<intptr_t>(mapword) & Internals::kMapWordXorMask) ==
               Internals::kMapWordSignature &&
           (0xffffffff00000000 & static_cast<intptr_t>(mapword)) != 0;
  }
#else
  static constexpr bool IsPacked(Address) { return false; }
#endif

895 896 897
 private:
  // HeapObject calls the private constructor and directly reads the value.
  friend class HeapObject;
898 899
  template <typename TFieldType, int kFieldOffset>
  friend class TaggedField;
900

901
  explicit MapWord(Address value) : value_(value) {}
902

903
  Address value_;
904 905
};

906
template <int start_offset, int end_offset, int size>
907
class FixedBodyDescriptor;
908

909
template <int start_offset>
910
class FlexibleBodyDescriptor;
911

912 913 914
template <int start_offset>
class FlexibleWeakBodyDescriptor;

915 916 917
template <class ParentBodyDescriptor, class ChildBodyDescriptor>
class SubclassBodyDescriptor;

918 919 920 921 922 923
enum EnsureElementsMode {
  DONT_ALLOW_DOUBLE_ELEMENTS,
  ALLOW_COPIED_DOUBLE_ELEMENTS,
  ALLOW_CONVERTED_DOUBLE_ELEMENTS
};

924
// Indicator for one component of an AccessorPair.
925
enum AccessorComponent { ACCESSOR_GETTER, ACCESSOR_SETTER };
926

927 928 929
// Utility superclass for stack-allocated objects that must be updated
// on gc.  It provides two ways for the gc to update instances, either
// iterating or updating after gc.
930
class Relocatable {
sgjesse@chromium.org's avatar
sgjesse@chromium.org committed
931
 public:
932 933
  explicit inline Relocatable(Isolate* isolate);
  inline virtual ~Relocatable();
934
  virtual void IterateInstance(RootVisitor* v) {}
935
  virtual void PostGarbageCollection() {}
936

937
  static void PostGarbageCollectionProcessing(Isolate* isolate);
938
  static int ArchiveSpacePerThread();
939 940
  static char* ArchiveState(Isolate* isolate, char* to);
  static char* RestoreState(Isolate* isolate, char* from);
941 942 943
  static void Iterate(Isolate* isolate, RootVisitor* v);
  static void Iterate(RootVisitor* v, Relocatable* top);
  static char* Iterate(RootVisitor* v, char* t);
944

sgjesse@chromium.org's avatar
sgjesse@chromium.org committed
945
 private:
946
  Isolate* isolate_;
947 948 949
  Relocatable* prev_;
};

950
// BooleanBit is a helper class for setting and getting a bit in an integer.
951
class BooleanBit : public AllStatic {
952 953 954 955 956 957 958 959 960 961 962 963 964 965 966
 public:
  static inline bool get(int value, int bit_position) {
    return (value & (1 << bit_position)) != 0;
  }

  static inline int set(int value, int bit_position, bool v) {
    if (v) {
      value |= (1 << bit_position);
    } else {
      value &= ~(1 << bit_position);
    }
    return value;
  }
};

967 968
}  // namespace internal
}  // namespace v8
969

970 971
#include "src/objects/object-macros-undef.h"

972
#endif  // V8_OBJECTS_OBJECTS_H_