heap-refs.h 37.5 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12
// Copyright 2019 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef V8_COMPILER_HEAP_REFS_H_
#define V8_COMPILER_HEAP_REFS_H_

#include "src/base/optional.h"
#include "src/ic/call-optimization.h"
#include "src/objects/elements-kind.h"
#include "src/objects/feedback-vector.h"
#include "src/objects/instance-type.h"
13
#include "src/utils/boxed-float.h"
14 15

namespace v8 {
16

17 18
class CFunctionInfo;

19 20 21 22 23 24 25 26 27 28 29 30 31 32
namespace internal {

class BytecodeArray;
class CallHandlerInfo;
class FixedDoubleArray;
class FunctionTemplateInfo;
class HeapNumber;
class InternalizedString;
class JSBoundFunction;
class JSDataView;
class JSGlobalProxy;
class JSTypedArray;
class NativeContext;
class ScriptContextTable;
33 34 35 36 37 38 39
template <typename>
class Signature;

namespace wasm {
class ValueType;
struct WasmModule;
}  // namespace wasm
40 41

namespace compiler {
42

43 44 45
class CompilationDependencies;
struct FeedbackSource;
class JSHeapBroker;
46
class ObjectData;
47 48
class PerIsolateCompilerCache;
class PropertyAccessInfo;
49

50 51 52 53
// Whether we are loading a property or storing to a property.
// For a store during literal creation, do not walk up the prototype chain.
enum class AccessMode { kLoad, kStore, kStoreInLiteral, kHas };

54 55 56 57
inline bool IsAnyStore(AccessMode mode) {
  return mode == AccessMode::kStore || mode == AccessMode::kStoreInLiteral;
}

58 59
enum class SerializationPolicy { kAssumeSerialized, kSerializeIfNeeded };

60 61 62 63 64 65 66
// Clarifies in function signatures that a method may only be called when
// concurrent inlining is disabled.
class NotConcurrentInliningTag final {
 public:
  explicit NotConcurrentInliningTag(JSHeapBroker* broker);
};

67 68 69 70 71 72 73 74 75 76
enum class OddballType : uint8_t {
  kNone,     // Not an Oddball.
  kBoolean,  // True or False.
  kUndefined,
  kNull,
  kHole,
  kUninitialized,
  kOther  // Oddball, but none of the above.
};

77
enum class RefSerializationKind {
78
  // Skips serialization.
79 80 81 82
  kNeverSerialized,
  // Can be serialized on demand from the background thread.
  kBackgroundSerialized,
};
83

84 85
// This list is sorted such that subtypes appear before their supertypes.
// DO NOT VIOLATE THIS PROPERTY!
86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144
#define HEAP_BROKER_OBJECT_LIST_BASE(BACKGROUND_SERIALIZED, NEVER_SERIALIZED) \
  /* Subtypes of JSObject */                                                  \
  BACKGROUND_SERIALIZED(JSArray)                                              \
  BACKGROUND_SERIALIZED(JSBoundFunction)                                      \
  BACKGROUND_SERIALIZED(JSDataView)                                           \
  BACKGROUND_SERIALIZED(JSFunction)                                           \
  BACKGROUND_SERIALIZED(JSGlobalObject)                                       \
  BACKGROUND_SERIALIZED(JSGlobalProxy)                                        \
  BACKGROUND_SERIALIZED(JSTypedArray)                                         \
  /* Subtypes of Context */                                                   \
  NEVER_SERIALIZED(NativeContext)                                             \
  /* Subtypes of FixedArray */                                                \
  NEVER_SERIALIZED(ObjectBoilerplateDescription)                              \
  BACKGROUND_SERIALIZED(ScriptContextTable)                                   \
  /* Subtypes of String */                                                    \
  NEVER_SERIALIZED(InternalizedString)                                        \
  /* Subtypes of FixedArrayBase */                                            \
  NEVER_SERIALIZED(BytecodeArray)                                             \
  BACKGROUND_SERIALIZED(FixedArray)                                           \
  NEVER_SERIALIZED(FixedDoubleArray)                                          \
  /* Subtypes of Name */                                                      \
  NEVER_SERIALIZED(String)                                                    \
  NEVER_SERIALIZED(Symbol)                                                    \
  /* Subtypes of JSReceiver */                                                \
  BACKGROUND_SERIALIZED(JSObject)                                             \
  /* Subtypes of HeapObject */                                                \
  NEVER_SERIALIZED(AccessorInfo)                                              \
  NEVER_SERIALIZED(AllocationSite)                                            \
  NEVER_SERIALIZED(ArrayBoilerplateDescription)                               \
  BACKGROUND_SERIALIZED(BigInt)                                               \
  NEVER_SERIALIZED(CallHandlerInfo)                                           \
  NEVER_SERIALIZED(Cell)                                                      \
  NEVER_SERIALIZED(Code)                                                      \
  NEVER_SERIALIZED(CodeDataContainer)                                         \
  NEVER_SERIALIZED(Context)                                                   \
  NEVER_SERIALIZED(DescriptorArray)                                           \
  NEVER_SERIALIZED(FeedbackCell)                                              \
  NEVER_SERIALIZED(FeedbackVector)                                            \
  BACKGROUND_SERIALIZED(FixedArrayBase)                                       \
  NEVER_SERIALIZED(FunctionTemplateInfo)                                      \
  NEVER_SERIALIZED(HeapNumber)                                                \
  BACKGROUND_SERIALIZED(JSReceiver)                                           \
  BACKGROUND_SERIALIZED(Map)                                                  \
  NEVER_SERIALIZED(Name)                                                      \
  BACKGROUND_SERIALIZED(PropertyCell)                                         \
  NEVER_SERIALIZED(RegExpBoilerplateDescription)                              \
  NEVER_SERIALIZED(ScopeInfo)                                                 \
  NEVER_SERIALIZED(SharedFunctionInfo)                                        \
  NEVER_SERIALIZED(SourceTextModule)                                          \
  NEVER_SERIALIZED(TemplateObjectDescription)                                 \
  /* Subtypes of Object */                                                    \
  BACKGROUND_SERIALIZED(HeapObject)

#define HEAP_BROKER_OBJECT_LIST(V) HEAP_BROKER_OBJECT_LIST_BASE(V, V)
#define IGNORE_CASE(...)
#define HEAP_BROKER_BACKGROUND_SERIALIZED_OBJECT_LIST(V) \
  HEAP_BROKER_OBJECT_LIST_BASE(V, IGNORE_CASE)

#define FORWARD_DECL(Name) class Name##Ref;
145
HEAP_BROKER_OBJECT_LIST(FORWARD_DECL)
146 147
#undef FORWARD_DECL

148 149
class ObjectRef;

150 151 152
template <class T>
struct ref_traits;

153 154 155 156 157 158 159 160 161 162 163
#define FORWARD_DECL(Name) class Name##Data;
HEAP_BROKER_BACKGROUND_SERIALIZED_OBJECT_LIST(FORWARD_DECL)
#undef FORWARD_DECL

#define BACKGROUND_SERIALIZED_REF_TRAITS(Name)                     \
  template <>                                                      \
  struct ref_traits<Name> {                                        \
    using ref_type = Name##Ref;                                    \
    using data_type = Name##Data;                                  \
    static constexpr RefSerializationKind ref_serialization_kind = \
        RefSerializationKind::kBackgroundSerialized;               \
164
  };
165 166 167 168 169 170 171 172 173 174 175 176 177 178

#define NEVER_SERIALIZED_REF_TRAITS(Name)                          \
  template <>                                                      \
  struct ref_traits<Name> {                                        \
    using ref_type = Name##Ref;                                    \
    using data_type = ObjectData;                                  \
    static constexpr RefSerializationKind ref_serialization_kind = \
        RefSerializationKind::kNeverSerialized;                    \
  };

HEAP_BROKER_OBJECT_LIST_BASE(BACKGROUND_SERIALIZED_REF_TRAITS,
                             NEVER_SERIALIZED_REF_TRAITS)
#undef NEVER_SERIALIZED_REF_TRAITS
#undef BACKGROUND_SERIALIZED_REF_TRAITS
179

180 181 182 183 184 185 186 187 188 189
template <>
struct ref_traits<Object> {
  using ref_type = ObjectRef;
  // Note: While a bit awkward, this artificial ref serialization kind value is
  // okay: smis are never-serialized, and we never create raw non-smi
  // ObjectRefs (they would at least be HeapObjectRefs instead).
  static constexpr RefSerializationKind ref_serialization_kind =
      RefSerializationKind::kNeverSerialized;
};

190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214
// A ref without the broker_ field, used when storage size is important.
template <class T>
class TinyRef {
 private:
  using RefType = typename ref_traits<T>::ref_type;

