Home | History | Annotate | Download | only in compiler
      1 // Copyright 2018 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 #include "src/compiler/js-heap-broker.h"
      6 
      7 #include "src/compiler/graph-reducer.h"
      8 #include "src/objects-inl.h"
      9 #include "src/objects/js-array-inl.h"
     10 #include "src/objects/js-regexp-inl.h"
     11 #include "src/objects/module-inl.h"
     12 #include "src/utils.h"
     13 
     14 namespace v8 {
     15 namespace internal {
     16 namespace compiler {
     17 
     18 #define FORWARD_DECL(Name) class Name##Data;
     19 HEAP_BROKER_OBJECT_LIST(FORWARD_DECL)
     20 #undef FORWARD_DECL
     21 
     22 // TODO(neis): It would be nice to share the serialized data for read-only
     23 // objects.
     24 
     25 class ObjectData : public ZoneObject {
     26  public:
     27   static ObjectData* Serialize(JSHeapBroker* broker, Handle<Object> object);
     28 
     29   ObjectData(JSHeapBroker* broker_, Handle<Object> object_, bool is_smi_)
     30       : broker(broker_), object(object_), is_smi(is_smi_) {
     31     broker->AddData(object, this);
     32   }
     33 
     34 #define DECLARE_IS_AND_AS(Name) \
     35   bool Is##Name() const;        \
     36   Name##Data* As##Name();
     37   HEAP_BROKER_OBJECT_LIST(DECLARE_IS_AND_AS)
     38 #undef DECLARE_IS_AND_AS
     39 
     40   JSHeapBroker* const broker;
     41   Handle<Object> const object;
     42   bool const is_smi;
     43 };
     44 
     45 // TODO(neis): Perhaps add a boolean that indicates whether serialization of an
     46 // object has completed. That could be used to add safety checks.
     47 
     48 #define GET_OR_CREATE(name) \
     49   broker->GetOrCreateData(handle(object_->name(), broker->isolate()))
     50 
     51 class HeapObjectData : public ObjectData {
     52  public:
     53   static HeapObjectData* Serialize(JSHeapBroker* broker,
     54                                    Handle<HeapObject> object);
     55 
     56   HeapObjectType const type;
     57   MapData* const map;
     58 
     59   HeapObjectData(JSHeapBroker* broker_, Handle<HeapObject> object_,
     60                  HeapObjectType type_)
     61       : ObjectData(broker_, object_, false),
     62         type(type_),
     63         map(GET_OR_CREATE(map)->AsMap()) {
     64     CHECK(broker_->SerializingAllowed());
     65   }
     66 };
     67 
     68 class PropertyCellData : public HeapObjectData {
     69  public:
     70   PropertyCellData(JSHeapBroker* broker_, Handle<PropertyCell> object_,
     71                    HeapObjectType type_)
     72       : HeapObjectData(broker_, object_, type_) {}
     73 };
     74 
     75 class JSObjectData : public HeapObjectData {
     76  public:
     77   JSObjectData(JSHeapBroker* broker_, Handle<JSObject> object_,
     78                HeapObjectType type_)
     79       : HeapObjectData(broker_, object_, type_) {}
     80 };
     81 
     82 class JSFunctionData : public JSObjectData {
     83  public:
     84   JSGlobalProxyData* const global_proxy;
     85   MapData* const initial_map;  // Can be nullptr.
     86   bool const has_prototype;
     87   ObjectData* const prototype;  // Can be nullptr.
     88   bool const PrototypeRequiresRuntimeLookup;
     89   SharedFunctionInfoData* const shared;
     90 
     91   JSFunctionData(JSHeapBroker* broker_, Handle<JSFunction> object_,
     92                  HeapObjectType type_);
     93 };
     94 
     95 class JSRegExpData : public JSObjectData {
     96  public:
     97   JSRegExpData(JSHeapBroker* broker_, Handle<JSRegExp> object_,
     98                HeapObjectType type_)
     99       : JSObjectData(broker_, object_, type_) {}
    100 };
    101 
    102 class HeapNumberData : public HeapObjectData {
    103  public:
    104   HeapNumberData(JSHeapBroker* broker_, Handle<HeapNumber> object_,
    105                  HeapObjectType type_)
    106       : HeapObjectData(broker_, object_, type_) {}
    107 };
    108 
    109 class MutableHeapNumberData : public HeapObjectData {
    110  public:
    111   MutableHeapNumberData(JSHeapBroker* broker_,
    112                         Handle<MutableHeapNumber> object_, HeapObjectType type_)
    113       : HeapObjectData(broker_, object_, type_) {}
    114 };
    115 
    116 class ContextData : public HeapObjectData {
    117  public:
    118   ContextData(JSHeapBroker* broker_, Handle<Context> object_,
    119               HeapObjectType type_)
    120       : HeapObjectData(broker_, object_, type_) {}
    121 };
    122 
    123 class NativeContextData : public ContextData {
    124  public:
    125 #define DECL_MEMBER(type, name) type##Data* const name;
    126   BROKER_NATIVE_CONTEXT_FIELDS(DECL_MEMBER)
    127 #undef DECL_MEMBER
    128 
    129   NativeContextData(JSHeapBroker* broker_, Handle<NativeContext> object_,
    130                     HeapObjectType type_)
    131       : ContextData(broker_, object_, type_)
    132 #define INIT_MEMBER(type, name) , name(GET_OR_CREATE(name)->As##type())
    133             BROKER_NATIVE_CONTEXT_FIELDS(INIT_MEMBER)
    134 #undef INIT_MEMBER
    135   {
    136   }
    137 };
    138 
    139 class NameData : public HeapObjectData {
    140  public:
    141   NameData(JSHeapBroker* broker, Handle<Name> object, HeapObjectType type)
    142       : HeapObjectData(broker, object, type) {}
    143 };
    144 
    145 class StringData : public NameData {
    146  public:
    147   StringData(JSHeapBroker* broker, Handle<String> object, HeapObjectType type)
    148       : NameData(broker, object, type),
    149         length(object->length()),
    150         first_char(length > 0 ? object->Get(0) : 0) {
    151     int flags = ALLOW_HEX | ALLOW_OCTAL | ALLOW_BINARY;
    152     if (length <= kMaxLengthForDoubleConversion) {
    153       to_number = StringToDouble(
    154           broker->isolate(), broker->isolate()->unicode_cache(), object, flags);
    155     }
    156   }
    157 
    158   int const length;
    159   uint16_t const first_char;
    160   base::Optional<double> to_number;
    161 
    162  private:
    163   static constexpr int kMaxLengthForDoubleConversion = 23;
    164 };
    165 
    166 class InternalizedStringData : public StringData {
    167  public:
    168   InternalizedStringData(JSHeapBroker* broker,
    169                          Handle<InternalizedString> object, HeapObjectType type)
    170       : StringData(broker, object, type) {}
    171 };
    172 
    173 namespace {
    174 
    175 bool IsFastLiteralHelper(Handle<JSObject> boilerplate, int max_depth,
    176                          int* max_properties) {
    177   DCHECK_GE(max_depth, 0);
    178   DCHECK_GE(*max_properties, 0);
    179 
    180   // Make sure the boilerplate map is not deprecated.
    181   if (!JSObject::TryMigrateInstance(boilerplate)) return false;
    182 
    183   // Check for too deep nesting.
    184   if (max_depth == 0) return false;
    185 
    186   // Check the elements.
    187   Isolate* const isolate = boilerplate->GetIsolate();
    188   Handle<FixedArrayBase> elements(boilerplate->elements(), isolate);
    189   if (elements->length() > 0 &&
    190       elements->map() != ReadOnlyRoots(isolate).fixed_cow_array_map()) {
    191     if (boilerplate->HasSmiOrObjectElements()) {
    192       Handle<FixedArray> fast_elements = Handle<FixedArray>::cast(elements);
    193       int length = elements->length();
    194       for (int i = 0; i < length; i++) {
    195         if ((*max_properties)-- == 0) return false;
    196         Handle<Object> value(fast_elements->get(i), isolate);
    197         if (value->IsJSObject()) {
    198           Handle<JSObject> value_object = Handle<JSObject>::cast(value);
    199           if (!IsFastLiteralHelper(value_object, max_depth - 1,
    200                                    max_properties)) {
    201             return false;
    202           }
    203         }
    204       }
    205     } else if (boilerplate->HasDoubleElements()) {
    206       if (elements->Size() > kMaxRegularHeapObjectSize) return false;
    207     } else {
    208       return false;
    209     }
    210   }
    211 
    212   // TODO(turbofan): Do we want to support out-of-object properties?
    213   if (!(boilerplate->HasFastProperties() &&
    214         boilerplate->property_array()->length() == 0)) {
    215     return false;
    216   }
    217 
    218   // Check the in-object properties.
    219   Handle<DescriptorArray> descriptors(
    220       boilerplate->map()->instance_descriptors(), isolate);
    221   int limit = boilerplate->map()->NumberOfOwnDescriptors();
    222   for (int i = 0; i < limit; i++) {
    223     PropertyDetails details = descriptors->GetDetails(i);
    224     if (details.location() != kField) continue;
    225     DCHECK_EQ(kData, details.kind());
    226     if ((*max_properties)-- == 0) return false;
    227     FieldIndex field_index = FieldIndex::ForDescriptor(boilerplate->map(), i);
    228     if (boilerplate->IsUnboxedDoubleField(field_index)) continue;
    229     Handle<Object> value(boilerplate->RawFastPropertyAt(field_index), isolate);
    230     if (value->IsJSObject()) {
    231       Handle<JSObject> value_object = Handle<JSObject>::cast(value);
    232       if (!IsFastLiteralHelper(value_object, max_depth - 1, max_properties)) {
    233         return false;
    234       }
    235     }
    236   }
    237   return true;
    238 }
    239 
    240 // Maximum depth and total number of elements and properties for literal
    241 // graphs to be considered for fast deep-copying. The limit is chosen to
    242 // match the maximum number of inobject properties, to ensure that the
    243 // performance of using object literals is not worse than using constructor
    244 // functions, see crbug.com/v8/6211 for details.
    245 const int kMaxFastLiteralDepth = 3;
    246 const int kMaxFastLiteralProperties = JSObject::kMaxInObjectProperties;
    247 
    248 // Determines whether the given array or object literal boilerplate satisfies
    249 // all limits to be considered for fast deep-copying and computes the total
    250 // size of all objects that are part of the graph.
    251 bool IsInlinableFastLiteral(Handle<JSObject> boilerplate) {
    252   int max_properties = kMaxFastLiteralProperties;
    253   return IsFastLiteralHelper(boilerplate, kMaxFastLiteralDepth,
    254                              &max_properties);
    255 }
    256 
    257 }  // namespace
    258 
    259 class AllocationSiteData : public HeapObjectData {
    260  public:
    261   AllocationSiteData(JSHeapBroker* broker, Handle<AllocationSite> object_,
    262                      HeapObjectType type_)
    263       : HeapObjectData(broker, object_, type_),
    264         PointsToLiteral(object_->PointsToLiteral()),
    265         GetPretenureMode(object_->GetPretenureMode()),
    266         nested_site(GET_OR_CREATE(nested_site)) {
    267     if (PointsToLiteral) {
    268       if (IsInlinableFastLiteral(
    269               handle(object_->boilerplate(), broker->isolate()))) {
    270         boilerplate = GET_OR_CREATE(boilerplate)->AsJSObject();
    271       }
    272     } else {
    273       GetElementsKind = object_->GetElementsKind();
    274       CanInlineCall = object_->CanInlineCall();
    275     }
    276   }
    277 
    278   bool const PointsToLiteral;
    279   PretenureFlag const GetPretenureMode;
    280   ObjectData* const nested_site;
    281   JSObjectData* boilerplate = nullptr;
    282 
    283   // These are only valid if PointsToLiteral is false.
    284   ElementsKind GetElementsKind = NO_ELEMENTS;
    285   bool CanInlineCall = false;
    286 };
    287 
    288 // Only used in JSNativeContextSpecialization.
    289 class ScriptContextTableData : public HeapObjectData {
    290  public:
    291   ScriptContextTableData(JSHeapBroker* broker_,
    292                          Handle<ScriptContextTable> object_,
    293                          HeapObjectType type_)
    294       : HeapObjectData(broker_, object_, type_) {}
    295 };
    296 
    297 class MapData : public HeapObjectData {
    298  public:
    299   InstanceType const instance_type;
    300   int const instance_size;
    301   byte const bit_field;
    302   byte const bit_field2;
    303   uint32_t const bit_field3;
    304 
    305   MapData(JSHeapBroker* broker_, Handle<Map> object_, HeapObjectType type_);
    306 
    307   // Extra information.
    308   void SerializeElementsKindGeneralizations();
    309   const ZoneVector<MapData*>& elements_kind_generalizations() {
    310     return elements_kind_generalizations_;
    311   }
    312 
    313  private:
    314   ZoneVector<MapData*> elements_kind_generalizations_;
    315 };
    316 
    317 MapData::MapData(JSHeapBroker* broker_, Handle<Map> object_,
    318                  HeapObjectType type_)
    319     : HeapObjectData(broker_, object_, type_),
    320       instance_type(object_->instance_type()),
    321       instance_size(object_->instance_size()),
    322       bit_field(object_->bit_field()),
    323       bit_field2(object_->bit_field2()),
    324       bit_field3(object_->bit_field3()),
    325       elements_kind_generalizations_(broker->zone()) {}
    326 
    327 JSFunctionData::JSFunctionData(JSHeapBroker* broker_,
    328                                Handle<JSFunction> object_, HeapObjectType type_)
    329     : JSObjectData(broker_, object_, type_),
    330       global_proxy(GET_OR_CREATE(global_proxy)->AsJSGlobalProxy()),
    331       initial_map(object_->has_prototype_slot() && object_->has_initial_map()
    332                       ? GET_OR_CREATE(initial_map)->AsMap()
    333                       : nullptr),
    334       has_prototype(object_->has_prototype_slot() && object_->has_prototype()),
    335       prototype(has_prototype ? GET_OR_CREATE(prototype) : nullptr),
    336       PrototypeRequiresRuntimeLookup(object_->PrototypeRequiresRuntimeLookup()),
    337       shared(GET_OR_CREATE(shared)->AsSharedFunctionInfo()) {
    338   if (initial_map != nullptr && initial_map->instance_type == JS_ARRAY_TYPE) {
    339     initial_map->SerializeElementsKindGeneralizations();
    340   }
    341 }
    342 
    343 void MapData::SerializeElementsKindGeneralizations() {
    344   broker->Trace("Computing ElementsKind generalizations of %p.\n", *object);
    345   DCHECK_EQ(instance_type, JS_ARRAY_TYPE);
    346   MapRef self(this);
    347   ElementsKind from_kind = self.elements_kind();
    348   for (int i = FIRST_FAST_ELEMENTS_KIND; i <= LAST_FAST_ELEMENTS_KIND; i++) {
    349     ElementsKind to_kind = static_cast<ElementsKind>(i);
    350     if (IsMoreGeneralElementsKindTransition(from_kind, to_kind)) {
    351       Handle<Map> target =
    352           Map::AsElementsKind(broker->isolate(), self.object<Map>(), to_kind);
    353       elements_kind_generalizations_.push_back(
    354           broker->GetOrCreateData(target)->AsMap());
    355     }
    356   }
    357 }
    358 
    359 class FeedbackVectorData : public HeapObjectData {
    360  public:
    361   const ZoneVector<ObjectData*>& feedback() { return feedback_; }
    362 
    363   FeedbackVectorData(JSHeapBroker* broker_, Handle<FeedbackVector> object_,
    364                      HeapObjectType type_);
    365 
    366  private:
    367   ZoneVector<ObjectData*> feedback_;
    368 };
    369 
    370 FeedbackVectorData::FeedbackVectorData(JSHeapBroker* broker_,
    371                                        Handle<FeedbackVector> object_,
    372                                        HeapObjectType type_)
    373     : HeapObjectData(broker_, object_, type_), feedback_(broker_->zone()) {
    374   feedback_.reserve(object_->length());
    375   for (int i = 0; i < object_->length(); ++i) {
    376     MaybeObject* value = object_->get(i);
    377     feedback_.push_back(value->IsObject()
    378                             ? broker->GetOrCreateData(
    379                                   handle(value->ToObject(), broker->isolate()))
    380                             : nullptr);
    381   }
    382   DCHECK_EQ(object_->length(), feedback_.size());
    383 }
    384 
    385 class FixedArrayBaseData : public HeapObjectData {
    386  public:
    387   int const length;
    388 
    389   FixedArrayBaseData(JSHeapBroker* broker_, Handle<FixedArrayBase> object_,
    390                      HeapObjectType type_)
    391       : HeapObjectData(broker_, object_, type_), length(object_->length()) {}
    392 };
    393 
    394 class FixedArrayData : public FixedArrayBaseData {
    395  public:
    396   FixedArrayData(JSHeapBroker* broker_, Handle<FixedArray> object_,
    397                  HeapObjectType type_)
    398       : FixedArrayBaseData(broker_, object_, type_) {}
    399 };
    400 
    401 class FixedDoubleArrayData : public FixedArrayBaseData {
    402  public:
    403   FixedDoubleArrayData(JSHeapBroker* broker_, Handle<FixedDoubleArray> object_,
    404                        HeapObjectType type_)
    405       : FixedArrayBaseData(broker_, object_, type_) {}
    406 };
    407 
    408 class BytecodeArrayData : public FixedArrayBaseData {
    409  public:
    410   int const register_count;
    411 
    412   BytecodeArrayData(JSHeapBroker* broker_, Handle<BytecodeArray> object_,
    413                     HeapObjectType type_)
    414       : FixedArrayBaseData(broker_, object_, type_),
    415         register_count(object_->register_count()) {}
    416 };
    417 
    418 class JSArrayData : public JSObjectData {
    419  public:
    420   JSArrayData(JSHeapBroker* broker_, Handle<JSArray> object_,
    421               HeapObjectType type_)
    422       : JSObjectData(broker_, object_, type_) {}
    423 };
    424 
    425 class ScopeInfoData : public HeapObjectData {
    426  public:
    427   ScopeInfoData(JSHeapBroker* broker_, Handle<ScopeInfo> object_,
    428                 HeapObjectType type_)
    429       : HeapObjectData(broker_, object_, type_) {}
    430 };
    431 
    432 class SharedFunctionInfoData : public HeapObjectData {
    433  public:
    434   int const builtin_id;
    435   BytecodeArrayData* const GetBytecodeArray;  // Can be nullptr.
    436 #define DECL_MEMBER(type, name) type const name;
    437   BROKER_SFI_FIELDS(DECL_MEMBER)
    438 #undef DECL_MEMBER
    439 
    440   SharedFunctionInfoData(JSHeapBroker* broker_,
    441                          Handle<SharedFunctionInfo> object_,
    442                          HeapObjectType type_)
    443       : HeapObjectData(broker_, object_, type_),
    444         builtin_id(object_->HasBuiltinId() ? object_->builtin_id()
    445                                            : Builtins::kNoBuiltinId),
    446         GetBytecodeArray(
    447             object_->HasBytecodeArray()
    448                 ? GET_OR_CREATE(GetBytecodeArray)->AsBytecodeArray()
    449                 : nullptr)
    450 #define INIT_MEMBER(type, name) , name(object_->name())
    451             BROKER_SFI_FIELDS(INIT_MEMBER)
    452 #undef INIT_MEMBER
    453   {
    454     DCHECK_EQ(HasBuiltinId, builtin_id != Builtins::kNoBuiltinId);
    455     DCHECK_EQ(HasBytecodeArray, GetBytecodeArray != nullptr);
    456   }
    457 };
    458 
    459 class ModuleData : public HeapObjectData {
    460  public:
    461   ModuleData(JSHeapBroker* broker_, Handle<Module> object_,
    462              HeapObjectType type_)
    463       : HeapObjectData(broker_, object_, type_) {}
    464 };
    465 
    466 class CellData : public HeapObjectData {
    467  public:
    468   CellData(JSHeapBroker* broker_, Handle<Cell> object_, HeapObjectType type_)
    469       : HeapObjectData(broker_, object_, type_) {}
    470 };
    471 
    472 class JSGlobalProxyData : public JSObjectData {
    473  public:
    474   JSGlobalProxyData(JSHeapBroker* broker_, Handle<JSGlobalProxy> object_,
    475                     HeapObjectType type_)
    476       : JSObjectData(broker_, object_, type_) {}
    477 };
    478 
    479 class CodeData : public HeapObjectData {
    480  public:
    481   CodeData(JSHeapBroker* broker_, Handle<Code> object_, HeapObjectType type_)
    482       : HeapObjectData(broker_, object_, type_) {}
    483 };
    484 
    485 #define DEFINE_IS_AND_AS(Name)                                          \
    486   bool ObjectData::Is##Name() const {                                   \
    487     if (broker->mode() == JSHeapBroker::kDisabled) {                    \
    488       AllowHandleDereference allow_handle_dereference;                  \
    489       return object->Is##Name();                                        \
    490     }                                                                   \
    491     if (is_smi) return false;                                           \
    492     InstanceType instance_type =                                        \
    493         static_cast<const HeapObjectData*>(this)->type.instance_type(); \
    494     return InstanceTypeChecker::Is##Name(instance_type);                \
    495   }                                                                     \
    496   Name##Data* ObjectData::As##Name() {                                  \
    497     CHECK_NE(broker->mode(), JSHeapBroker::kDisabled);                  \
    498     CHECK(Is##Name());                                                  \
    499     return static_cast<Name##Data*>(this);                              \
    500   }
    501 HEAP_BROKER_OBJECT_LIST(DEFINE_IS_AND_AS)
    502 #undef DEFINE_IS_AND_AS
    503 
    504 ObjectData* ObjectData::Serialize(JSHeapBroker* broker, Handle<Object> object) {
    505   CHECK(broker->SerializingAllowed());
    506   return object->IsSmi() ? new (broker->zone()) ObjectData(broker, object, true)
    507                          : HeapObjectData::Serialize(
    508                                broker, Handle<HeapObject>::cast(object));
    509 }
    510 
    511 HeapObjectData* HeapObjectData::Serialize(JSHeapBroker* broker,
    512                                           Handle<HeapObject> object) {
    513   CHECK(broker->SerializingAllowed());
    514   Handle<Map> map(object->map(), broker->isolate());
    515   HeapObjectType type = broker->HeapObjectTypeFromMap(map);
    516 
    517 #define RETURN_CREATE_DATA_IF_MATCH(name)                     \
    518   if (object->Is##name()) {                                   \
    519     return new (broker->zone())                               \
    520         name##Data(broker, Handle<name>::cast(object), type); \
    521   }
    522   HEAP_BROKER_OBJECT_LIST(RETURN_CREATE_DATA_IF_MATCH)
    523 #undef RETURN_CREATE_DATA_IF_MATCH
    524   UNREACHABLE();
    525 }
    526 
    527 bool ObjectRef::equals(const ObjectRef& other) const {
    528   return data_ == other.data_;
    529 }
    530 
    531 StringRef ObjectRef::TypeOf() const {
    532   AllowHandleAllocation handle_allocation;
    533   AllowHandleDereference handle_dereference;
    534   return StringRef(broker(),
    535                    Object::TypeOf(broker()->isolate(), object<Object>()));
    536 }
    537 
    538 Isolate* ObjectRef::isolate() const { return broker()->isolate(); }
    539 
    540 base::Optional<ContextRef> ContextRef::previous() const {
    541   AllowHandleAllocation handle_allocation;
    542   AllowHandleDereference handle_dereference;
    543   Context* previous = object<Context>()->previous();
    544   if (previous == nullptr) return base::Optional<ContextRef>();
    545   return ContextRef(broker(), handle(previous, broker()->isolate()));
    546 }
    547 
    548 ObjectRef ContextRef::get(int index) const {
    549   AllowHandleAllocation handle_allocation;
    550   AllowHandleDereference handle_dereference;
    551   Handle<Object> value(object<Context>()->get(index), broker()->isolate());
    552   return ObjectRef(broker(), value);
    553 }
    554 
    555 JSHeapBroker::JSHeapBroker(Isolate* isolate, Zone* zone)
    556     : isolate_(isolate),
    557       zone_(zone),
    558       refs_(zone),
    559       mode_(FLAG_concurrent_compiler_frontend ? kSerializing : kDisabled) {
    560   Trace("%s", "Constructing heap broker.\n");
    561 }
    562 
    563 void JSHeapBroker::Trace(const char* format, ...) const {
    564   if (FLAG_trace_heap_broker) {
    565     PrintF("[%p] ", this);
    566     va_list arguments;
    567     va_start(arguments, format);
    568     base::OS::VPrint(format, arguments);
    569     va_end(arguments);
    570   }
    571 }
    572 
    573 bool JSHeapBroker::SerializingAllowed() const {
    574   return mode() == kSerializing ||
    575          (!FLAG_strict_heap_broker && mode() == kSerialized);
    576 }
    577 
    578 void JSHeapBroker::SerializeStandardObjects() {
    579   Trace("Serializing standard objects.\n");
    580 
    581   Builtins* const b = isolate()->builtins();
    582   Factory* const f = isolate()->factory();
    583 
    584   // Stuff used by JSGraph:
    585   GetOrCreateData(f->empty_fixed_array());
    586 
    587   // Stuff used by JSCreateLowering:
    588   GetOrCreateData(f->block_context_map());
    589   GetOrCreateData(f->catch_context_map());
    590   GetOrCreateData(f->eval_context_map());
    591   GetOrCreateData(f->fixed_array_map());
    592   GetOrCreateData(f->fixed_double_array_map());
    593   GetOrCreateData(f->function_context_map());
    594   GetOrCreateData(f->many_closures_cell_map());
    595   GetOrCreateData(f->mutable_heap_number_map());
    596   GetOrCreateData(f->name_dictionary_map());
    597   GetOrCreateData(f->one_pointer_filler_map());
    598   GetOrCreateData(f->sloppy_arguments_elements_map());
    599   GetOrCreateData(f->with_context_map());
    600 
    601   // Stuff used by TypedOptimization:
    602   // Strings produced by typeof:
    603   GetOrCreateData(f->boolean_string());
    604   GetOrCreateData(f->number_string());
    605   GetOrCreateData(f->string_string());
    606   GetOrCreateData(f->bigint_string());
    607   GetOrCreateData(f->symbol_string());
    608   GetOrCreateData(f->undefined_string());
    609   GetOrCreateData(f->object_string());
    610   GetOrCreateData(f->function_string());
    611 
    612   // Stuff used by JSTypedLowering:
    613   GetOrCreateData(f->length_string());
    614   Builtins::Name builtins[] = {
    615       Builtins::kArgumentsAdaptorTrampoline,
    616       Builtins::kCallFunctionForwardVarargs,
    617       Builtins::kStringAdd_CheckNone_NotTenured,
    618       Builtins::kStringAdd_CheckNone_Tenured,
    619       Builtins::kStringAdd_ConvertLeft_NotTenured,
    620       Builtins::kStringAdd_ConvertRight_NotTenured,
    621   };
    622   for (auto id : builtins) {
    623     GetOrCreateData(b->builtin_handle(id));
    624   }
    625   for (int32_t id = 0; id < Builtins::builtin_count; ++id) {
    626     if (Builtins::KindOf(id) == Builtins::TFJ) {
    627       GetOrCreateData(b->builtin_handle(id));
    628     }
    629   }
    630 
    631   Trace("Finished serializing standard objects.\n");
    632 }
    633 
    634 HeapObjectType JSHeapBroker::HeapObjectTypeFromMap(Map* map) const {
    635   AllowHandleDereference allow_handle_dereference;
    636   OddballType oddball_type = OddballType::kNone;
    637   if (map->instance_type() == ODDBALL_TYPE) {
    638     ReadOnlyRoots roots(isolate_);
    639     if (map == roots.undefined_map()) {
    640       oddball_type = OddballType::kUndefined;
    641     } else if (map == roots.null_map()) {
    642       oddball_type = OddballType::kNull;
    643     } else if (map == roots.boolean_map()) {
    644       oddball_type = OddballType::kBoolean;
    645     } else if (map == roots.the_hole_map()) {
    646       oddball_type = OddballType::kHole;
    647     } else if (map == roots.uninitialized_map()) {
    648       oddball_type = OddballType::kUninitialized;
    649     } else {
    650       oddball_type = OddballType::kOther;
    651       DCHECK(map == roots.termination_exception_map() ||
    652              map == roots.arguments_marker_map() ||
    653              map == roots.optimized_out_map() ||
    654              map == roots.stale_register_map());
    655     }
    656   }
    657   HeapObjectType::Flags flags(0);
    658   if (map->is_undetectable()) flags |= HeapObjectType::kUndetectable;
    659   if (map->is_callable()) flags |= HeapObjectType::kCallable;
    660 
    661   return HeapObjectType(map->instance_type(), flags, oddball_type);
    662 }
    663 
    664 ObjectData* JSHeapBroker::GetData(Handle<Object> object) const {
    665   auto it = refs_.find(object.address());
    666   return it != refs_.end() ? it->second : nullptr;
    667 }
    668 
    669 ObjectData* JSHeapBroker::GetOrCreateData(Handle<Object> object) {
    670   CHECK(SerializingAllowed());
    671   ObjectData* data = GetData(object);
    672   if (data == nullptr) {
    673     // TODO(neis): Remove these Allow* once we serialize everything upfront.
    674     AllowHandleAllocation handle_allocation;
    675     AllowHandleDereference handle_dereference;
    676     data = ObjectData::Serialize(this, object);
    677   }
    678   CHECK_NOT_NULL(data);
    679   return data;
    680 }
    681 
    682 void JSHeapBroker::AddData(Handle<Object> object, ObjectData* data) {
    683   Trace("Creating data %p for handle %" V8PRIuPTR " (", data, object.address());
    684   if (FLAG_trace_heap_broker) {
    685     object->ShortPrint();
    686     PrintF(")\n");
    687   }
    688   CHECK_NOT_NULL(isolate()->handle_scope_data()->canonical_scope);
    689   CHECK(refs_.insert({object.address(), data}).second);
    690 }
    691 
    692 #define DEFINE_IS_AND_AS(Name)                                    \
    693   bool ObjectRef::Is##Name() const { return data()->Is##Name(); } \
    694   Name##Ref ObjectRef::As##Name() const {                         \
    695     DCHECK(Is##Name());                                           \
    696     return Name##Ref(data());                                     \
    697   }
    698 HEAP_BROKER_OBJECT_LIST(DEFINE_IS_AND_AS)
    699 #undef DEFINE_IS_AND_AS
    700 
    701 bool ObjectRef::IsSmi() const { return data()->is_smi; }
    702 
    703 int ObjectRef::AsSmi() const {
    704   DCHECK(IsSmi());
    705   // Handle-dereference is always allowed for Handle<Smi>.
    706   return object<Smi>()->value();
    707 }
    708 
    709 HeapObjectType HeapObjectRef::type() const {
    710   if (broker()->mode() == JSHeapBroker::kDisabled) {
    711     AllowHandleDereference allow_handle_dereference;
    712     return broker()->HeapObjectTypeFromMap(object<HeapObject>()->map());
    713   } else {
    714     return data()->AsHeapObject()->type;
    715   }
    716 }
    717 
    718 base::Optional<MapRef> HeapObjectRef::TryGetObjectCreateMap() const {
    719   AllowHandleAllocation handle_allocation;
    720   AllowHandleDereference allow_handle_dereference;
    721   Handle<Map> instance_map;
    722   if (Map::TryGetObjectCreateMap(broker()->isolate(), object<HeapObject>())
    723           .ToHandle(&instance_map)) {
    724     return MapRef(broker(), instance_map);
    725   } else {
    726     return base::Optional<MapRef>();
    727   }
    728 }
    729 
    730 base::Optional<MapRef> MapRef::AsElementsKind(ElementsKind kind) const {
    731   if (broker()->mode() == JSHeapBroker::kDisabled) {
    732     AllowHandleAllocation handle_allocation;
    733     AllowHeapAllocation heap_allocation;
    734     AllowHandleDereference allow_handle_dereference;
    735     return MapRef(broker(), Map::AsElementsKind(broker()->isolate(),
    736                                                 object<Map>(), kind));
    737   } else {
    738     if (kind == elements_kind()) return *this;
    739     const ZoneVector<MapData*>& elements_kind_generalizations =
    740         data()->AsMap()->elements_kind_generalizations();
    741     for (auto data : elements_kind_generalizations) {
    742       MapRef map(data);
    743       if (map.elements_kind() == kind) return map;
    744     }
    745     return base::Optional<MapRef>();
    746   }
    747 }
    748 
    749 int JSFunctionRef::InitialMapInstanceSizeWithMinSlack() const {
    750   AllowHandleDereference allow_handle_dereference;
    751   AllowHandleAllocation handle_allocation;
    752 
    753   return object<JSFunction>()->ComputeInstanceSizeWithMinSlack(
    754       broker()->isolate());
    755 }
    756 
    757 base::Optional<ScriptContextTableRef::LookupResult>
    758 ScriptContextTableRef::lookup(const NameRef& name) const {
    759   AllowHandleAllocation handle_allocation;
    760   AllowHandleDereference handle_dereference;
    761   if (!name.IsString()) return {};
    762   ScriptContextTable::LookupResult lookup_result;
    763   auto table = object<ScriptContextTable>();
    764   if (!ScriptContextTable::Lookup(broker()->isolate(), table,
    765                                   name.object<String>(), &lookup_result)) {
    766     return {};
    767   }
    768   Handle<Context> script_context = ScriptContextTable::GetContext(
    769       broker()->isolate(), table, lookup_result.context_index);
    770   LookupResult result{ContextRef(broker(), script_context),
    771                       lookup_result.mode == VariableMode::kConst,
    772                       lookup_result.slot_index};
    773   return result;
    774 }
    775 
    776 OddballType ObjectRef::oddball_type() const {
    777   return IsSmi() ? OddballType::kNone : AsHeapObject().type().oddball_type();
    778 }
    779 
    780 ObjectRef FeedbackVectorRef::get(FeedbackSlot slot) const {
    781   if (broker()->mode() == JSHeapBroker::kDisabled) {
    782     AllowHandleAllocation handle_allocation;
    783     AllowHandleDereference handle_dereference;
    784     Handle<Object> value(object<FeedbackVector>()->Get(slot)->ToObject(),
    785                          broker()->isolate());
    786     return ObjectRef(broker(), value);
    787   }
    788   int i = FeedbackVector::GetIndex(slot);
    789   return ObjectRef(data()->AsFeedbackVector()->feedback().at(i));
    790 }
    791 
    792 bool JSObjectRef::IsUnboxedDoubleField(FieldIndex index) const {
    793   AllowHandleDereference handle_dereference;
    794   return object<JSObject>()->IsUnboxedDoubleField(index);
    795 }
    796 
    797 double JSObjectRef::RawFastDoublePropertyAt(FieldIndex index) const {
    798   AllowHandleDereference handle_dereference;
    799   return object<JSObject>()->RawFastDoublePropertyAt(index);
    800 }
    801 
    802 ObjectRef JSObjectRef::RawFastPropertyAt(FieldIndex index) const {
    803   AllowHandleAllocation handle_allocation;
    804   AllowHandleDereference handle_dereference;
    805   return ObjectRef(broker(),
    806                    handle(object<JSObject>()->RawFastPropertyAt(index),
    807                           broker()->isolate()));
    808 }
    809 
    810 
    811 bool AllocationSiteRef::IsFastLiteral() const {
    812   if (broker()->mode() == JSHeapBroker::kDisabled) {
    813     AllowHeapAllocation
    814         allow_heap_allocation;  // This is needed for TryMigrateInstance.
    815     AllowHandleAllocation allow_handle_allocation;
    816     AllowHandleDereference allow_handle_dereference;
    817     return IsInlinableFastLiteral(
    818         handle(object<AllocationSite>()->boilerplate(), broker()->isolate()));
    819   } else {
    820     return data()->AsAllocationSite()->boilerplate != nullptr;
    821   }
    822 }
    823 
    824 void JSObjectRef::EnsureElementsTenured() {
    825   // TODO(jarin) Eventually, we will pretenure the boilerplates before
    826   // the compilation job starts.
    827   AllowHandleAllocation allow_handle_allocation;
    828   AllowHandleDereference allow_handle_dereference;
    829   AllowHeapAllocation allow_heap_allocation;
    830 
    831   Handle<FixedArrayBase> object_elements = elements().object<FixedArrayBase>();
    832   if (Heap::InNewSpace(*object_elements)) {
    833     // If we would like to pretenure a fixed cow array, we must ensure that
    834     // the array is already in old space, otherwise we'll create too many
    835     // old-to-new-space pointers (overflowing the store buffer).
    836     object_elements =
    837         broker()->isolate()->factory()->CopyAndTenureFixedCOWArray(
    838             Handle<FixedArray>::cast(object_elements));
    839     object<JSObject>()->set_elements(*object_elements);
    840   }
    841 }
    842 
    843 FieldIndex MapRef::GetFieldIndexFor(int i) const {
    844   AllowHandleDereference allow_handle_dereference;
    845   return FieldIndex::ForDescriptor(*object<Map>(), i);
    846 }
    847 
    848 int MapRef::GetInObjectPropertyOffset(int i) const {
    849   AllowHandleDereference allow_handle_dereference;
    850   return object<Map>()->GetInObjectPropertyOffset(i);
    851 }
    852 
    853 PropertyDetails MapRef::GetPropertyDetails(int i) const {
    854   AllowHandleDereference allow_handle_dereference;
    855   return object<Map>()->instance_descriptors()->GetDetails(i);
    856 }
    857 
    858 NameRef MapRef::GetPropertyKey(int i) const {
    859   AllowHandleAllocation handle_allocation;
    860   AllowHandleDereference allow_handle_dereference;
    861   return NameRef(broker(),
    862                  handle(object<Map>()->instance_descriptors()->GetKey(i),
    863                         broker()->isolate()));
    864 }
    865 
    866 bool MapRef::IsFixedCowArrayMap() const {
    867   AllowHandleDereference allow_handle_dereference;
    868   return *object<Map>() ==
    869          ReadOnlyRoots(broker()->isolate()).fixed_cow_array_map();
    870 }
    871 
    872 MapRef MapRef::FindFieldOwner(int descriptor) const {
    873   AllowHandleAllocation handle_allocation;
    874   AllowHandleDereference allow_handle_dereference;
    875   Handle<Map> owner(
    876       object<Map>()->FindFieldOwner(broker()->isolate(), descriptor),
    877       broker()->isolate());
    878   return MapRef(broker(), owner);
    879 }
    880 
    881 ObjectRef MapRef::GetFieldType(int descriptor) const {
    882   AllowHandleAllocation handle_allocation;
    883   AllowHandleDereference allow_handle_dereference;
    884   Handle<FieldType> field_type(
    885       object<Map>()->instance_descriptors()->GetFieldType(descriptor),
    886       broker()->isolate());
    887   return ObjectRef(broker(), field_type);
    888 }
    889 
    890 uint16_t StringRef::GetFirstChar() {
    891   if (broker()->mode() == JSHeapBroker::kDisabled) {
    892     AllowHandleDereference allow_handle_dereference;
    893     return object<String>()->Get(0);
    894   } else {
    895     return data()->AsString()->first_char;
    896   }
    897 }
    898 
    899 base::Optional<double> StringRef::ToNumber() {
    900   if (broker()->mode() == JSHeapBroker::kDisabled) {
    901     AllowHandleDereference allow_handle_dereference;
    902     AllowHandleAllocation allow_handle_allocation;
    903     AllowHeapAllocation allow_heap_allocation;
    904     int flags = ALLOW_HEX | ALLOW_OCTAL | ALLOW_BINARY;
    905     return StringToDouble(broker()->isolate(),
    906                           broker()->isolate()->unicode_cache(),
    907                           object<String>(), flags);
    908   } else {
    909     return data()->AsString()->to_number;
    910   }
    911 }
    912 
    913 bool FixedArrayRef::is_the_hole(int i) const {
    914   AllowHandleDereference allow_handle_dereference;
    915   return object<FixedArray>()->is_the_hole(broker()->isolate(), i);
    916 }
    917 
    918 ObjectRef FixedArrayRef::get(int i) const {
    919   AllowHandleAllocation handle_allocation;
    920   AllowHandleDereference allow_handle_dereference;
    921   return ObjectRef(broker(),
    922                    handle(object<FixedArray>()->get(i), broker()->isolate()));
    923 }
    924 
    925 bool FixedDoubleArrayRef::is_the_hole(int i) const {
    926   AllowHandleDereference allow_handle_dereference;
    927   return object<FixedDoubleArray>()->is_the_hole(i);
    928 }
    929 
    930 double FixedDoubleArrayRef::get_scalar(int i) const {
    931   AllowHandleDereference allow_handle_dereference;
    932   return object<FixedDoubleArray>()->get_scalar(i);
    933 }
    934 
    935 #define IF_BROKER_DISABLED_ACCESS_HANDLE_C(holder, name) \
    936   if (broker()->mode() == JSHeapBroker::kDisabled) {     \
    937     AllowHandleAllocation handle_allocation;             \
    938     AllowHandleDereference allow_handle_dereference;     \
    939     return object<holder>()->name();                     \
    940   }
    941 
    942 // Macros for definining a const getter that, depending on the broker mode,
    943 // either looks into the handle or into the serialized data. The first one is
    944 // used for the rare case of a XYZRef class that does not have a corresponding
    945 // XYZ class in objects.h. The second one is used otherwise.
    946 #define BIMODAL_ACCESSOR(holder, result, name)                              \
    947   result##Ref holder##Ref::name() const {                                   \
    948     if (broker()->mode() == JSHeapBroker::kDisabled) {                      \
    949       AllowHandleAllocation handle_allocation;                              \
    950       AllowHandleDereference allow_handle_dereference;                      \
    951       return result##Ref(                                                   \
    952           broker(), handle(object<holder>()->name(), broker()->isolate())); \
    953     } else {                                                                \
    954       return result##Ref(data()->As##holder()->name);                       \
    955     }                                                                       \
    956   }
    957 
    958 // Like HANDLE_ACCESSOR except that the result type is not an XYZRef.
    959 #define BIMODAL_ACCESSOR_C(holder, result, name)      \
    960   result holder##Ref::name() const {                  \
    961     IF_BROKER_DISABLED_ACCESS_HANDLE_C(holder, name); \
    962     return data()->As##holder()->name;                \
    963   }
    964 
    965 // Like HANDLE_ACCESSOR_C but for BitFields.
    966 #define BIMODAL_ACCESSOR_B(holder, field, name, BitField)  \
    967   typename BitField::FieldType holder##Ref::name() const { \
    968     IF_BROKER_DISABLED_ACCESS_HANDLE_C(holder, name);      \
    969     return BitField::decode(data()->As##holder()->field);  \
    970   }
    971 
    972 // Macros for definining a const getter that always looks into the handle.
    973 // (These will go away once we serialize everything.) The first one is used for
    974 // the rare case of a XYZRef class that does not have a corresponding XYZ class
    975 // in objects.h. The second one is used otherwise.
    976 #define HANDLE_ACCESSOR(holder, result, name)                                  \
    977   result##Ref holder##Ref::name() const {                                      \
    978     AllowHandleAllocation handle_allocation;                                   \
    979     AllowHandleDereference allow_handle_dereference;                           \
    980     return result##Ref(broker(),                                               \
    981                        handle(object<holder>()->name(), broker()->isolate())); \
    982   }
    983 
    984 // Like HANDLE_ACCESSOR except that the result type is not an XYZRef.
    985 #define HANDLE_ACCESSOR_C(holder, result, name)      \
    986   result holder##Ref::name() const {                 \
    987     AllowHandleAllocation handle_allocation;         \
    988     AllowHandleDereference allow_handle_dereference; \
    989     return object<holder>()->name();                 \
    990   }
    991 
    992 BIMODAL_ACCESSOR(AllocationSite, Object, nested_site)
    993 BIMODAL_ACCESSOR_C(AllocationSite, bool, CanInlineCall)
    994 BIMODAL_ACCESSOR_C(AllocationSite, bool, PointsToLiteral)
    995 BIMODAL_ACCESSOR_C(AllocationSite, ElementsKind, GetElementsKind)
    996 BIMODAL_ACCESSOR_C(AllocationSite, PretenureFlag, GetPretenureMode)
    997 
    998 BIMODAL_ACCESSOR_C(BytecodeArray, int, register_count)
    999 
   1000 BIMODAL_ACCESSOR_C(FixedArrayBase, int, length)
   1001 
   1002 BIMODAL_ACCESSOR(HeapObject, Map, map)
   1003 HANDLE_ACCESSOR_C(HeapObject, bool, IsExternalString)
   1004 HANDLE_ACCESSOR_C(HeapObject, bool, IsSeqString)
   1005 
   1006 HANDLE_ACCESSOR_C(HeapNumber, double, value)
   1007 
   1008 HANDLE_ACCESSOR(JSArray, Object, length)
   1009 
   1010 BIMODAL_ACCESSOR_C(JSFunction, bool, has_prototype)
   1011 BIMODAL_ACCESSOR_C(JSFunction, bool, PrototypeRequiresRuntimeLookup)
   1012 BIMODAL_ACCESSOR(JSFunction, Map, initial_map)
   1013 BIMODAL_ACCESSOR(JSFunction, Object, prototype)
   1014 HANDLE_ACCESSOR_C(JSFunction, bool, IsConstructor)
   1015 HANDLE_ACCESSOR(JSFunction, JSGlobalProxy, global_proxy)
   1016 HANDLE_ACCESSOR(JSFunction, SharedFunctionInfo, shared)
   1017 
   1018 HANDLE_ACCESSOR(JSObject, FixedArrayBase, elements)
   1019 
   1020 HANDLE_ACCESSOR(JSRegExp, Object, data)
   1021 HANDLE_ACCESSOR(JSRegExp, Object, flags)
   1022 HANDLE_ACCESSOR(JSRegExp, Object, last_index)
   1023 HANDLE_ACCESSOR(JSRegExp, Object, raw_properties_or_hash)
   1024 HANDLE_ACCESSOR(JSRegExp, Object, source)
   1025 
   1026 BIMODAL_ACCESSOR_B(Map, bit_field2, elements_kind, Map::ElementsKindBits)
   1027 BIMODAL_ACCESSOR_B(Map, bit_field3, is_deprecated, Map::IsDeprecatedBit)
   1028 BIMODAL_ACCESSOR_B(Map, bit_field3, is_dictionary_map, Map::IsDictionaryMapBit)
   1029 BIMODAL_ACCESSOR_B(Map, bit_field, has_prototype_slot, Map::HasPrototypeSlotBit)
   1030 BIMODAL_ACCESSOR_C(Map, int, instance_size)
   1031 HANDLE_ACCESSOR_C(Map, bool, CanBeDeprecated)
   1032 HANDLE_ACCESSOR_C(Map, bool, CanTransition)
   1033 HANDLE_ACCESSOR_C(Map, bool, IsInobjectSlackTrackingInProgress)
   1034 HANDLE_ACCESSOR_C(Map, bool, IsJSArrayMap)
   1035 HANDLE_ACCESSOR_C(Map, bool, is_stable)
   1036 HANDLE_ACCESSOR_C(Map, InstanceType, instance_type)
   1037 HANDLE_ACCESSOR_C(Map, int, GetInObjectProperties)
   1038 HANDLE_ACCESSOR_C(Map, int, GetInObjectPropertiesStartInWords)
   1039 HANDLE_ACCESSOR_C(Map, int, NumberOfOwnDescriptors)
   1040 HANDLE_ACCESSOR(Map, Object, constructor_or_backpointer)
   1041 
   1042 HANDLE_ACCESSOR_C(MutableHeapNumber, double, value)
   1043 
   1044 #define DEF_NATIVE_CONTEXT_ACCESSOR(type, name) \
   1045   BIMODAL_ACCESSOR(NativeContext, type, name)
   1046 BROKER_NATIVE_CONTEXT_FIELDS(DEF_NATIVE_CONTEXT_ACCESSOR)
   1047 #undef DEF_NATIVE_CONTEXT_ACCESSOR
   1048 
   1049 HANDLE_ACCESSOR(PropertyCell, Object, value)
   1050 HANDLE_ACCESSOR_C(PropertyCell, PropertyDetails, property_details)
   1051 
   1052 HANDLE_ACCESSOR_C(ScopeInfo, int, ContextLength)
   1053 
   1054 BIMODAL_ACCESSOR_C(SharedFunctionInfo, int, builtin_id)
   1055 BIMODAL_ACCESSOR(SharedFunctionInfo, BytecodeArray, GetBytecodeArray)
   1056 #define DEF_SFI_ACCESSOR(type, name) \
   1057   BIMODAL_ACCESSOR_C(SharedFunctionInfo, type, name)
   1058 BROKER_SFI_FIELDS(DEF_SFI_ACCESSOR)
   1059 #undef DEF_SFI_ACCESSOR
   1060 
   1061 BIMODAL_ACCESSOR_C(String, int, length)
   1062 
   1063 // TODO(neis): Provide StringShape() on StringRef.
   1064 
   1065 bool JSFunctionRef::has_initial_map() const {
   1066   IF_BROKER_DISABLED_ACCESS_HANDLE_C(JSFunction, has_initial_map);
   1067   return data()->AsJSFunction()->initial_map != nullptr;
   1068 }
   1069 
   1070 MapRef NativeContextRef::GetFunctionMapFromIndex(int index) const {
   1071   DCHECK_LE(index, Context::LAST_FUNCTION_MAP_INDEX);
   1072   DCHECK_GE(index, Context::FIRST_FUNCTION_MAP_INDEX);
   1073   return get(index).AsMap();
   1074 }
   1075 
   1076 MapRef NativeContextRef::GetInitialJSArrayMap(ElementsKind kind) const {
   1077   switch (kind) {
   1078     case PACKED_SMI_ELEMENTS:
   1079       return js_array_packed_smi_elements_map();
   1080     case HOLEY_SMI_ELEMENTS:
   1081       return js_array_holey_smi_elements_map();
   1082     case PACKED_DOUBLE_ELEMENTS:
   1083       return js_array_packed_double_elements_map();
   1084     case HOLEY_DOUBLE_ELEMENTS:
   1085       return js_array_holey_double_elements_map();
   1086     case PACKED_ELEMENTS:
   1087       return js_array_packed_elements_map();
   1088     case HOLEY_ELEMENTS:
   1089       return js_array_holey_elements_map();
   1090     default:
   1091       UNREACHABLE();
   1092   }
   1093 }
   1094 
   1095 bool ObjectRef::BooleanValue() {
   1096   AllowHandleDereference allow_handle_dereference;
   1097   return object<Object>()->BooleanValue(broker()->isolate());
   1098 }
   1099 
   1100 double ObjectRef::OddballToNumber() const {
   1101   OddballType type = oddball_type();
   1102 
   1103   switch (type) {
   1104     case OddballType::kBoolean: {
   1105       ObjectRef true_ref(broker(),
   1106                          broker()->isolate()->factory()->true_value());
   1107       return this->equals(true_ref) ? 1 : 0;
   1108       break;
   1109     }
   1110     case OddballType::kUndefined: {
   1111       return std::numeric_limits<double>::quiet_NaN();
   1112       break;
   1113     }
   1114     case OddballType::kNull: {
   1115       return 0;
   1116       break;
   1117     }
   1118     default: {
   1119       UNREACHABLE();
   1120       break;
   1121     }
   1122   }
   1123 }
   1124 
   1125 CellRef ModuleRef::GetCell(int cell_index) {
   1126   AllowHandleAllocation handle_allocation;
   1127   AllowHandleDereference allow_handle_dereference;
   1128   return CellRef(broker(), handle(object<Module>()->GetCell(cell_index),
   1129                                   broker()->isolate()));
   1130 }
   1131 
   1132 ObjectRef::ObjectRef(JSHeapBroker* broker, Handle<Object> object) {
   1133   switch (broker->mode()) {
   1134     case JSHeapBroker::kSerialized:
   1135       data_ = FLAG_strict_heap_broker ? broker->GetData(object)
   1136                                       : broker->GetOrCreateData(object);
   1137       break;
   1138     case JSHeapBroker::kSerializing:
   1139       data_ = broker->GetOrCreateData(object);
   1140       break;
   1141     case JSHeapBroker::kDisabled:
   1142       data_ = broker->GetData(object);
   1143       if (data_ == nullptr) {
   1144         AllowHandleDereference handle_dereference;
   1145         data_ =
   1146             new (broker->zone()) ObjectData(broker, object, object->IsSmi());
   1147       }
   1148       break;
   1149   }
   1150   CHECK_NOT_NULL(data_);
   1151 }
   1152 
   1153 base::Optional<JSObjectRef> AllocationSiteRef::boilerplate() const {
   1154   if (broker()->mode() == JSHeapBroker::kDisabled) {
   1155     AllowHandleAllocation handle_allocation;
   1156     AllowHandleDereference allow_handle_dereference;
   1157     return JSObjectRef(broker(), handle(object<AllocationSite>()->boilerplate(),
   1158                                         broker()->isolate()));
   1159   } else {
   1160     JSObjectData* boilerplate = data()->AsAllocationSite()->boilerplate;
   1161     if (boilerplate) {
   1162       return JSObjectRef(boilerplate);
   1163     } else {
   1164       return base::nullopt;
   1165     }
   1166   }
   1167 }
   1168 
   1169 ElementsKind JSObjectRef::GetElementsKind() const {
   1170   return map().elements_kind();
   1171 }
   1172 
   1173 Handle<Object> ObjectRef::object() const { return data_->object; }
   1174 
   1175 JSHeapBroker* ObjectRef::broker() const { return data_->broker; }
   1176 
   1177 ObjectData* ObjectRef::data() const { return data_; }
   1178 
   1179 Reduction NoChangeBecauseOfMissingData(JSHeapBroker* broker,
   1180                                        const char* function, int line) {
   1181   if (FLAG_trace_heap_broker) {
   1182     PrintF("[%p] Skipping optimization in %s at line %d due to missing data\n",
   1183            broker, function, line);
   1184   }
   1185   return AdvancedReducer::NoChange();
   1186 }
   1187 
   1188 #undef BIMODAL_ACCESSOR
   1189 #undef BIMODAL_ACCESSOR_B
   1190 #undef BIMODAL_ACCESSOR_C
   1191 #undef GET_OR_CREATE
   1192 #undef HANDLE_ACCESSOR
   1193 #undef HANDLE_ACCESSOR_C
   1194 #undef IF_BROKER_DISABLED_ACCESS_HANDLE_C
   1195 
   1196 }  // namespace compiler
   1197 }  // namespace internal
   1198 }  // namespace v8
   1199