 public:
  explicit TinyRef(const RefType& ref) : TinyRef(ref.data_) {}
  RefType AsRef(JSHeapBroker* broker) const;
  static base::Optional<RefType> AsOptionalRef(JSHeapBroker* broker,
                                               base::Optional<TinyRef<T>> ref) {
    if (!ref.has_value()) return {};
    return ref->AsRef(broker);
  }
  Handle<T> object() const;

 private:
  explicit TinyRef(ObjectData* data) : data_(data) { DCHECK_NOT_NULL(data); }
  ObjectData* const data_;
};

#define V(Name) using Name##TinyRef = TinyRef<Name>;
HEAP_BROKER_OBJECT_LIST(V)
#undef V

215 216 217 218 219 220 221 222
#ifdef V8_EXTERNAL_CODE_SPACE
using CodeTRef = CodeDataContainerRef;
using CodeTTinyRef = CodeDataContainerTinyRef;
#else
using CodeTRef = CodeRef;
using CodeTTinyRef = CodeTinyRef;
#endif

223 224
class V8_EXPORT_PRIVATE ObjectRef {
 public:
225
  ObjectRef(JSHeapBroker* broker, ObjectData* data, bool check_type = true)
226 227 228
      : data_(data), broker_(broker) {
    CHECK_NOT_NULL(data_);
  }
229

230 231 232 233 234 235 236
  Handle<Object> object() const;

  bool equals(const ObjectRef& other) const;

  bool IsSmi() const;
  int AsSmi() const;

237
#define HEAP_IS_METHOD_DECL(Name) bool Is##Name() const;
238
  HEAP_BROKER_OBJECT_LIST(HEAP_IS_METHOD_DECL)
239 240
#undef HEAP_IS_METHOD_DECL

241
#define HEAP_AS_METHOD_DECL(Name) Name##Ref As##Name() const;
242
  HEAP_BROKER_OBJECT_LIST(HEAP_AS_METHOD_DECL)
243 244
#undef HEAP_AS_METHOD_DECL

245
  bool IsNull() const;
246
  bool IsNullOrUndefined() const;
247
  bool IsTheHole() const;
248

249
  base::Optional<bool> TryGetBooleanValue() const;
250 251
  Maybe<double> OddballToNumber() const;

252 253
  bool should_access_heap() const;

254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274
  Isolate* isolate() const;

  struct Hash {
    size_t operator()(const ObjectRef& ref) const {
      return base::hash_combine(ref.object().address());
    }
  };
  struct Equal {
    bool operator()(const ObjectRef& lhs, const ObjectRef& rhs) const {
      return lhs.equals(rhs);
    }
  };

 protected:
  JSHeapBroker* broker() const;
  ObjectData* data() const;
  ObjectData* data_;  // Should be used only by object() getters.

 private:
  friend class FunctionTemplateInfoRef;
  friend class JSArrayData;
275 276
  friend class JSGlobalObjectData;
  friend class JSGlobalObjectRef;
277
  friend class JSHeapBroker;
278 279
  friend class JSObjectData;
  friend class StringData;
280 281
  template <class T>
  friend class TinyRef;
282 283 284 285 286 287

  friend std::ostream& operator<<(std::ostream& os, const ObjectRef& ref);

  JSHeapBroker* broker_;
};

288 289 290 291
template <class T>
using ZoneRefUnorderedSet =
    ZoneUnorderedSet<T, ObjectRef::Hash, ObjectRef::Equal>;

292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326
// Temporary class that carries information from a Map. We'd like to remove
// this class and use MapRef instead, but we can't as long as we support the
// kDisabled broker mode. That's because obtaining the MapRef via
// HeapObjectRef::map() requires a HandleScope when the broker is disabled.
// During OptimizeGraph we generally don't have a HandleScope, however. There
// are two places where we therefore use GetHeapObjectType() instead. Both that
// function and this class should eventually be removed.
class HeapObjectType {
 public:
  enum Flag : uint8_t { kUndetectable = 1 << 0, kCallable = 1 << 1 };

  using Flags = base::Flags<Flag>;

  HeapObjectType(InstanceType instance_type, Flags flags,
                 OddballType oddball_type)
      : instance_type_(instance_type),
        oddball_type_(oddball_type),
        flags_(flags) {
    DCHECK_EQ(instance_type == ODDBALL_TYPE,
              oddball_type != OddballType::kNone);
  }

  OddballType oddball_type() const { return oddball_type_; }
  InstanceType instance_type() const { return instance_type_; }
  Flags flags() const { return flags_; }

  bool is_callable() const { return flags_ & kCallable; }
  bool is_undetectable() const { return flags_ & kUndetectable; }

 private:
  InstanceType const instance_type_;
  OddballType const oddball_type_;
  Flags const flags_;
};

327 328
// Constructors are carefully defined such that we do a type check on
// the outermost Ref class in the inheritance chain only.
329 330 331
#define DEFINE_REF_CONSTRUCTOR(Name, Base)                                  \
  Name##Ref(JSHeapBroker* broker, ObjectData* data, bool check_type = true) \
      : Base(broker, data, false) {                                         \
332
    if (check_type) {                                                       \
333
      CHECK(Is##Name());                                                    \
334 335 336
    }                                                                       \
  }

337 338
class HeapObjectRef : public ObjectRef {
 public:
339
  DEFINE_REF_CONSTRUCTOR(HeapObject, ObjectRef)
340

341 342 343 344
  Handle<HeapObject> object() const;

  MapRef map() const;

345 346 347 348
  // Only for use in special situations where we need to read the object's
  // current map (instead of returning the cached map). Use with care.
  base::Optional<MapRef> map_direct_read() const;

349 350 351 352 353 354
  // See the comment on the HeapObjectType class.
  HeapObjectType GetHeapObjectType() const;
};

class PropertyCellRef : public HeapObjectRef {
 public:
355
  DEFINE_REF_CONSTRUCTOR(PropertyCell, HeapObjectRef)
356

357 358
  Handle<PropertyCell> object() const;

359 360 361
  V8_WARN_UNUSED_RESULT bool Cache() const;
  void CacheAsProtector() const {
    bool cached = Cache();
362
    // A protector always holds a Smi value and its cell type never changes, so
363 364
    // Cache can't fail.
    CHECK(cached);
365
  }
366

367
  PropertyDetails property_details() const;
368 369 370
  ObjectRef value() const;
};

371
class JSReceiverRef : public HeapObjectRef {
372
 public:
373
  DEFINE_REF_CONSTRUCTOR(JSReceiver, HeapObjectRef)
374

375 376 377 378 379
  Handle<JSReceiver> object() const;
};

class JSObjectRef : public JSReceiverRef {
 public:
380
  DEFINE_REF_CONSTRUCTOR(JSObject, JSReceiverRef)
381

382 383
  Handle<JSObject> object() const;

384 385
  base::Optional<ObjectRef> raw_properties_or_hash() const;

386 387 388 389
  // Usable only for in-object properties. Only use this if the underlying
  // value can be an uninitialized-sentinel, or if HeapNumber construction must
  // be avoided for some reason. Otherwise, use the higher-level
  // GetOwnFastDataProperty.
390
  base::Optional<ObjectRef> RawInobjectPropertyAt(FieldIndex index) const;
391

392
  // Return the element at key {index} if {index} is known to be an own data
393 394 395
  // property of the object that is non-writable and non-configurable. If
  // {dependencies} is non-null, a dependency will be taken to protect
  // against inconsistency due to weak memory concurrency.
396
  base::Optional<ObjectRef> GetOwnConstantElement(
397
      const FixedArrayBaseRef& elements_ref, uint32_t index,
398
      CompilationDependencies* dependencies,
399 400 401 402 403 404 405 406
      SerializationPolicy policy =
          SerializationPolicy::kAssumeSerialized) const;
  // The direct-read implementation of the above, extracted into a helper since
  // it's also called from compilation-dependency validation. This helper is
  // guaranteed to not create new Ref instances.
  base::Optional<Object> GetOwnConstantElementFromHeap(
      FixedArrayBase elements, ElementsKind elements_kind,
      uint32_t index) const;
407

408 409
  // Return the value of the property identified by the field {index}
  // if {index} is known to be an own data property of the object.
410 411 412
  // If {dependencies} is non-null, and a property was successfully read,
  // then the function will take a dependency to check the value of the
  // property at code finalization time.
413
  base::Optional<ObjectRef> GetOwnFastDataProperty(
414
      Representation field_representation, FieldIndex index,
415
      CompilationDependencies* dependencies,
416 417
      SerializationPolicy policy =
          SerializationPolicy::kAssumeSerialized) const;
418 419 420

  // Return the value of the dictionary property at {index} in the dictionary
  // if {index} is known to be an own data property of the object.
421 422 423 424
  base::Optional<ObjectRef> GetOwnDictionaryProperty(
      InternalIndex index, CompilationDependencies* dependencies,
      SerializationPolicy policy =
          SerializationPolicy::kAssumeSerialized) const;
425

426 427 428 429
  // When concurrent inlining is enabled, reads the elements through a direct
  // relaxed read. This is to ease the transition to unserialized (or
  // background-serialized) elements.
  base::Optional<FixedArrayBaseRef> elements(RelaxedLoadTag) const;
430
  void SerializeElements(NotConcurrentInliningTag tag);
431
  bool IsElementsTenured(const FixedArrayBaseRef& elements);
432

433
  void SerializeObjectCreateMap(NotConcurrentInliningTag tag);
434
  base::Optional<MapRef> GetObjectCreateMap() const;
435

436
  void SerializeAsBoilerplateRecursive(NotConcurrentInliningTag tag);
437 438 439 440
};

class JSDataViewRef : public JSObjectRef {
 public:
441
  DEFINE_REF_CONSTRUCTOR(JSDataView, JSObjectRef)
442

443 444 445 446 447 448 449
  Handle<JSDataView> object() const;

  size_t byte_length() const;
};

class JSBoundFunctionRef : public JSObjectRef {
 public:
450
  DEFINE_REF_CONSTRUCTOR(JSBoundFunction, JSObjectRef)
451

452 453
  Handle<JSBoundFunction> object() const;

454
  bool Serialize(NotConcurrentInliningTag tag);
455

456 457 458 459
  // TODO(neis): Make return types non-optional once JSFunction is no longer
  // fg-serialized.
  base::Optional<JSReceiverRef> bound_target_function() const;
  base::Optional<ObjectRef> bound_this() const;
460 461 462 463 464
  FixedArrayRef bound_arguments() const;
};

class V8_EXPORT_PRIVATE JSFunctionRef : public JSObjectRef {
 public:
465
  DEFINE_REF_CONSTRUCTOR(JSFunction, JSObjectRef)
466

467 468
  Handle<JSFunction> object() const;

469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491
  // Returns true, iff the serialized JSFunctionData contents are consistent
  // with the state of the underlying JSFunction object. Must be called from
  // the main thread.
  bool IsConsistentWithHeapState() const;

  // TODO(jgruber): Consider more fine-grained dependencies that keep track of
  // which fields were actually inspected during compilation.
  bool has_feedback_vector(CompilationDependencies* dependencies) const;
  bool has_initial_map(CompilationDependencies* dependencies) const;
  bool PrototypeRequiresRuntimeLookup(
      CompilationDependencies* dependencies) const;
  bool has_instance_prototype(CompilationDependencies* dependencies) const;
  ObjectRef instance_prototype(CompilationDependencies* dependencies) const;
  MapRef initial_map(CompilationDependencies* dependencies) const;
  ContextRef context(CompilationDependencies* dependencies) const;
  NativeContextRef native_context(CompilationDependencies* dependencies) const;
  SharedFunctionInfoRef shared(CompilationDependencies* dependencies) const;
  int InitialMapInstanceSizeWithMinSlack(
      CompilationDependencies* dependencies) const;
  FeedbackVectorRef feedback_vector(
      CompilationDependencies* dependencies) const;
  FeedbackCellRef raw_feedback_cell(
      CompilationDependencies* dependencies) const;
492

493
  CodeRef code() const;
494 495 496

 private:
  void RecordDependencyIfNeeded(CompilationDependencies* dependencies) const;
497 498
};

499
class RegExpBoilerplateDescriptionRef : public HeapObjectRef {
500
 public:
501
  DEFINE_REF_CONSTRUCTOR(RegExpBoilerplateDescription, HeapObjectRef)
502

503
  Handle<RegExpBoilerplateDescription> object() const;
504

505
  void Serialize(NotConcurrentInliningTag tag);
506

507 508 509
  FixedArrayRef data() const;
  StringRef source() const;
  int flags() const;
510 511
};

512 513 514 515 516
// HeapNumberRef is only created for immutable HeapNumbers. Mutable
// HeapNumbers (those owned by in-object or backing store fields with
// representation type Double are not exposed to the compiler through
// HeapNumberRef. Instead, we read their value, and protect that read
// with a field-constness Dependency.
517 518
class HeapNumberRef : public HeapObjectRef {
 public:
519
  DEFINE_REF_CONSTRUCTOR(HeapNumber, HeapObjectRef)
520

521 522 523
  Handle<HeapNumber> object() const;

  double value() const;
524
  uint64_t value_as_bits() const;
525 526 527 528
};

class ContextRef : public HeapObjectRef {
 public:
529
  DEFINE_REF_CONSTRUCTOR(Context, HeapObjectRef)
530

531 532
  Handle<Context> object() const;

533
  // {previous} decrements {depth} by 1 for each previous link successfully
534
  // followed. If {depth} != 0 on function return, then it only got partway to
535 536
  // the desired depth.
  ContextRef previous(size_t* depth) const;
537 538

  // Only returns a value if the index is valid for this ContextRef.
539
  base::Optional<ObjectRef> get(int index) const;
540 541
};

542 543 544
// TODO(jgruber): Don't serialize NativeContext fields once all refs can be
// created concurrently.

545 546 547 548 549 550 551 552 553 554 555 556 557 558 559
#define BROKER_NATIVE_CONTEXT_FIELDS(V)          \
  V(JSFunction, array_function)                  \
  V(JSFunction, bigint_function)                 \
  V(JSFunction, boolean_function)                \
  V(JSFunction, function_prototype_apply)        \
  V(JSFunction, number_function)                 \
  V(JSFunction, object_function)                 \
  V(JSFunction, promise_function)                \
  V(JSFunction, promise_then)                    \
  V(JSFunction, regexp_exec_function)            \
  V(JSFunction, regexp_function)                 \
  V(JSFunction, string_function)                 \
  V(JSFunction, symbol_function)                 \
  V(JSGlobalObject, global_object)               \
  V(JSGlobalProxy, global_proxy_object)          \
560
  V(JSObject, initial_array_prototype)           \
561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587
  V(JSObject, promise_prototype)                 \
  V(Map, async_function_object_map)              \
  V(Map, block_context_map)                      \
  V(Map, bound_function_with_constructor_map)    \
  V(Map, bound_function_without_constructor_map) \
  V(Map, catch_context_map)                      \
  V(Map, eval_context_map)                       \
  V(Map, fast_aliased_arguments_map)             \
  V(Map, function_context_map)                   \
  V(Map, initial_array_iterator_map)             \
  V(Map, initial_string_iterator_map)            \
  V(Map, iterator_result_map)                    \
  V(Map, js_array_holey_double_elements_map)     \
  V(Map, js_array_holey_elements_map)            \
  V(Map, js_array_holey_smi_elements_map)        \
  V(Map, js_array_packed_double_elements_map)    \
  V(Map, js_array_packed_elements_map)           \
  V(Map, js_array_packed_smi_elements_map)       \
  V(Map, map_key_iterator_map)                   \
  V(Map, map_key_value_iterator_map)             \
  V(Map, map_value_iterator_map)                 \
  V(Map, set_key_value_iterator_map)             \
  V(Map, set_value_iterator_map)                 \
  V(Map, sloppy_arguments_map)                   \
  V(Map, slow_object_with_null_prototype_map)    \
  V(Map, strict_arguments_map)                   \
  V(Map, with_context_map)                       \
588
  V(ScriptContextTable, script_context_table)
589 590 591

class NativeContextRef : public ContextRef {
 public:
592
  DEFINE_REF_CONSTRUCTOR(NativeContext, ContextRef)
593

594 595
  Handle<NativeContext> object() const;

596
  void Serialize(NotConcurrentInliningTag tag);
597 598 599 600 601 602 603 604 605

#define DECL_ACCESSOR(type, name) type##Ref name() const;
  BROKER_NATIVE_CONTEXT_FIELDS(DECL_ACCESSOR)
#undef DECL_ACCESSOR

  ScopeInfoRef scope_info() const;
  MapRef GetFunctionMapFromIndex(int index) const;
  MapRef GetInitialJSArrayMap(ElementsKind kind) const;
  base::Optional<JSFunctionRef> GetConstructorFunction(const MapRef& map) const;
606
  bool GlobalIsDetached() const;
607 608 609 610
};

class NameRef : public HeapObjectRef {
 public:
611
  DEFINE_REF_CONSTRUCTOR(Name, HeapObjectRef)
612

613 614 615 616 617 618 619
  Handle<Name> object() const;

  bool IsUniqueName() const;
};

class DescriptorArrayRef : public HeapObjectRef {
 public:
620
  DEFINE_REF_CONSTRUCTOR(DescriptorArray, HeapObjectRef)
621

622
  Handle<DescriptorArray> object() const;
623 624

  PropertyDetails GetPropertyDetails(InternalIndex descriptor_index) const;
625
  NameRef GetPropertyKey(InternalIndex descriptor_index) const;
626
  ObjectRef GetFieldType(InternalIndex descriptor_index) const;
627 628
  base::Optional<ObjectRef> GetStrongValue(
      InternalIndex descriptor_index) const;
629 630 631 632
};

class FeedbackCellRef : public HeapObjectRef {
 public:
633
  DEFINE_REF_CONSTRUCTOR(FeedbackCell, HeapObjectRef)
634

635
  Handle<FeedbackCell> object() const;
636
  base::Optional<SharedFunctionInfoRef> shared_function_info() const;
637 638 639 640 641

  // TODO(mvstanton): Once we allow inlining of functions we didn't see
  // during serialization, we do need to ensure that any feedback vector
  // we read here has been fully initialized (ie, store-ordered into the
  // cell).
642
  base::Optional<FeedbackVectorRef> value() const;
643 644 645 646
};

class FeedbackVectorRef : public HeapObjectRef {
 public:
647
  DEFINE_REF_CONSTRUCTOR(FeedbackVector, HeapObjectRef)
648

649 650
  Handle<FeedbackVector> object() const;

651
  SharedFunctionInfoRef shared_function_info() const;
652

653
  FeedbackCellRef GetClosureFeedbackCell(int index) const;
654 655 656 657
};

class CallHandlerInfoRef : public HeapObjectRef {
 public:
658
  DEFINE_REF_CONSTRUCTOR(CallHandlerInfo, HeapObjectRef)
659

660 661 662 663 664 665
  Handle<CallHandlerInfo> object() const;

  Address callback() const;
  ObjectRef data() const;
};

666 667
class AccessorInfoRef : public HeapObjectRef {
 public:
668
  DEFINE_REF_CONSTRUCTOR(AccessorInfo, HeapObjectRef)
669

670 671 672
  Handle<AccessorInfo> object() const;
};

673 674
class AllocationSiteRef : public HeapObjectRef {
 public:
675
  DEFINE_REF_CONSTRUCTOR(AllocationSite, HeapObjectRef)
676

677 678 679 680 681 682
  Handle<AllocationSite> object() const;

  bool PointsToLiteral() const;
  AllocationType GetAllocationType() const;
  ObjectRef nested_site() const;

683
  void SerializeRecursive(NotConcurrentInliningTag tag);
684

685 686 687 688 689
  base::Optional<JSObjectRef> boilerplate() const;
  ElementsKind GetElementsKind() const;
  bool CanInlineCall() const;
};

690 691
class BigIntRef : public HeapObjectRef {
 public:
692
  DEFINE_REF_CONSTRUCTOR(BigInt, HeapObjectRef)
693

694 695 696 697 698
  Handle<BigInt> object() const;

  uint64_t AsUint64() const;
};

699 700
class V8_EXPORT_PRIVATE MapRef : public HeapObjectRef {
 public:
701
  DEFINE_REF_CONSTRUCTOR(Map, HeapObjectRef)
702

703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731
  Handle<Map> object() const;

  int instance_size() const;
  InstanceType instance_type() const;
  int GetInObjectProperties() const;
  int GetInObjectPropertiesStartInWords() const;
  int NumberOfOwnDescriptors() const;
  int GetInObjectPropertyOffset(int index) const;
  int constructor_function_index() const;
  int NextFreePropertyIndex() const;
  int UnusedPropertyFields() const;
  ElementsKind elements_kind() const;
  bool is_stable() const;
  bool is_constructor() const;
  bool has_prototype_slot() const;
  bool is_access_check_needed() const;
  bool is_deprecated() const;
  bool CanBeDeprecated() const;
  bool CanTransition() const;
  bool IsInobjectSlackTrackingInProgress() const;
  bool is_dictionary_map() const;
  bool IsFixedCowArrayMap() const;
  bool IsPrimitiveMap() const;
  bool is_undetectable() const;
  bool is_callable() const;
  bool has_indexed_interceptor() const;
  bool is_migration_target() const;
  bool supports_fast_array_iteration() const;
  bool supports_fast_array_resize() const;
732
  bool is_abandoned_prototype_map() const;
733 734 735

  OddballType oddball_type() const;

736 737
  bool CanInlineElementAccess() const;

738 739 740 741
  // Note: Only returns a value if the requested elements kind matches the
  // current kind, or if the current map is an unmodified JSArray initial map.
  base::Optional<MapRef> AsElementsKind(ElementsKind kind) const;

742 743 744 745
#define DEF_TESTER(Type, ...) bool Is##Type##Map() const;
  INSTANCE_TYPE_CHECKERS(DEF_TESTER)
#undef DEF_TESTER

746
  void SerializeBackPointer(NotConcurrentInliningTag tag);
747 748
  HeapObjectRef GetBackPointer() const;

749
  void SerializePrototype(NotConcurrentInliningTag tag);
750 751 752
  // TODO(neis): We should be able to remove TrySerializePrototype once
  // concurrent-inlining is always on. Then we can also change the return type
  // of prototype() back to HeapObjectRef.
753
  bool TrySerializePrototype(NotConcurrentInliningTag tag);
754
  base::Optional<HeapObjectRef> prototype() const;
755

756
  void SerializeForElementStore(NotConcurrentInliningTag tag);
757 758 759 760
  bool HasOnlyStablePrototypesWithFastElements(
      ZoneVector<MapRef>* prototype_maps);

  // Concerning the underlying instance_descriptors:
761 762 763 764 765
  MapRef FindFieldOwner(InternalIndex descriptor_index) const;
  PropertyDetails GetPropertyDetails(InternalIndex descriptor_index) const;
  NameRef GetPropertyKey(InternalIndex descriptor_index) const;
  FieldIndex GetFieldIndexFor(InternalIndex descriptor_index) const;
  ObjectRef GetFieldType(InternalIndex descriptor_index) const;
766 767
  base::Optional<ObjectRef> GetStrongValue(
      InternalIndex descriptor_number) const;
768

769 770
  DescriptorArrayRef instance_descriptors() const;

771
  void SerializeRootMap(NotConcurrentInliningTag tag);
772 773
  base::Optional<MapRef> FindRootMap() const;

774 775 776 777 778 779 780 781 782 783 784 785 786 787
  ObjectRef GetConstructor() const;
};

struct HolderLookupResult {
  HolderLookupResult(CallOptimization::HolderLookup lookup_ =
                         CallOptimization::kHolderNotFound,
                     base::Optional<JSObjectRef> holder_ = base::nullopt)
      : lookup(lookup_), holder(holder_) {}
  CallOptimization::HolderLookup lookup;
  base::Optional<JSObjectRef> holder;
};

class FunctionTemplateInfoRef : public HeapObjectRef {
 public:
788
  DEFINE_REF_CONSTRUCTOR(FunctionTemplateInfo, HeapObjectRef)
789

790 791 792 793 794 795 796
  Handle<FunctionTemplateInfo> object() const;

  bool is_signature_undefined() const;
  bool accept_any_receiver() const;
  // The following returns true if the CallHandlerInfo is present.
  bool has_call_code() const;

797
  void SerializeCallCode(NotConcurrentInliningTag tag);
798
  base::Optional<CallHandlerInfoRef> call_code() const;
799 800
  ZoneVector<Address> c_functions() const;
  ZoneVector<const CFunctionInfo*> c_signatures() const;
801

802 803 804
  HolderLookupResult LookupHolderOfExpectedType(
      MapRef receiver_map,
      SerializationPolicy policy = SerializationPolicy::kAssumeSerialized);
805 806 807 808
};

class FixedArrayBaseRef : public HeapObjectRef {
 public:
809
  DEFINE_REF_CONSTRUCTOR(FixedArrayBase, HeapObjectRef)
810

811 812 813 814 815
  Handle<FixedArrayBase> object() const;

  int length() const;
};

816 817 818 819 820 821 822 823
class ArrayBoilerplateDescriptionRef : public HeapObjectRef {
 public:
  using HeapObjectRef::HeapObjectRef;
  Handle<ArrayBoilerplateDescription> object() const;

  int constants_elements_length() const;
};

824 825
class FixedArrayRef : public FixedArrayBaseRef {
 public:
826
  DEFINE_REF_CONSTRUCTOR(FixedArray, FixedArrayBaseRef)
827

828 829 830
  Handle<FixedArray> object() const;

  ObjectRef get(int i) const;
831 832 833 834 835 836

  // As above but may fail if Ref construction is not possible (e.g. for
  // serialized types on the background thread).
  // TODO(jgruber): Remove once all Ref types are never-serialized or
  // background-serialized and can thus be created on background threads.
  base::Optional<ObjectRef> TryGet(int i) const;
837 838 839 840
};

class FixedDoubleArrayRef : public FixedArrayBaseRef {
 public:
841
  DEFINE_REF_CONSTRUCTOR(FixedDoubleArray, FixedArrayBaseRef)
842

843 844
  Handle<FixedDoubleArray> object() const;

845 846 847 848
  // Due to 64-bit unaligned reads, only usable for
  // immutable-after-initialization FixedDoubleArrays protected by
  // acquire-release semantics (such as boilerplate elements).
  Float64 GetFromImmutableFixedDoubleArray(int i) const;
849 850 851 852
};

class BytecodeArrayRef : public FixedArrayBaseRef {
 public:
853
  DEFINE_REF_CONSTRUCTOR(BytecodeArray, FixedArrayBaseRef)
854

855 856
  Handle<BytecodeArray> object() const;

857 858
  // NOTE: Concurrent reads of the actual bytecodes as well as the constant pool
  // (both immutable) do not go through BytecodeArrayRef but are performed
859
  // directly through the handle by BytecodeArrayIterator.
860

861 862 863 864
  int register_count() const;
  int parameter_count() const;
  interpreter::Register incoming_new_target_or_generator_register() const;

865
  Handle<ByteArray> SourcePositionTable() const;
866

867 868 869
  // Exception handler table.
  Address handler_table_address() const;
  int handler_table_size() const;
870 871
};

872 873
class ScriptContextTableRef : public FixedArrayRef {
 public:
874
  DEFINE_REF_CONSTRUCTOR(ScriptContextTable, FixedArrayRef)
875 876 877 878 879 880

  Handle<ScriptContextTable> object() const;
};

class ObjectBoilerplateDescriptionRef : public FixedArrayRef {
 public:
881
  DEFINE_REF_CONSTRUCTOR(ObjectBoilerplateDescription, FixedArrayRef)
882 883 884 885 886 887

  Handle<ObjectBoilerplateDescription> object() const;

  int size() const;
};

888 889
class JSArrayRef : public JSObjectRef {
 public:
890
  DEFINE_REF_CONSTRUCTOR(JSArray, JSObjectRef)
891

892 893
  Handle<JSArray> object() const;

894 895 896 897
  // The `length` property of boilerplate JSArray objects. Boilerplates are
  // immutable after initialization. Must not be used for non-boilerplate
  // JSArrays.
  ObjectRef GetBoilerplateLength() const;
898 899 900

  // Return the element at key {index} if the array has a copy-on-write elements
  // storage and {index} is known to be an own data property.
901 902
  // Note the value returned by this function is only valid if we ensure at
  // runtime that the backing store has not changed.
903
  base::Optional<ObjectRef> GetOwnCowElement(
904 905 906 907 908 909 910 911
      FixedArrayBaseRef elements_ref, uint32_t index,
      SerializationPolicy policy =
          SerializationPolicy::kAssumeSerialized) const;

  // The `JSArray::length` property; not safe to use in general, but can be
  // used in some special cases that guarantee a valid `length` value despite
  // concurrent reads.
  ObjectRef length_unsafe() const;
912 913 914 915
};

class ScopeInfoRef : public HeapObjectRef {
 public:
916
  DEFINE_REF_CONSTRUCTOR(ScopeInfo, HeapObjectRef)
917

918 919 920
  Handle<ScopeInfo> object() const;

  int ContextLength() const;
921
  bool HasOuterScopeInfo() const;
922
  bool HasContextExtensionSlot() const;
923 924

  ScopeInfoRef OuterScopeInfo() const;
925 926
};

927 928
#define BROKER_SFI_FIELDS(V)                       \
  V(int, internal_formal_parameter_count)          \
929
  V(bool, has_simple_parameters)                   \
930 931 932 933 934 935 936 937 938 939 940 941 942 943
  V(bool, has_duplicate_parameters)                \
  V(int, function_map_index)                       \
  V(FunctionKind, kind)                            \
  V(LanguageMode, language_mode)                   \
  V(bool, native)                                  \
  V(bool, HasBreakInfo)                            \
  V(bool, HasBuiltinId)                            \
  V(bool, construct_as_builtin)                    \
  V(bool, HasBytecodeArray)                        \
  V(int, StartPosition)                            \
  V(bool, is_compiled)                             \
  V(bool, IsUserJavaScript)                        \
  IF_WASM(V, const wasm::WasmModule*, wasm_module) \
  IF_WASM(V, const wasm::FunctionSig*, wasm_function_signature)
944 945 946

class V8_EXPORT_PRIVATE SharedFunctionInfoRef : public HeapObjectRef {
 public:
947
  DEFINE_REF_CONSTRUCTOR(SharedFunctionInfo, HeapObjectRef)
948

949 950
  Handle<SharedFunctionInfo> object() const;

951
  Builtin builtin_id() const;
952
  int context_header_size() const;
953
  BytecodeArrayRef GetBytecodeArray() const;
954
  SharedFunctionInfo::Inlineability GetInlineability() const;
955 956
  base::Optional<FunctionTemplateInfoRef> function_template_info() const;
  ScopeInfoRef scope_info() const;
957 958 959 960 961

#define DECL_ACCESSOR(type, name) type name() const;
  BROKER_SFI_FIELDS(DECL_ACCESSOR)
#undef DECL_ACCESSOR

962 963 964
  bool IsInlineable() const {
    return GetInlineability() == SharedFunctionInfo::kIsInlineable;
  }
965 966 967 968
};

class StringRef : public NameRef {
 public:
969
  DEFINE_REF_CONSTRUCTOR(String, NameRef)
970

971 972
  Handle<String> object() const;

973 974
  // With concurrent inlining on, we return base::nullopt due to not being able
  // to use LookupIterator in a thread-safe way.
975
  base::Optional<ObjectRef> GetCharAsStringOrUndefined(
976 977 978
      uint32_t index, SerializationPolicy policy =
                          SerializationPolicy::kAssumeSerialized) const;

979 980
  // When concurrently accessing non-read-only non-supported strings, we return
  // base::nullopt for these methods.
981
  base::Optional<int> length() const;
982
  base::Optional<uint16_t> GetFirstChar();
983
  base::Optional<double> ToNumber();
984

985 986
  bool IsSeqString() const;
  bool IsExternalString() const;
987 988 989 990 991 992

 private:
  // With concurrent inlining on, we currently support reading directly
  // internalized strings, and thin strings (which are pointers to internalized
  // strings).
  bool SupportedStringKind() const;
993 994 995 996
};

class SymbolRef : public NameRef {
 public:
997
  DEFINE_REF_CONSTRUCTOR(Symbol, NameRef)
998

999 1000 1001 1002 1003
  Handle<Symbol> object() const;
};

class JSTypedArrayRef : public JSObjectRef {
 public:
1004
  DEFINE_REF_CONSTRUCTOR(JSTypedArray, JSObjectRef)
1005

1006 1007 1008 1009
  Handle<JSTypedArray> object() const;

  bool is_on_heap() const;
  size_t length() const;
1010
  void* data_ptr() const;
1011

1012
  void Serialize(NotConcurrentInliningTag tag);
1013 1014 1015 1016 1017 1018 1019
  bool serialized() const;

  HeapObjectRef buffer() const;
};

class SourceTextModuleRef : public HeapObjectRef {
 public:
1020
  DEFINE_REF_CONSTRUCTOR(SourceTextModule, HeapObjectRef)
1021

1022 1023
  Handle<SourceTextModule> object() const;

1024
  base::Optional<CellRef> GetCell(int cell_index) const;
1025
  base::Optional<ObjectRef> import_meta() const;
1026 1027
};

1028 1029
class TemplateObjectDescriptionRef : public HeapObjectRef {
 public:
1030
  DEFINE_REF_CONSTRUCTOR(TemplateObjectDescription, HeapObjectRef)
1031 1032 1033 1034

  Handle<TemplateObjectDescription> object() const;
};

1035 1036
class CellRef : public HeapObjectRef {
 public:
1037
  DEFINE_REF_CONSTRUCTOR(Cell, HeapObjectRef)
1038

1039 1040 1041
  Handle<Cell> object() const;
};

1042 1043
class JSGlobalObjectRef : public JSObjectRef {
 public:
1044
  DEFINE_REF_CONSTRUCTOR(JSGlobalObject, JSObjectRef)
1045 1046

  Handle<JSGlobalObject> object() const;
1047

1048
  bool IsDetachedFrom(JSGlobalProxyRef const& proxy) const;
1049

1050
  // Can be called even when there is no property cell for the given name.
1051 1052 1053
  base::Optional<PropertyCellRef> GetPropertyCell(
      NameRef const& name, SerializationPolicy policy =
                               SerializationPolicy::kAssumeSerialized) const;
1054 1055
};

1056 1057
class JSGlobalProxyRef : public JSObjectRef {
 public:
1058
  DEFINE_REF_CONSTRUCTOR(JSGlobalProxy, JSObjectRef)
1059 1060 1061 1062

  Handle<JSGlobalProxy> object() const;
};

1063 1064
class CodeRef : public HeapObjectRef {
 public:
1065
  DEFINE_REF_CONSTRUCTOR(Code, HeapObjectRef)
1066

1067
  Handle<Code> object() const;
1068

1069
  unsigned GetInlinedBytecodeSize() const;
1070 1071
};

1072 1073 1074 1075 1076 1077 1078 1079 1080
// CodeDataContainerRef doesn't appear to be used, but it is used via CodeT when
// V8_EXTERNAL_CODE_SPACE is defined.
class CodeDataContainerRef : public HeapObjectRef {
 public:
  DEFINE_REF_CONSTRUCTOR(CodeDataContainer, HeapObjectRef)

  Handle<CodeDataContainer> object() const;
};

1081 1082
class InternalizedStringRef : public StringRef {
 public:
1083
  DEFINE_REF_CONSTRUCTOR(InternalizedString, StringRef)
1084

1085 1086
  Handle<InternalizedString> object() const;
};
1087

1088 1089
#undef DEFINE_REF_CONSTRUCTOR

1090 1091 1092 1093 1094
}  // namespace compiler
}  // namespace internal
}  // namespace v8

#endif  // V8_COMPILER_HEAP_REFS_H_