LCOV - code coverage report
Current view: top level - src/compiler - js-heap-broker.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 1065 1280 83.2 %
Date: 2019-04-17 Functions: 387 618 62.6 %

          Line data    Source code
       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             : #ifdef ENABLE_SLOW_DCHECKS
       8             : #include <algorithm>
       9             : #endif
      10             : 
      11             : #include "src/api-inl.h"
      12             : #include "src/ast/modules.h"
      13             : #include "src/bootstrapper.h"
      14             : #include "src/boxed-float.h"
      15             : #include "src/code-factory.h"
      16             : #include "src/compiler/graph-reducer.h"
      17             : #include "src/compiler/per-isolate-compiler-cache.h"
      18             : #include "src/objects-inl.h"
      19             : #include "src/objects/allocation-site-inl.h"
      20             : #include "src/objects/api-callbacks.h"
      21             : #include "src/objects/cell-inl.h"
      22             : #include "src/objects/heap-number-inl.h"
      23             : #include "src/objects/instance-type-inl.h"
      24             : #include "src/objects/js-array-buffer-inl.h"
      25             : #include "src/objects/js-array-inl.h"
      26             : #include "src/objects/js-regexp-inl.h"
      27             : #include "src/objects/module-inl.h"
      28             : #include "src/objects/templates.h"
      29             : #include "src/utils.h"
      30             : #include "src/vector-slot-pair.h"
      31             : 
      32             : namespace v8 {
      33             : namespace internal {
      34             : namespace compiler {
      35             : 
      36             : #define TRACE(broker, x) TRACE_BROKER(broker, x)
      37             : #define TRACE_MISSING(broker, x) TRACE_BROKER_MISSING(broker, x)
      38             : 
      39             : #define FORWARD_DECL(Name) class Name##Data;
      40             : HEAP_BROKER_OBJECT_LIST(FORWARD_DECL)
      41             : #undef FORWARD_DECL
      42             : 
      43             : // There are three kinds of ObjectData values.
      44             : //
      45             : // kSmi: The underlying V8 object is a Smi and the data is an instance of the
      46             : //   base class (ObjectData), i.e. it's basically just the handle.  Because the
      47             : //   object is a Smi, it's safe to access the handle in order to extract the
      48             : //   number value, and AsSmi() does exactly that.
      49             : //
      50             : // kSerializedHeapObject: The underlying V8 object is a HeapObject and the
      51             : //   data is an instance of the corresponding (most-specific) subclass, e.g.
      52             : //   JSFunctionData, which provides serialized information about the object.
      53             : //
      54             : // kUnserializedHeapObject: The underlying V8 object is a HeapObject and the
      55             : //   data is an instance of the base class (ObjectData), i.e. it basically
      56             : //   carries no information other than the handle.
      57             : //
      58             : enum ObjectDataKind { kSmi, kSerializedHeapObject, kUnserializedHeapObject };
      59             : 
      60             : class ObjectData : public ZoneObject {
      61             :  public:
      62    94250924 :   ObjectData(JSHeapBroker* broker, ObjectData** storage, Handle<Object> object,
      63             :              ObjectDataKind kind)
      64    94250924 :       : object_(object), kind_(kind) {
      65             :     // This assignment ensures we don't end up inserting the same object
      66             :     // in an endless recursion.
      67    94250924 :     *storage = this;
      68             : 
      69    94250924 :     TRACE(broker, "Creating data " << this << " for handle " << object.address()
      70             :                                    << " (" << Brief(*object) << ")");
      71             : 
      72    94250924 :     CHECK_NOT_NULL(broker->isolate()->handle_scope_data()->canonical_scope);
      73    94250924 :   }
      74             : 
      75             : #define DECLARE_IS_AND_AS(Name) \
      76             :   bool Is##Name() const;        \
      77             :   Name##Data* As##Name();
      78             :   HEAP_BROKER_OBJECT_LIST(DECLARE_IS_AND_AS)
      79             : #undef DECLARE_IS_AND_AS
      80             : 
      81             :   Handle<Object> object() const { return object_; }
      82             :   ObjectDataKind kind() const { return kind_; }
      83    12631612 :   bool is_smi() const { return kind_ == kSmi; }
      84             : 
      85             :  private:
      86             :   Handle<Object> const object_;
      87             :   ObjectDataKind const kind_;
      88             : };
      89             : 
      90             : class HeapObjectData : public ObjectData {
      91             :  public:
      92             :   HeapObjectData(JSHeapBroker* broker, ObjectData** storage,
      93             :                  Handle<HeapObject> object);
      94             : 
      95             :   bool boolean_value() const { return boolean_value_; }
      96             :   MapData* map() const { return map_; }
      97             : 
      98             :   static HeapObjectData* Serialize(JSHeapBroker* broker,
      99             :                                    Handle<HeapObject> object);
     100             : 
     101             :  private:
     102             :   bool const boolean_value_;
     103             :   MapData* const map_;
     104             : };
     105             : 
     106             : class PropertyCellData : public HeapObjectData {
     107             :  public:
     108             :   PropertyCellData(JSHeapBroker* broker, ObjectData** storage,
     109             :                    Handle<PropertyCell> object);
     110             : 
     111             :   PropertyDetails property_details() const { return property_details_; }
     112             : 
     113             :   void Serialize(JSHeapBroker* broker);
     114             :   ObjectData* value() const { return value_; }
     115             : 
     116             :  private:
     117             :   PropertyDetails const property_details_;
     118             : 
     119             :   bool serialized_ = false;
     120             :   ObjectData* value_ = nullptr;
     121             : };
     122             : 
     123             : class FunctionTemplateInfoData : public HeapObjectData {
     124             :  public:
     125             :   FunctionTemplateInfoData(JSHeapBroker* broker, ObjectData** storage,
     126             :                            Handle<FunctionTemplateInfo> object);
     127             : 
     128             :   void Serialize(JSHeapBroker* broker);
     129             :   ObjectData* call_code() const { return call_code_; }
     130             : 
     131             :  private:
     132             :   bool serialized_ = false;
     133             :   ObjectData* call_code_ = nullptr;
     134             : };
     135             : 
     136             : class CallHandlerInfoData : public HeapObjectData {
     137             :  public:
     138             :   CallHandlerInfoData(JSHeapBroker* broker, ObjectData** storage,
     139             :                       Handle<CallHandlerInfo> object);
     140             : 
     141             :   Address callback() const { return callback_; }
     142             : 
     143             :   void Serialize(JSHeapBroker* broker);
     144             :   ObjectData* data() const { return data_; }
     145             : 
     146             :  private:
     147             :   Address const callback_;
     148             : 
     149             :   bool serialized_ = false;
     150             :   ObjectData* data_ = nullptr;
     151             : };
     152             : 
     153         128 : FunctionTemplateInfoData::FunctionTemplateInfoData(
     154             :     JSHeapBroker* broker, ObjectData** storage,
     155             :     Handle<FunctionTemplateInfo> object)
     156         128 :     : HeapObjectData(broker, storage, object) {}
     157             : 
     158           0 : CallHandlerInfoData::CallHandlerInfoData(JSHeapBroker* broker,
     159             :                                          ObjectData** storage,
     160             :                                          Handle<CallHandlerInfo> object)
     161             :     : HeapObjectData(broker, storage, object),
     162           0 :       callback_(v8::ToCData<Address>(object->callback())) {}
     163             : 
     164    29200642 : void JSHeapBroker::IncrementTracingIndentation() { ++trace_indentation_; }
     165             : 
     166    29200774 : void JSHeapBroker::DecrementTracingIndentation() { --trace_indentation_; }
     167             : 
     168             : class TraceScope {
     169             :  public:
     170             :   TraceScope(JSHeapBroker* broker, const char* label)
     171      479036 :       : TraceScope(broker, static_cast<void*>(broker), label) {}
     172             : 
     173             :   TraceScope(JSHeapBroker* broker, ObjectData* data, const char* label)
     174    28721742 :       : TraceScope(broker, static_cast<void*>(data), label) {}
     175             : 
     176    58400037 :   ~TraceScope() { broker_->DecrementTracingIndentation(); }
     177             : 
     178             :  private:
     179             :   JSHeapBroker* const broker_;
     180             : 
     181    29200642 :   TraceScope(JSHeapBroker* broker, void* self, const char* label)
     182    29200642 :       : broker_(broker) {
     183    29200642 :     TRACE(broker_, "Running " << label << " on " << self);
     184    29200642 :     broker_->IncrementTracingIndentation();
     185    29200642 :   }
     186             : };
     187             : 
     188     3259151 : PropertyCellData::PropertyCellData(JSHeapBroker* broker, ObjectData** storage,
     189             :                                    Handle<PropertyCell> object)
     190             :     : HeapObjectData(broker, storage, object),
     191     6518296 :       property_details_(object->property_details()) {}
     192             : 
     193     3248788 : void PropertyCellData::Serialize(JSHeapBroker* broker) {
     194     3248788 :   if (serialized_) return;
     195     3248788 :   serialized_ = true;
     196             : 
     197     3248788 :   TraceScope tracer(broker, this, "PropertyCellData::Serialize");
     198             :   auto cell = Handle<PropertyCell>::cast(object());
     199             :   DCHECK_NULL(value_);
     200     3248789 :   value_ = broker->GetOrCreateData(cell->value());
     201             : }
     202             : 
     203           0 : void FunctionTemplateInfoData::Serialize(JSHeapBroker* broker) {
     204           0 :   if (serialized_) return;
     205           0 :   serialized_ = true;
     206             : 
     207           0 :   TraceScope tracer(broker, this, "FunctionTemplateInfoData::Serialize");
     208             :   auto function_template_info = Handle<FunctionTemplateInfo>::cast(object());
     209             :   DCHECK_NULL(call_code_);
     210           0 :   call_code_ = broker->GetOrCreateData(function_template_info->call_code());
     211             : 
     212           0 :   if (call_code_->IsCallHandlerInfo()) {
     213           0 :     call_code_->AsCallHandlerInfo()->Serialize(broker);
     214             :   }
     215             : }
     216             : 
     217           0 : void CallHandlerInfoData::Serialize(JSHeapBroker* broker) {
     218           0 :   if (serialized_) return;
     219           0 :   serialized_ = true;
     220             : 
     221           0 :   TraceScope tracer(broker, this, "CallHandlerInfoData::Serialize");
     222             :   auto call_handler_info = Handle<CallHandlerInfo>::cast(object());
     223             :   DCHECK_NULL(data_);
     224           0 :   data_ = broker->GetOrCreateData(call_handler_info->data());
     225             : }
     226             : 
     227             : class JSObjectField {
     228             :  public:
     229             :   bool IsDouble() const { return object_ == nullptr; }
     230             :   double AsDouble() const {
     231         128 :     CHECK(IsDouble());
     232         128 :     return number_;
     233             :   }
     234             : 
     235             :   bool IsObject() const { return object_ != nullptr; }
     236             :   ObjectData* AsObject() const {
     237        3202 :     CHECK(IsObject());
     238             :     return object_;
     239             :   }
     240             : 
     241         128 :   explicit JSObjectField(double value) : number_(value) {}
     242        2735 :   explicit JSObjectField(ObjectData* value) : object_(value) {}
     243             : 
     244             :  private:
     245             :   ObjectData* object_ = nullptr;
     246             :   double number_ = 0;
     247             : };
     248             : 
     249             : class JSObjectData : public HeapObjectData {
     250             :  public:
     251             :   JSObjectData(JSHeapBroker* broker, ObjectData** storage,
     252             :                Handle<JSObject> object);
     253             : 
     254             :   // Recursive serialization of all reachable JSObjects.
     255             :   void SerializeAsBoilerplate(JSHeapBroker* broker);
     256             :   const JSObjectField& GetInobjectField(int property_index) const;
     257             : 
     258             :   // Shallow serialization of {elements}.
     259             :   void SerializeElements(JSHeapBroker* broker);
     260             :   bool serialized_elements() const { return serialized_elements_; }
     261             :   FixedArrayBaseData* elements() const;
     262             : 
     263             :   void SerializeObjectCreateMap(JSHeapBroker* broker);
     264             :   MapData* object_create_map() const {  // Can be nullptr.
     265          16 :     CHECK(serialized_object_create_map_);
     266          16 :     return object_create_map_;
     267             :   }
     268             : 
     269             :   ObjectData* GetOwnConstantElement(JSHeapBroker* broker, uint32_t index,
     270             :                                     bool serialize);
     271             : 
     272             :   // This method is only used to assert our invariants.
     273             :   bool cow_or_empty_elements_tenured() const;
     274             : 
     275             :  private:
     276             :   void SerializeRecursive(JSHeapBroker* broker, int max_depths);
     277             : 
     278             :   FixedArrayBaseData* elements_ = nullptr;
     279             :   bool cow_or_empty_elements_tenured_ = false;
     280             :   // The {serialized_as_boilerplate} flag is set when all recursively
     281             :   // reachable JSObjects are serialized.
     282             :   bool serialized_as_boilerplate_ = false;
     283             :   bool serialized_elements_ = false;
     284             : 
     285             :   ZoneVector<JSObjectField> inobject_fields_;
     286             : 
     287             :   bool serialized_object_create_map_ = false;
     288             :   MapData* object_create_map_ = nullptr;
     289             : 
     290             :   // Elements (indexed properties) that either
     291             :   // (1) are known to exist directly on the object as non-writable and
     292             :   // non-configurable, or (2) are known not to (possibly they don't exist at
     293             :   // all). In case (2), the second pair component is nullptr.
     294             :   ZoneVector<std::pair<uint32_t, ObjectData*>> own_constant_elements_;
     295             : };
     296             : 
     297     1141482 : void JSObjectData::SerializeObjectCreateMap(JSHeapBroker* broker) {
     298     1663039 :   if (serialized_object_create_map_) return;
     299      619925 :   serialized_object_create_map_ = true;
     300             : 
     301      619925 :   TraceScope tracer(broker, this, "JSObjectData::SerializeObjectCreateMap");
     302             :   Handle<JSObject> jsobject = Handle<JSObject>::cast(object());
     303             : 
     304      619925 :   if (jsobject->map()->is_prototype_map()) {
     305             :     Handle<Object> maybe_proto_info(jsobject->map()->prototype_info(),
     306             :                                     broker->isolate());
     307       10482 :     if (maybe_proto_info->IsPrototypeInfo()) {
     308             :       auto proto_info = Handle<PrototypeInfo>::cast(maybe_proto_info);
     309        3301 :       if (proto_info->HasObjectCreateMap()) {
     310             :         DCHECK_NULL(object_create_map_);
     311             :         object_create_map_ =
     312          30 :             broker->GetOrCreateData(proto_info->ObjectCreateMap())->AsMap();
     313             :       }
     314             :     }
     315             :   }
     316             : }
     317             : 
     318             : namespace {
     319        1642 : base::Optional<ObjectRef> GetOwnElementFromHeap(JSHeapBroker* broker,
     320             :                                                 Handle<Object> receiver,
     321             :                                                 uint32_t index,
     322             :                                                 bool constant_only) {
     323        1642 :   LookupIterator it(broker->isolate(), receiver, index, LookupIterator::OWN);
     324        3284 :   if (it.state() == LookupIterator::DATA &&
     325        1399 :       (!constant_only || (it.IsReadOnly() && !it.IsConfigurable()))) {
     326         254 :     return ObjectRef(broker, it.GetDataValue());
     327             :   }
     328             :   return base::nullopt;
     329             : }
     330             : }  // namespace
     331             : 
     332           9 : ObjectData* JSObjectData::GetOwnConstantElement(JSHeapBroker* broker,
     333             :                                                 uint32_t index,
     334             :                                                 bool serialize) {
     335           9 :   for (auto const& p : own_constant_elements_) {
     336           0 :     if (p.first == index) return p.second;
     337             :   }
     338             : 
     339           9 :   if (!serialize) {
     340           9 :     TRACE_MISSING(broker, "knowledge about index " << index << " on " << this);
     341             :     return nullptr;
     342             :   }
     343             : 
     344             :   base::Optional<ObjectRef> element =
     345           0 :       GetOwnElementFromHeap(broker, object(), index, true);
     346           0 :   ObjectData* result = element.has_value() ? element->data() : nullptr;
     347           0 :   own_constant_elements_.push_back({index, result});
     348           0 :   return result;
     349             : }
     350             : 
     351             : class JSTypedArrayData : public JSObjectData {
     352             :  public:
     353             :   JSTypedArrayData(JSHeapBroker* broker, ObjectData** storage,
     354             :                    Handle<JSTypedArray> object);
     355             : 
     356             :   bool is_on_heap() const { return is_on_heap_; }
     357             :   size_t length() const { return length_; }
     358             :   void* elements_external_pointer() const { return elements_external_pointer_; }
     359             : 
     360             :   void Serialize(JSHeapBroker* broker);
     361             :   bool serialized() const { return serialized_; }
     362             : 
     363             :   HeapObjectData* buffer() const { return buffer_; }
     364             : 
     365             :  private:
     366             :   bool const is_on_heap_;
     367             :   size_t const length_;
     368             :   void* const elements_external_pointer_;
     369             : 
     370             :   bool serialized_ = false;
     371             :   HeapObjectData* buffer_ = nullptr;
     372             : };
     373             : 
     374         807 : JSTypedArrayData::JSTypedArrayData(JSHeapBroker* broker, ObjectData** storage,
     375             :                                    Handle<JSTypedArray> object)
     376             :     : JSObjectData(broker, storage, object),
     377             :       is_on_heap_(object->is_on_heap()),
     378             :       length_(object->length()),
     379             :       elements_external_pointer_(
     380        3228 :           FixedTypedArrayBase::cast(object->elements())->external_pointer()) {}
     381             : 
     382           0 : void JSTypedArrayData::Serialize(JSHeapBroker* broker) {
     383           0 :   if (serialized_) return;
     384           0 :   serialized_ = true;
     385             : 
     386           0 :   TraceScope tracer(broker, this, "JSTypedArrayData::Serialize");
     387             :   Handle<JSTypedArray> typed_array = Handle<JSTypedArray>::cast(object());
     388             : 
     389           0 :   if (!is_on_heap()) {
     390             :     DCHECK_NULL(buffer_);
     391           0 :     buffer_ = broker->GetOrCreateData(typed_array->buffer())->AsHeapObject();
     392             :   }
     393             : }
     394             : 
     395             : class JSDataViewData : public JSObjectData {
     396             :  public:
     397             :   JSDataViewData(JSHeapBroker* broker, ObjectData** storage,
     398             :                  Handle<JSDataView> object);
     399             : 
     400             :   size_t byte_length() const { return byte_length_; }
     401             :   size_t byte_offset() const { return byte_offset_; }
     402             : 
     403             :  private:
     404             :   size_t const byte_length_;
     405             :   size_t const byte_offset_;
     406             : };
     407             : 
     408             : class JSBoundFunctionData : public JSObjectData {
     409             :  public:
     410             :   JSBoundFunctionData(JSHeapBroker* broker, ObjectData** storage,
     411             :                       Handle<JSBoundFunction> object);
     412             : 
     413             :   void Serialize(JSHeapBroker* broker);
     414             : 
     415             :   ObjectData* bound_target_function() const { return bound_target_function_; }
     416             :   ObjectData* bound_this() const { return bound_this_; }
     417             :   FixedArrayData* bound_arguments() const { return bound_arguments_; }
     418             : 
     419             :  private:
     420             :   bool serialized_ = false;
     421             : 
     422             :   ObjectData* bound_target_function_ = nullptr;
     423             :   ObjectData* bound_this_ = nullptr;
     424             :   FixedArrayData* bound_arguments_ = nullptr;
     425             : };
     426             : 
     427             : class JSFunctionData : public JSObjectData {
     428             :  public:
     429             :   JSFunctionData(JSHeapBroker* broker, ObjectData** storage,
     430             :                  Handle<JSFunction> object);
     431             : 
     432             :   bool has_feedback_vector() const { return has_feedback_vector_; }
     433             :   bool has_initial_map() const { return has_initial_map_; }
     434             :   bool has_prototype() const { return has_prototype_; }
     435             :   bool PrototypeRequiresRuntimeLookup() const {
     436             :     return PrototypeRequiresRuntimeLookup_;
     437             :   }
     438             : 
     439             :   void Serialize(JSHeapBroker* broker);
     440             :   bool serialized() const { return serialized_; }
     441             : 
     442             :   ContextData* context() const { return context_; }
     443             :   NativeContextData* native_context() const { return native_context_; }
     444             :   MapData* initial_map() const { return initial_map_; }
     445             :   ObjectData* prototype() const { return prototype_; }
     446             :   SharedFunctionInfoData* shared() const { return shared_; }
     447             :   FeedbackVectorData* feedback_vector() const { return feedback_vector_; }
     448             :   int initial_map_instance_size_with_min_slack() const {
     449        5447 :     CHECK(serialized_);
     450        5447 :     return initial_map_instance_size_with_min_slack_;
     451             :   }
     452             : 
     453             :  private:
     454             :   bool has_feedback_vector_;
     455             :   bool has_initial_map_;
     456             :   bool has_prototype_;
     457             :   bool PrototypeRequiresRuntimeLookup_;
     458             : 
     459             :   bool serialized_ = false;
     460             : 
     461             :   ContextData* context_ = nullptr;
     462             :   NativeContextData* native_context_ = nullptr;
     463             :   MapData* initial_map_ = nullptr;
     464             :   ObjectData* prototype_ = nullptr;
     465             :   SharedFunctionInfoData* shared_ = nullptr;
     466             :   FeedbackVectorData* feedback_vector_ = nullptr;
     467             :   int initial_map_instance_size_with_min_slack_;
     468             : };
     469             : 
     470             : class JSRegExpData : public JSObjectData {
     471             :  public:
     472         640 :   JSRegExpData(JSHeapBroker* broker, ObjectData** storage,
     473             :                Handle<JSRegExp> object)
     474         640 :       : JSObjectData(broker, storage, object) {}
     475             : 
     476             :   void SerializeAsRegExpBoilerplate(JSHeapBroker* broker);
     477             : 
     478             :   ObjectData* raw_properties_or_hash() const { return raw_properties_or_hash_; }
     479             :   ObjectData* data() const { return data_; }
     480             :   ObjectData* source() const { return source_; }
     481             :   ObjectData* flags() const { return flags_; }
     482             :   ObjectData* last_index() const { return last_index_; }
     483             : 
     484             :  private:
     485             :   bool serialized_as_reg_exp_boilerplate_ = false;
     486             : 
     487             :   ObjectData* raw_properties_or_hash_ = nullptr;
     488             :   ObjectData* data_ = nullptr;
     489             :   ObjectData* source_ = nullptr;
     490             :   ObjectData* flags_ = nullptr;
     491             :   ObjectData* last_index_ = nullptr;
     492             : };
     493             : 
     494             : class HeapNumberData : public HeapObjectData {
     495             :  public:
     496      464238 :   HeapNumberData(JSHeapBroker* broker, ObjectData** storage,
     497             :                  Handle<HeapNumber> object)
     498      928477 :       : HeapObjectData(broker, storage, object), value_(object->value()) {}
     499             : 
     500             :   double value() const { return value_; }
     501             : 
     502             :  private:
     503             :   double const value_;
     504             : };
     505             : 
     506             : class MutableHeapNumberData : public HeapObjectData {
     507             :  public:
     508           0 :   MutableHeapNumberData(JSHeapBroker* broker, ObjectData** storage,
     509             :                         Handle<MutableHeapNumber> object)
     510           0 :       : HeapObjectData(broker, storage, object), value_(object->value()) {}
     511             : 
     512             :   double value() const { return value_; }
     513             : 
     514             :  private:
     515             :   double const value_;
     516             : };
     517             : 
     518             : class ContextData : public HeapObjectData {
     519             :  public:
     520             :   ContextData(JSHeapBroker* broker, ObjectData** storage,
     521             :               Handle<Context> object);
     522             :   void SerializeContextChain(JSHeapBroker* broker);
     523             : 
     524             :   ContextData* previous() const {
     525           0 :     CHECK(serialized_context_chain_);
     526           0 :     return previous_;
     527             :   }
     528             : 
     529             :   void SerializeSlot(JSHeapBroker* broker, int index);
     530             : 
     531          16 :   ObjectData* GetSlot(int index) {
     532             :     auto search = slots_.find(index);
     533          16 :     CHECK(search != slots_.end());
     534          16 :     return search->second;
     535             :   }
     536             : 
     537             :  private:
     538             :   ZoneMap<int, ObjectData*> slots_;
     539             :   bool serialized_context_chain_ = false;
     540             :   ContextData* previous_ = nullptr;
     541             : };
     542             : 
     543      196035 : ContextData::ContextData(JSHeapBroker* broker, ObjectData** storage,
     544             :                          Handle<Context> object)
     545     1320308 :     : HeapObjectData(broker, storage, object), slots_(broker->zone()) {}
     546             : 
     547     1178736 : void ContextData::SerializeContextChain(JSHeapBroker* broker) {
     548     1798870 :   if (serialized_context_chain_) return;
     549      558602 :   serialized_context_chain_ = true;
     550             : 
     551      558602 :   TraceScope tracer(broker, this, "ContextData::SerializeContextChain");
     552             :   Handle<Context> context = Handle<Context>::cast(object());
     553             : 
     554             :   DCHECK_NULL(previous_);
     555             :   // Context::previous DCHECK-fails when called on the native context.
     556      558603 :   if (!context->IsNativeContext()) {
     557       94489 :     previous_ = broker->GetOrCreateData(context->previous())->AsContext();
     558       94489 :     previous_->SerializeContextChain(broker);
     559             :   }
     560             : }
     561             : 
     562          16 : void ContextData::SerializeSlot(JSHeapBroker* broker, int index) {
     563          16 :   TraceScope tracer(broker, this, "ContextData::SerializeSlot");
     564          16 :   TRACE(broker, "Serializing script context slot " << index);
     565             :   Handle<Context> context = Handle<Context>::cast(object());
     566          32 :   CHECK(index >= 0 && index < context->length());
     567          16 :   ObjectData* odata = broker->GetOrCreateData(context->get(index));
     568          32 :   slots_.insert(std::make_pair(index, odata));
     569          16 : }
     570             : 
     571             : class NativeContextData : public ContextData {
     572             :  public:
     573             : #define DECL_ACCESSOR(type, name) \
     574             :   type##Data* name() const { return name##_; }
     575             :   BROKER_NATIVE_CONTEXT_FIELDS(DECL_ACCESSOR)
     576             : #undef DECL_ACCESSOR
     577             : 
     578             :   const ZoneVector<MapData*>& function_maps() const {
     579       32152 :     CHECK(serialized_);
     580             :     return function_maps_;
     581             :   }
     582             : 
     583             :   NativeContextData(JSHeapBroker* broker, ObjectData** storage,
     584             :                     Handle<NativeContext> object);
     585             :   void Serialize(JSHeapBroker* broker);
     586             : 
     587             :  private:
     588             :   bool serialized_ = false;
     589             : #define DECL_MEMBER(type, name) type##Data* name##_ = nullptr;
     590             :   BROKER_NATIVE_CONTEXT_FIELDS(DECL_MEMBER)
     591             : #undef DECL_MEMBER
     592             :   ZoneVector<MapData*> function_maps_;
     593             : };
     594             : 
     595             : class NameData : public HeapObjectData {
     596             :  public:
     597           0 :   NameData(JSHeapBroker* broker, ObjectData** storage, Handle<Name> object)
     598     7652765 :       : HeapObjectData(broker, storage, object) {}
     599             : };
     600             : 
     601             : class StringData : public NameData {
     602             :  public:
     603             :   StringData(JSHeapBroker* broker, ObjectData** storage, Handle<String> object);
     604             : 
     605             :   int length() const { return length_; }
     606             :   uint16_t first_char() const { return first_char_; }
     607         842 :   base::Optional<double> to_number() const { return to_number_; }
     608             :   bool is_external_string() const { return is_external_string_; }
     609             :   bool is_seq_string() const { return is_seq_string_; }
     610             : 
     611             :   StringData* GetCharAsString(JSHeapBroker* broker, uint32_t index,
     612             :                               bool serialize);
     613             : 
     614             :  private:
     615             :   int const length_;
     616             :   uint16_t const first_char_;
     617             :   base::Optional<double> to_number_;
     618             :   bool const is_external_string_;
     619             :   bool const is_seq_string_;
     620             : 
     621             :   // Known individual characters as strings, corresponding to the semantics of
     622             :   // element access (s[i]). The first pair component is always less than
     623             :   // {length_}. The second component is never nullptr.
     624             :   ZoneVector<std::pair<uint32_t, StringData*>> chars_as_strings_;
     625             : 
     626             :   static constexpr int kMaxLengthForDoubleConversion = 23;
     627             : };
     628             : 
     629             : class SymbolData : public NameData {
     630             :  public:
     631       36686 :   SymbolData(JSHeapBroker* broker, ObjectData** storage, Handle<Symbol> object)
     632       36686 :       : NameData(broker, storage, object) {}
     633             : };
     634             : 
     635     7616079 : StringData::StringData(JSHeapBroker* broker, ObjectData** storage,
     636             :                        Handle<String> object)
     637             :     : NameData(broker, storage, object),
     638             :       length_(object->length()),
     639             :       first_char_(length_ > 0 ? object->Get(0) : 0),
     640             :       is_external_string_(object->IsExternalString()),
     641             :       is_seq_string_(object->IsSeqString()),
     642    30464296 :       chars_as_strings_(broker->zone()) {
     643             :   int flags = ALLOW_HEX | ALLOW_OCTAL | ALLOW_BINARY;
     644     7616074 :   if (length_ <= kMaxLengthForDoubleConversion) {
     645     7568235 :     to_number_ = StringToDouble(broker->isolate(), object, flags);
     646             :   }
     647     7616073 : }
     648             : 
     649             : class InternalizedStringData : public StringData {
     650             :  public:
     651             :   InternalizedStringData(JSHeapBroker* broker, ObjectData** storage,
     652             :                          Handle<InternalizedString> object);
     653             : 
     654             :   uint32_t array_index() const { return array_index_; }
     655             : 
     656             :  private:
     657             :   uint32_t array_index_;
     658             : };
     659             : 
     660           0 : StringData* StringData::GetCharAsString(JSHeapBroker* broker, uint32_t index,
     661             :                                         bool serialize) {
     662           0 :   if (index >= static_cast<uint32_t>(length())) return nullptr;
     663             : 
     664           0 :   for (auto const& p : chars_as_strings_) {
     665           0 :     if (p.first == index) return p.second;
     666             :   }
     667             : 
     668           0 :   if (!serialize) {
     669           0 :     TRACE_MISSING(broker, "knowledge about index " << index << " on " << this);
     670             :     return nullptr;
     671             :   }
     672             : 
     673             :   base::Optional<ObjectRef> element =
     674           0 :       GetOwnElementFromHeap(broker, object(), index, true);
     675             :   StringData* result =
     676           0 :       element.has_value() ? element->data()->AsString() : nullptr;
     677           0 :   chars_as_strings_.push_back({index, result});
     678           0 :   return result;
     679             : }
     680             : 
     681     7615741 : InternalizedStringData::InternalizedStringData(
     682             :     JSHeapBroker* broker, ObjectData** storage,
     683             :     Handle<InternalizedString> object)
     684     7615741 :     : StringData(broker, storage, object) {}
     685             : 
     686             : namespace {
     687             : 
     688        7191 : bool IsFastLiteralHelper(Handle<JSObject> boilerplate, int max_depth,
     689             :                          int* max_properties) {
     690             :   DCHECK_GE(max_depth, 0);
     691             :   DCHECK_GE(*max_properties, 0);
     692             : 
     693             :   // Make sure the boilerplate map is not deprecated.
     694        7191 :   if (!JSObject::TryMigrateInstance(boilerplate)) return false;
     695             : 
     696             :   // Check for too deep nesting.
     697        7191 :   if (max_depth == 0) return false;
     698             : 
     699             :   // Check the elements.
     700             :   Isolate* const isolate = boilerplate->GetIsolate();
     701             :   Handle<FixedArrayBase> elements(boilerplate->elements(), isolate);
     702       11697 :   if (elements->length() > 0 &&
     703             :       elements->map() != ReadOnlyRoots(isolate).fixed_cow_array_map()) {
     704        2445 :     if (boilerplate->HasSmiOrObjectElements()) {
     705             :       Handle<FixedArray> fast_elements = Handle<FixedArray>::cast(elements);
     706             :       int length = elements->length();
     707       24618 :       for (int i = 0; i < length; i++) {
     708       11392 :         if ((*max_properties)-- == 0) return false;
     709             :         Handle<Object> value(fast_elements->get(i), isolate);
     710       11378 :         if (value->IsJSObject()) {
     711         700 :           Handle<JSObject> value_object = Handle<JSObject>::cast(value);
     712         700 :           if (!IsFastLiteralHelper(value_object, max_depth - 1,
     713             :                                    max_properties)) {
     714           0 :             return false;
     715             :           }
     716             :         }
     717             :       }
     718         583 :     } else if (boilerplate->HasDoubleElements()) {
     719         547 :       if (elements->Size() > kMaxRegularHeapObjectSize) return false;
     720             :     } else {
     721             :       return false;
     722             :     }
     723             :   }
     724             : 
     725             :   // TODO(turbofan): Do we want to support out-of-object properties?
     726       14268 :   if (!(boilerplate->HasFastProperties() &&
     727       21238 :         boilerplate->property_array()->length() == 0)) {
     728             :     return false;
     729             :   }
     730             : 
     731             :   // Check the in-object properties.
     732             :   Handle<DescriptorArray> descriptors(
     733             :       boilerplate->map()->instance_descriptors(), isolate);
     734             :   int limit = boilerplate->map()->NumberOfOwnDescriptors();
     735       21718 :   for (int i = 0; i < limit; i++) {
     736        7340 :     PropertyDetails details = descriptors->GetDetails(i);
     737       11938 :     if (details.location() != kField) continue;
     738             :     DCHECK_EQ(kData, details.kind());
     739        2877 :     if ((*max_properties)-- == 0) return false;
     740        2870 :     FieldIndex field_index = FieldIndex::ForDescriptor(boilerplate->map(), i);
     741        2870 :     if (boilerplate->IsUnboxedDoubleField(field_index)) continue;
     742        5484 :     Handle<Object> value(boilerplate->RawFastPropertyAt(field_index), isolate);
     743        2742 :     if (value->IsJSObject()) {
     744         291 :       Handle<JSObject> value_object = Handle<JSObject>::cast(value);
     745         291 :       if (!IsFastLiteralHelper(value_object, max_depth - 1, max_properties)) {
     746           7 :         return false;
     747             :       }
     748             :     }
     749             :   }
     750             :   return true;
     751             : }
     752             : 
     753             : // Maximum depth and total number of elements and properties for literal
     754             : // graphs to be considered for fast deep-copying. The limit is chosen to
     755             : // match the maximum number of inobject properties, to ensure that the
     756             : // performance of using object literals is not worse than using constructor
     757             : // functions, see crbug.com/v8/6211 for details.
     758             : const int kMaxFastLiteralDepth = 3;
     759             : const int kMaxFastLiteralProperties = JSObject::kMaxInObjectProperties;
     760             : 
     761             : // Determines whether the given array or object literal boilerplate satisfies
     762             : // all limits to be considered for fast deep-copying and computes the total
     763             : // size of all objects that are part of the graph.
     764             : bool IsInlinableFastLiteral(Handle<JSObject> boilerplate) {
     765        6200 :   int max_properties = kMaxFastLiteralProperties;
     766             :   return IsFastLiteralHelper(boilerplate, kMaxFastLiteralDepth,
     767        6200 :                              &max_properties);
     768             : }
     769             : 
     770             : }  // namespace
     771             : 
     772             : class AllocationSiteData : public HeapObjectData {
     773             :  public:
     774             :   AllocationSiteData(JSHeapBroker* broker, ObjectData** storage,
     775             :                      Handle<AllocationSite> object);
     776             :   void SerializeBoilerplate(JSHeapBroker* broker);
     777             : 
     778             :   bool PointsToLiteral() const { return PointsToLiteral_; }
     779             :   AllocationType GetAllocationType() const { return GetAllocationType_; }
     780             :   ObjectData* nested_site() const { return nested_site_; }
     781             :   bool IsFastLiteral() const { return IsFastLiteral_; }
     782             :   JSObjectData* boilerplate() const { return boilerplate_; }
     783             : 
     784             :   // These are only valid if PointsToLiteral is false.
     785             :   ElementsKind GetElementsKind() const { return GetElementsKind_; }
     786             :   bool CanInlineCall() const { return CanInlineCall_; }
     787             : 
     788             :  private:
     789             :   bool const PointsToLiteral_;
     790             :   AllocationType const GetAllocationType_;
     791             :   ObjectData* nested_site_ = nullptr;
     792             :   bool IsFastLiteral_ = false;
     793             :   JSObjectData* boilerplate_ = nullptr;
     794             :   ElementsKind GetElementsKind_ = NO_ELEMENTS;
     795             :   bool CanInlineCall_ = false;
     796             :   bool serialized_boilerplate_ = false;
     797             : };
     798             : 
     799             : // Only used in JSNativeContextSpecialization.
     800             : class ScriptContextTableData : public HeapObjectData {
     801             :  public:
     802      464113 :   ScriptContextTableData(JSHeapBroker* broker, ObjectData** storage,
     803             :                          Handle<ScriptContextTable> object)
     804      464113 :       : HeapObjectData(broker, storage, object) {}
     805             : };
     806             : 
     807        8842 : struct PropertyDescriptor {
     808             :   NameData* key = nullptr;
     809             :   PropertyDetails details = PropertyDetails::Empty();
     810             :   FieldIndex field_index;
     811             :   MapData* field_owner = nullptr;
     812             :   ObjectData* field_type = nullptr;
     813             :   bool is_unboxed_double_field = false;
     814             : };
     815             : 
     816             : class MapData : public HeapObjectData {
     817             :  public:
     818             :   MapData(JSHeapBroker* broker, ObjectData** storage, Handle<Map> object);
     819             : 
     820             :   InstanceType instance_type() const { return instance_type_; }
     821             :   int instance_size() const { return instance_size_; }
     822             :   byte bit_field() const { return bit_field_; }
     823             :   byte bit_field2() const { return bit_field2_; }
     824             :   uint32_t bit_field3() const { return bit_field3_; }
     825             :   bool can_be_deprecated() const { return can_be_deprecated_; }
     826             :   bool can_transition() const { return can_transition_; }
     827             :   int in_object_properties_start_in_words() const {
     828       40981 :     CHECK(InstanceTypeChecker::IsJSObject(instance_type()));
     829       40981 :     return in_object_properties_start_in_words_;
     830             :   }
     831             :   int in_object_properties() const {
     832       76778 :     CHECK(InstanceTypeChecker::IsJSObject(instance_type()));
     833       76778 :     return in_object_properties_;
     834             :   }
     835             :   int constructor_function_index() const { return constructor_function_index_; }
     836             :   int NextFreePropertyIndex() const { return next_free_property_index_; }
     837             :   int UnusedPropertyFields() const { return unused_property_fields_; }
     838             :   bool supports_fast_array_iteration() const {
     839             :     return supports_fast_array_iteration_;
     840             :   }
     841             :   bool supports_fast_array_resize() const {
     842             :     return supports_fast_array_resize_;
     843             :   }
     844             :   bool IsMapOfCurrentGlobalProxy() const {
     845             :     return is_map_of_current_global_proxy_;
     846             :   }
     847             : 
     848             :   // Extra information.
     849             : 
     850             :   void SerializeElementsKindGeneralizations(JSHeapBroker* broker);
     851             :   const ZoneVector<MapData*>& elements_kind_generalizations() const {
     852        1098 :     CHECK(serialized_elements_kind_generalizations_);
     853             :     return elements_kind_generalizations_;
     854             :   }
     855             : 
     856             :   // Serialize the own part of the descriptor array and, recursively, that of
     857             :   // any field owner.
     858             :   void SerializeOwnDescriptors(JSHeapBroker* broker);
     859             :   DescriptorArrayData* instance_descriptors() const {
     860       17627 :     CHECK(serialized_own_descriptors_);
     861       17627 :     return instance_descriptors_;
     862             :   }
     863             : 
     864             :   void SerializeConstructor(JSHeapBroker* broker);
     865             :   ObjectData* GetConstructor() const {
     866        4942 :     CHECK(serialized_constructor_);
     867        4942 :     return constructor_;
     868             :   }
     869             : 
     870             :   void SerializeBackPointer(JSHeapBroker* broker);
     871             :   HeapObjectData* GetBackPointer() const {
     872           0 :     CHECK(serialized_backpointer_);
     873           0 :     return backpointer_;
     874             :   }
     875             : 
     876             :   void SerializePrototype(JSHeapBroker* broker);
     877             :   bool serialized_prototype() const { return serialized_prototype_; }
     878             :   ObjectData* prototype() const {
     879          50 :     CHECK(serialized_prototype_);
     880          50 :     return prototype_;
     881             :   }
     882             : 
     883             :   void SerializeForElementLoad(JSHeapBroker* broker);
     884             : 
     885             :   void SerializeForElementStore(JSHeapBroker* broker);
     886             : 
     887             :  private:
     888             :   InstanceType const instance_type_;
     889             :   int const instance_size_;
     890             :   byte const bit_field_;
     891             :   byte const bit_field2_;
     892             :   uint32_t const bit_field3_;
     893             :   bool const can_be_deprecated_;
     894             :   bool const can_transition_;
     895             :   int const in_object_properties_start_in_words_;
     896             :   int const in_object_properties_;
     897             :   int const constructor_function_index_;
     898             :   int const next_free_property_index_;
     899             :   int const unused_property_fields_;
     900             :   bool const supports_fast_array_iteration_;
     901             :   bool const supports_fast_array_resize_;
     902             :   bool const is_map_of_current_global_proxy_;
     903             : 
     904             :   bool serialized_elements_kind_generalizations_ = false;
     905             :   ZoneVector<MapData*> elements_kind_generalizations_;
     906             : 
     907             :   bool serialized_own_descriptors_ = false;
     908             :   DescriptorArrayData* instance_descriptors_ = nullptr;
     909             : 
     910             :   bool serialized_constructor_ = false;
     911             :   ObjectData* constructor_ = nullptr;
     912             : 
     913             :   bool serialized_backpointer_ = false;
     914             :   HeapObjectData* backpointer_ = nullptr;
     915             : 
     916             :   bool serialized_prototype_ = false;
     917             :   ObjectData* prototype_ = nullptr;
     918             : 
     919             :   bool serialized_for_element_load_ = false;
     920             : 
     921             :   bool serialized_for_element_store_ = false;
     922             : };
     923             : 
     924        7696 : AllocationSiteData::AllocationSiteData(JSHeapBroker* broker,
     925             :                                        ObjectData** storage,
     926             :                                        Handle<AllocationSite> object)
     927             :     : HeapObjectData(broker, storage, object),
     928             :       PointsToLiteral_(object->PointsToLiteral()),
     929       23088 :       GetAllocationType_(object->GetAllocationType()) {
     930        7696 :   if (PointsToLiteral_) {
     931             :     IsFastLiteral_ = IsInlinableFastLiteral(
     932        6200 :         handle(object->boilerplate(), broker->isolate()));
     933             :   } else {
     934        1496 :     GetElementsKind_ = object->GetElementsKind();
     935        1496 :     CanInlineCall_ = object->CanInlineCall();
     936             :   }
     937        7696 : }
     938             : 
     939        6061 : void AllocationSiteData::SerializeBoilerplate(JSHeapBroker* broker) {
     940        6061 :   if (serialized_boilerplate_) return;
     941        6061 :   serialized_boilerplate_ = true;
     942             : 
     943        6061 :   TraceScope tracer(broker, this, "AllocationSiteData::SerializeBoilerplate");
     944             :   Handle<AllocationSite> site = Handle<AllocationSite>::cast(object());
     945             : 
     946        6061 :   CHECK(IsFastLiteral_);
     947             :   DCHECK_NULL(boilerplate_);
     948        6061 :   boilerplate_ = broker->GetOrCreateData(site->boilerplate())->AsJSObject();
     949             :   boilerplate_->SerializeAsBoilerplate(broker);
     950             : 
     951             :   DCHECK_NULL(nested_site_);
     952        6061 :   nested_site_ = broker->GetOrCreateData(site->nested_site());
     953        6061 :   if (nested_site_->IsAllocationSite()) {
     954         227 :     nested_site_->AsAllocationSite()->SerializeBoilerplate(broker);
     955             :   }
     956             : }
     957             : 
     958    91729391 : HeapObjectData::HeapObjectData(JSHeapBroker* broker, ObjectData** storage,
     959             :                                Handle<HeapObject> object)
     960             :     : ObjectData(broker, storage, object, kSerializedHeapObject),
     961   183458062 :       boolean_value_(object->BooleanValue(broker->isolate())),
     962             :       // We have to use a raw cast below instead of AsMap() because of
     963             :       // recursion. AsMap() would call IsMap(), which accesses the
     964             :       // instance_type_ member. In the case of constructing the MapData for the
     965             :       // meta map (whose map is itself), this member has not yet been
     966             :       // initialized.
     967   275187181 :       map_(static_cast<MapData*>(broker->GetOrCreateData(object->map()))) {
     968    91728926 :   CHECK(broker->SerializingAllowed());
     969    91728926 : }
     970             : 
     971             : namespace {
     972     2762518 : bool IsReadOnlyLengthDescriptor(Isolate* isolate, Handle<Map> jsarray_map) {
     973             :   DCHECK(!jsarray_map->is_dictionary_map());
     974             :   Handle<Name> length_string = isolate->factory()->length_string();
     975     2762518 :   DescriptorArray descriptors = jsarray_map->instance_descriptors();
     976             :   int number = descriptors->Search(*length_string, *jsarray_map);
     977             :   DCHECK_NE(DescriptorArray::kNotFound, number);
     978     5525036 :   return descriptors->GetDetails(number).IsReadOnly();
     979             : }
     980             : 
     981    96357755 : bool SupportsFastArrayIteration(Isolate* isolate, Handle<Map> map) {
     982     6517055 :   return map->instance_type() == JS_ARRAY_TYPE &&
     983     6514065 :          IsFastElementsKind(map->elements_kind()) &&
     984     5578936 :          map->prototype()->IsJSArray() &&
     985     5578939 :          isolate->IsAnyInitialArrayPrototype(
     986   101936327 :              handle(JSArray::cast(map->prototype()), isolate)) &&
     987   101936322 :          isolate->IsNoElementsProtectorIntact();
     988             : }
     989             : 
     990    48178618 : bool SupportsFastArrayResize(Isolate* isolate, Handle<Map> map) {
     991    53703660 :   return SupportsFastArrayIteration(isolate, map) && map->is_extensible() &&
     992    50941053 :          !map->is_dictionary_map() && !IsReadOnlyLengthDescriptor(isolate, map);
     993             : }
     994             : }  // namespace
     995             : 
     996    48175462 : MapData::MapData(JSHeapBroker* broker, ObjectData** storage, Handle<Map> object)
     997             :     : HeapObjectData(broker, storage, object),
     998             :       instance_type_(object->instance_type()),
     999             :       instance_size_(object->instance_size()),
    1000             :       bit_field_(object->bit_field()),
    1001             :       bit_field2_(object->bit_field2()),
    1002             :       bit_field3_(object->bit_field3()),
    1003             :       can_be_deprecated_(object->NumberOfOwnDescriptors() > 0
    1004    73349248 :                              ? object->CanBeDeprecated()
    1005             :                              : false),
    1006             :       can_transition_(object->CanTransition()),
    1007             :       in_object_properties_start_in_words_(
    1008             :           object->IsJSObjectMap() ? object->GetInObjectPropertiesStartInWords()
    1009             :                                   : 0),
    1010             :       in_object_properties_(
    1011    80795075 :           object->IsJSObjectMap() ? object->GetInObjectProperties() : 0),
    1012             :       constructor_function_index_(object->IsPrimitiveMap()
    1013             :                                       ? object->GetConstructorFunctionIndex()
    1014             :                                       : Map::kNoConstructorFunctionIndex),
    1015    96350691 :       next_free_property_index_(object->NextFreePropertyIndex()),
    1016    96350595 :       unused_property_fields_(object->UnusedPropertyFields()),
    1017             :       supports_fast_array_iteration_(
    1018    48175298 :           SupportsFastArrayIteration(broker->isolate(), object)),
    1019             :       supports_fast_array_resize_(
    1020    48175256 :           SupportsFastArrayResize(broker->isolate(), object)),
    1021             :       is_map_of_current_global_proxy_(
    1022   144525454 :           object->IsMapOfGlobalProxy(broker->isolate()->native_context())),
    1023  1021298892 :       elements_kind_generalizations_(broker->zone()) {}
    1024             : 
    1025     7504016 : JSFunctionData::JSFunctionData(JSHeapBroker* broker, ObjectData** storage,
    1026             :                                Handle<JSFunction> object)
    1027             :     : JSObjectData(broker, storage, object),
    1028    15008035 :       has_feedback_vector_(object->has_feedback_vector()),
    1029    21471566 :       has_initial_map_(object->has_prototype_slot() &&
    1030    13967541 :                        object->has_initial_map()),
    1031    21471561 :       has_prototype_(object->has_prototype_slot() && object->has_prototype()),
    1032             :       PrototypeRequiresRuntimeLookup_(
    1033    37520102 :           object->PrototypeRequiresRuntimeLookup()) {}
    1034             : 
    1035     5217786 : void JSFunctionData::Serialize(JSHeapBroker* broker) {
    1036     5714886 :   if (serialized_) return;
    1037     4720686 :   serialized_ = true;
    1038             : 
    1039     4720686 :   TraceScope tracer(broker, this, "JSFunctionData::Serialize");
    1040             :   Handle<JSFunction> function = Handle<JSFunction>::cast(object());
    1041             : 
    1042             :   DCHECK_NULL(context_);
    1043             :   DCHECK_NULL(native_context_);
    1044             :   DCHECK_NULL(initial_map_);
    1045             :   DCHECK_NULL(prototype_);
    1046             :   DCHECK_NULL(shared_);
    1047             :   DCHECK_NULL(feedback_vector_);
    1048             : 
    1049     4720687 :   context_ = broker->GetOrCreateData(function->context())->AsContext();
    1050             :   native_context_ =
    1051     4720679 :       broker->GetOrCreateData(function->native_context())->AsNativeContext();
    1052     4720679 :   shared_ = broker->GetOrCreateData(function->shared())->AsSharedFunctionInfo();
    1053             :   feedback_vector_ = has_feedback_vector()
    1054      471135 :                          ? broker->GetOrCreateData(function->feedback_vector())
    1055      471135 :                                ->AsFeedbackVector()
    1056     5191816 :                          : nullptr;
    1057             :   initial_map_ = has_initial_map()
    1058     3724898 :                      ? broker->GetOrCreateData(function->initial_map())->AsMap()
    1059     8445582 :                      : nullptr;
    1060    12176522 :   prototype_ = has_prototype() ? broker->GetOrCreateData(function->prototype())
    1061     9441372 :                                : nullptr;
    1062             : 
    1063     4720679 :   if (initial_map_ != nullptr) {
    1064             :     initial_map_instance_size_with_min_slack_ =
    1065     3724890 :         function->ComputeInstanceSizeWithMinSlack(broker->isolate());
    1066     3724897 :     if (initial_map_->instance_type() == JS_ARRAY_TYPE) {
    1067      464698 :       initial_map_->SerializeElementsKindGeneralizations(broker);
    1068             :     }
    1069     3724897 :     initial_map_->SerializeConstructor(broker);
    1070             :     // TODO(neis): This is currently only needed for native_context's
    1071             :     // object_function, as used by GetObjectCreateMap. If no further use sites
    1072             :     // show up, we should move this into NativeContextData::Serialize.
    1073     3724899 :     initial_map_->SerializePrototype(broker);
    1074             :   }
    1075             : }
    1076             : 
    1077      464698 : void MapData::SerializeElementsKindGeneralizations(JSHeapBroker* broker) {
    1078      464698 :   if (serialized_elements_kind_generalizations_) return;
    1079      464698 :   serialized_elements_kind_generalizations_ = true;
    1080             : 
    1081             :   TraceScope tracer(broker, this,
    1082      464698 :                     "MapData::SerializeElementsKindGeneralizations");
    1083             :   DCHECK_EQ(instance_type(), JS_ARRAY_TYPE);
    1084             :   MapRef self(broker, this);
    1085      464696 :   ElementsKind from_kind = self.elements_kind();
    1086             :   DCHECK(elements_kind_generalizations_.empty());
    1087     6041066 :   for (int i = FIRST_FAST_ELEMENTS_KIND; i <= LAST_FAST_ELEMENTS_KIND; i++) {
    1088             :     ElementsKind to_kind = static_cast<ElementsKind>(i);
    1089     2788185 :     if (IsMoreGeneralElementsKindTransition(from_kind, to_kind)) {
    1090             :       Handle<Map> target =
    1091     2323488 :           Map::AsElementsKind(broker->isolate(), self.object(), to_kind);
    1092     4646970 :       elements_kind_generalizations_.push_back(
    1093     4646968 :           broker->GetOrCreateData(target)->AsMap());
    1094             :     }
    1095             :   }
    1096             : }
    1097             : 
    1098             : class DescriptorArrayData : public HeapObjectData {
    1099             :  public:
    1100        4198 :   DescriptorArrayData(JSHeapBroker* broker, ObjectData** storage,
    1101             :                       Handle<DescriptorArray> object)
    1102        8396 :       : HeapObjectData(broker, storage, object), contents_(broker->zone()) {}
    1103             : 
    1104             :   ZoneVector<PropertyDescriptor>& contents() { return contents_; }
    1105             : 
    1106             :  private:
    1107             :   ZoneVector<PropertyDescriptor> contents_;
    1108             : };
    1109             : 
    1110             : class FeedbackVectorData : public HeapObjectData {
    1111             :  public:
    1112             :   const ZoneVector<ObjectData*>& feedback() { return feedback_; }
    1113             : 
    1114             :   FeedbackVectorData(JSHeapBroker* broker, ObjectData** storage,
    1115             :                      Handle<FeedbackVector> object);
    1116             : 
    1117             :   void SerializeSlots(JSHeapBroker* broker);
    1118             : 
    1119             :  private:
    1120             :   bool serialized_ = false;
    1121             :   ZoneVector<ObjectData*> feedback_;
    1122             : };
    1123             : 
    1124      471712 : FeedbackVectorData::FeedbackVectorData(JSHeapBroker* broker,
    1125             :                                        ObjectData** storage,
    1126             :                                        Handle<FeedbackVector> object)
    1127      943425 :     : HeapObjectData(broker, storage, object), feedback_(broker->zone()) {}
    1128             : 
    1129       53205 : void FeedbackVectorData::SerializeSlots(JSHeapBroker* broker) {
    1130       71610 :   if (serialized_) return;
    1131       34800 :   serialized_ = true;
    1132             : 
    1133       34800 :   TraceScope tracer(broker, this, "FeedbackVectorData::SerializeSlots");
    1134             :   Handle<FeedbackVector> vector = Handle<FeedbackVector>::cast(object());
    1135             :   DCHECK(feedback_.empty());
    1136       34800 :   feedback_.reserve(vector->length());
    1137     1369948 :   for (int i = 0; i < vector->length(); ++i) {
    1138             :     MaybeObject value = vector->get(i);
    1139             :     ObjectData* slot_value =
    1140             :         value->IsObject() ? broker->GetOrCreateData(value->cast<Object>())
    1141      667574 :                           : nullptr;
    1142      667575 :     feedback_.push_back(slot_value);
    1143      768483 :     if (slot_value == nullptr) continue;
    1144             : 
    1145      573675 :     if (slot_value->IsAllocationSite() &&
    1146        7008 :         slot_value->AsAllocationSite()->IsFastLiteral()) {
    1147        5834 :       slot_value->AsAllocationSite()->SerializeBoilerplate(broker);
    1148      560833 :     } else if (slot_value->IsJSRegExp()) {
    1149         492 :       slot_value->AsJSRegExp()->SerializeAsRegExpBoilerplate(broker);
    1150             :     }
    1151             :   }
    1152             :   DCHECK_EQ(vector->length(), feedback_.size());
    1153       34800 :   TRACE(broker, "Copied " << feedback_.size() << " slots");
    1154             : }
    1155             : 
    1156             : class FixedArrayBaseData : public HeapObjectData {
    1157             :  public:
    1158           0 :   FixedArrayBaseData(JSHeapBroker* broker, ObjectData** storage,
    1159             :                      Handle<FixedArrayBase> object)
    1160     2259155 :       : HeapObjectData(broker, storage, object), length_(object->length()) {}
    1161             : 
    1162             :   int length() const { return length_; }
    1163             : 
    1164             :  private:
    1165             :   int const length_;
    1166             : };
    1167             : 
    1168             : class FixedArrayData : public FixedArrayBaseData {
    1169             :  public:
    1170             :   FixedArrayData(JSHeapBroker* broker, ObjectData** storage,
    1171             :                  Handle<FixedArray> object);
    1172             : 
    1173             :   // Creates all elements of the fixed array.
    1174             :   void SerializeContents(JSHeapBroker* broker);
    1175             : 
    1176             :   ObjectData* Get(int i) const;
    1177             : 
    1178             :  private:
    1179             :   bool serialized_contents_ = false;
    1180             :   ZoneVector<ObjectData*> contents_;
    1181             : };
    1182             : 
    1183         160 : JSDataViewData::JSDataViewData(JSHeapBroker* broker, ObjectData** storage,
    1184             :                                Handle<JSDataView> object)
    1185             :     : JSObjectData(broker, storage, object),
    1186             :       byte_length_(object->byte_length()),
    1187         480 :       byte_offset_(object->byte_offset()) {}
    1188             : 
    1189         161 : JSBoundFunctionData::JSBoundFunctionData(JSHeapBroker* broker,
    1190             :                                          ObjectData** storage,
    1191             :                                          Handle<JSBoundFunction> object)
    1192         161 :     : JSObjectData(broker, storage, object) {}
    1193             : 
    1194           0 : void JSBoundFunctionData::Serialize(JSHeapBroker* broker) {
    1195           0 :   if (serialized_) return;
    1196           0 :   serialized_ = true;
    1197             : 
    1198           0 :   TraceScope tracer(broker, this, "JSBoundFunctionData::Serialize");
    1199             :   Handle<JSBoundFunction> function = Handle<JSBoundFunction>::cast(object());
    1200             : 
    1201             :   DCHECK_NULL(bound_target_function_);
    1202             :   DCHECK_NULL(bound_this_);
    1203             :   DCHECK_NULL(bound_arguments_);
    1204             : 
    1205             :   bound_target_function_ =
    1206           0 :       broker->GetOrCreateData(function->bound_target_function());
    1207           0 :   bound_this_ = broker->GetOrCreateData(function->bound_this());
    1208             :   bound_arguments_ =
    1209           0 :       broker->GetOrCreateData(function->bound_arguments())->AsFixedArray();
    1210             : 
    1211           0 :   bound_arguments_->SerializeContents(broker);
    1212             : }
    1213             : 
    1214    11758708 : JSObjectData::JSObjectData(JSHeapBroker* broker, ObjectData** storage,
    1215             :                            Handle<JSObject> object)
    1216             :     : HeapObjectData(broker, storage, object),
    1217             :       inobject_fields_(broker->zone()),
    1218    35276086 :       own_constant_elements_(broker->zone()) {}
    1219             : 
    1220      513866 : FixedArrayData::FixedArrayData(JSHeapBroker* broker, ObjectData** storage,
    1221             :                                Handle<FixedArray> object)
    1222     1027732 :     : FixedArrayBaseData(broker, storage, object), contents_(broker->zone()) {}
    1223             : 
    1224        1811 : void FixedArrayData::SerializeContents(JSHeapBroker* broker) {
    1225        1811 :   if (serialized_contents_) return;
    1226        1811 :   serialized_contents_ = true;
    1227             : 
    1228        1811 :   TraceScope tracer(broker, this, "FixedArrayData::SerializeContents");
    1229             :   Handle<FixedArray> array = Handle<FixedArray>::cast(object());
    1230        1811 :   CHECK_EQ(array->length(), length());
    1231        1811 :   CHECK(contents_.empty());
    1232        1811 :   contents_.reserve(static_cast<size_t>(length()));
    1233             : 
    1234       16853 :   for (int i = 0; i < length(); i++) {
    1235             :     Handle<Object> value(array->get(i), broker->isolate());
    1236       15042 :     contents_.push_back(broker->GetOrCreateData(value));
    1237             :   }
    1238        1811 :   TRACE(broker, "Copied " << contents_.size() << " elements");
    1239             : }
    1240             : 
    1241             : class FixedDoubleArrayData : public FixedArrayBaseData {
    1242             :  public:
    1243             :   FixedDoubleArrayData(JSHeapBroker* broker, ObjectData** storage,
    1244             :                        Handle<FixedDoubleArray> object);
    1245             : 
    1246             :   // Serializes all elements of the fixed array.
    1247             :   void SerializeContents(JSHeapBroker* broker);
    1248             : 
    1249             :   Float64 Get(int i) const;
    1250             : 
    1251             :  private:
    1252             :   bool serialized_contents_ = false;
    1253             :   ZoneVector<Float64> contents_;
    1254             : };
    1255             : 
    1256         518 : FixedDoubleArrayData::FixedDoubleArrayData(JSHeapBroker* broker,
    1257             :                                            ObjectData** storage,
    1258             :                                            Handle<FixedDoubleArray> object)
    1259        1036 :     : FixedArrayBaseData(broker, storage, object), contents_(broker->zone()) {}
    1260             : 
    1261         518 : void FixedDoubleArrayData::SerializeContents(JSHeapBroker* broker) {
    1262         518 :   if (serialized_contents_) return;
    1263         518 :   serialized_contents_ = true;
    1264             : 
    1265         518 :   TraceScope tracer(broker, this, "FixedDoubleArrayData::SerializeContents");
    1266             :   Handle<FixedDoubleArray> self = Handle<FixedDoubleArray>::cast(object());
    1267         518 :   CHECK_EQ(self->length(), length());
    1268         518 :   CHECK(contents_.empty());
    1269         518 :   contents_.reserve(static_cast<size_t>(length()));
    1270             : 
    1271       14940 :   for (int i = 0; i < length(); i++) {
    1272       14422 :     contents_.push_back(Float64::FromBits(self->get_representation(i)));
    1273             :   }
    1274         518 :   TRACE(broker, "Copied " << contents_.size() << " elements");
    1275             : }
    1276             : 
    1277             : class BytecodeArrayData : public FixedArrayBaseData {
    1278             :  public:
    1279             :   int register_count() const { return register_count_; }
    1280             : 
    1281      615193 :   BytecodeArrayData(JSHeapBroker* broker, ObjectData** storage,
    1282             :                     Handle<BytecodeArray> object)
    1283             :       : FixedArrayBaseData(broker, storage, object),
    1284      615194 :         register_count_(object->register_count()) {}
    1285             : 
    1286             :  private:
    1287             :   int const register_count_;
    1288             : };
    1289             : 
    1290             : class JSArrayData : public JSObjectData {
    1291             :  public:
    1292             :   JSArrayData(JSHeapBroker* broker, ObjectData** storage,
    1293             :               Handle<JSArray> object);
    1294             : 
    1295             :   void Serialize(JSHeapBroker* broker);
    1296             :   ObjectData* length() const { return length_; }
    1297             : 
    1298             :   ObjectData* GetOwnElement(JSHeapBroker* broker, uint32_t index,
    1299             :                             bool serialize);
    1300             : 
    1301             :  private:
    1302             :   bool serialized_ = false;
    1303             :   ObjectData* length_ = nullptr;
    1304             : 
    1305             :   // Elements (indexed properties) that either
    1306             :   // (1) are known to exist directly on the object, or
    1307             :   // (2) are known not to (possibly they don't exist at all).
    1308             :   // In case (2), the second pair component is nullptr.
    1309             :   ZoneVector<std::pair<uint32_t, ObjectData*>> own_elements_;
    1310             : };
    1311             : 
    1312      473296 : JSArrayData::JSArrayData(JSHeapBroker* broker, ObjectData** storage,
    1313             :                          Handle<JSArray> object)
    1314      946597 :     : JSObjectData(broker, storage, object), own_elements_(broker->zone()) {}
    1315             : 
    1316        4200 : void JSArrayData::Serialize(JSHeapBroker* broker) {
    1317        4200 :   if (serialized_) return;
    1318        4200 :   serialized_ = true;
    1319             : 
    1320        4200 :   TraceScope tracer(broker, this, "JSArrayData::Serialize");
    1321             :   Handle<JSArray> jsarray = Handle<JSArray>::cast(object());
    1322             : 
    1323             :   DCHECK_NULL(length_);
    1324        4200 :   length_ = broker->GetOrCreateData(jsarray->length());
    1325             : }
    1326             : 
    1327           0 : ObjectData* JSArrayData::GetOwnElement(JSHeapBroker* broker, uint32_t index,
    1328             :                                        bool serialize) {
    1329           0 :   for (auto const& p : own_elements_) {
    1330           0 :     if (p.first == index) return p.second;
    1331             :   }
    1332             : 
    1333           0 :   if (!serialize) {
    1334           0 :     TRACE_MISSING(broker, "knowledge about index " << index << " on " << this);
    1335             :     return nullptr;
    1336             :   }
    1337             : 
    1338             :   base::Optional<ObjectRef> element =
    1339           0 :       GetOwnElementFromHeap(broker, object(), index, false);
    1340           0 :   ObjectData* result = element.has_value() ? element->data() : nullptr;
    1341           0 :   own_elements_.push_back({index, result});
    1342           0 :   return result;
    1343             : }
    1344             : 
    1345             : class ScopeInfoData : public HeapObjectData {
    1346             :  public:
    1347             :   ScopeInfoData(JSHeapBroker* broker, ObjectData** storage,
    1348             :                 Handle<ScopeInfo> object);
    1349             : 
    1350             :   int context_length() const { return context_length_; }
    1351             : 
    1352             :  private:
    1353             :   int const context_length_;
    1354             : };
    1355             : 
    1356       56751 : ScopeInfoData::ScopeInfoData(JSHeapBroker* broker, ObjectData** storage,
    1357             :                              Handle<ScopeInfo> object)
    1358             :     : HeapObjectData(broker, storage, object),
    1359      113502 :       context_length_(object->ContextLength()) {}
    1360             : 
    1361             : class SharedFunctionInfoData : public HeapObjectData {
    1362             :  public:
    1363             :   SharedFunctionInfoData(JSHeapBroker* broker, ObjectData** storage,
    1364             :                          Handle<SharedFunctionInfo> object);
    1365             : 
    1366             :   int builtin_id() const { return builtin_id_; }
    1367             :   BytecodeArrayData* GetBytecodeArray() const { return GetBytecodeArray_; }
    1368             :   void SetSerializedForCompilation(JSHeapBroker* broker,
    1369             :                                    FeedbackVectorRef feedback);
    1370             :   bool IsSerializedForCompilation(FeedbackVectorRef feedback) const;
    1371             : #define DECL_ACCESSOR(type, name) \
    1372             :   type name() const { return name##_; }
    1373             :   BROKER_SFI_FIELDS(DECL_ACCESSOR)
    1374             : #undef DECL_ACCESSOR
    1375             : 
    1376             :  private:
    1377             :   int const builtin_id_;
    1378             :   BytecodeArrayData* const GetBytecodeArray_;
    1379             :   ZoneUnorderedSet<Handle<FeedbackVector>, Handle<FeedbackVector>::hash,
    1380             :                    Handle<FeedbackVector>::equal_to>
    1381             :       serialized_for_compilation_;
    1382             : #define DECL_MEMBER(type, name) type const name##_;
    1383             :   BROKER_SFI_FIELDS(DECL_MEMBER)
    1384             : #undef DECL_MEMBER
    1385             : };
    1386             : 
    1387     7018560 : SharedFunctionInfoData::SharedFunctionInfoData(
    1388             :     JSHeapBroker* broker, ObjectData** storage,
    1389             :     Handle<SharedFunctionInfo> object)
    1390             :     : HeapObjectData(broker, storage, object),
    1391             :       builtin_id_(object->HasBuiltinId() ? object->builtin_id()
    1392             :                                          : Builtins::kNoBuiltinId),
    1393             :       GetBytecodeArray_(
    1394    14037107 :           object->HasBytecodeArray()
    1395     7633747 :               ? broker->GetOrCreateData(object->GetBytecodeArray())
    1396      615194 :                     ->AsBytecodeArray()
    1397             :               : nullptr),
    1398             :       serialized_for_compilation_(broker->zone())
    1399             : #define INIT_MEMBER(type, name) , name##_(object->name())
    1400   112911982 :           BROKER_SFI_FIELDS(INIT_MEMBER)
    1401             : #undef INIT_MEMBER
    1402             : {
    1403             :   DCHECK_EQ(HasBuiltinId_, builtin_id_ != Builtins::kNoBuiltinId);
    1404             :   DCHECK_EQ(HasBytecodeArray_, GetBytecodeArray_ != nullptr);
    1405     7018551 : }
    1406             : 
    1407         162 : void SharedFunctionInfoData::SetSerializedForCompilation(
    1408             :     JSHeapBroker* broker, FeedbackVectorRef feedback) {
    1409         324 :   CHECK(serialized_for_compilation_.insert(feedback.object()).second);
    1410         162 :   TRACE(broker, "Set function " << object() << " with " << feedback.object()
    1411             :                                 << " as serialized for compilation");
    1412         162 : }
    1413             : 
    1414           0 : bool SharedFunctionInfoData::IsSerializedForCompilation(
    1415             :     FeedbackVectorRef feedback) const {
    1416         832 :   return serialized_for_compilation_.find(feedback.object()) !=
    1417           0 :          serialized_for_compilation_.end();
    1418             : }
    1419             : 
    1420             : class ModuleData : public HeapObjectData {
    1421             :  public:
    1422             :   ModuleData(JSHeapBroker* broker, ObjectData** storage, Handle<Module> object);
    1423             :   void Serialize(JSHeapBroker* broker);
    1424             : 
    1425             :   CellData* GetCell(int cell_index) const;
    1426             : 
    1427             :  private:
    1428             :   bool serialized_ = false;
    1429             :   ZoneVector<CellData*> imports_;
    1430             :   ZoneVector<CellData*> exports_;
    1431             : };
    1432             : 
    1433          85 : ModuleData::ModuleData(JSHeapBroker* broker, ObjectData** storage,
    1434             :                        Handle<Module> object)
    1435             :     : HeapObjectData(broker, storage, object),
    1436             :       imports_(broker->zone()),
    1437         170 :       exports_(broker->zone()) {}
    1438             : 
    1439         138 : CellData* ModuleData::GetCell(int cell_index) const {
    1440         138 :   CHECK(serialized_);
    1441             :   CellData* cell;
    1442         138 :   switch (ModuleDescriptor::GetCellIndexKind(cell_index)) {
    1443             :     case ModuleDescriptor::kImport:
    1444          62 :       cell = imports_.at(Module::ImportIndex(cell_index));
    1445          31 :       break;
    1446             :     case ModuleDescriptor::kExport:
    1447         214 :       cell = exports_.at(Module::ExportIndex(cell_index));
    1448         107 :       break;
    1449             :     case ModuleDescriptor::kInvalid:
    1450           0 :       UNREACHABLE();
    1451             :       break;
    1452             :   }
    1453         138 :   CHECK_NOT_NULL(cell);
    1454         138 :   return cell;
    1455             : }
    1456             : 
    1457         170 : void ModuleData::Serialize(JSHeapBroker* broker) {
    1458         255 :   if (serialized_) return;
    1459          85 :   serialized_ = true;
    1460             : 
    1461          85 :   TraceScope tracer(broker, this, "ModuleData::Serialize");
    1462             :   Handle<Module> module = Handle<Module>::cast(object());
    1463             : 
    1464             :   // TODO(neis): We could be smarter and only serialize the cells we care about.
    1465             :   // TODO(neis): Define a helper for serializing a FixedArray into a ZoneVector.
    1466             : 
    1467             :   DCHECK(imports_.empty());
    1468             :   Handle<FixedArray> imports(module->regular_imports(), broker->isolate());
    1469             :   int const imports_length = imports->length();
    1470          85 :   imports_.reserve(imports_length);
    1471         273 :   for (int i = 0; i < imports_length; ++i) {
    1472         188 :     imports_.push_back(broker->GetOrCreateData(imports->get(i))->AsCell());
    1473             :   }
    1474          85 :   TRACE(broker, "Copied " << imports_.size() << " imports");
    1475             : 
    1476             :   DCHECK(exports_.empty());
    1477             :   Handle<FixedArray> exports(module->regular_exports(), broker->isolate());
    1478             :   int const exports_length = exports->length();
    1479          85 :   exports_.reserve(exports_length);
    1480         433 :   for (int i = 0; i < exports_length; ++i) {
    1481         348 :     exports_.push_back(broker->GetOrCreateData(exports->get(i))->AsCell());
    1482             :   }
    1483          85 :   TRACE(broker, "Copied " << exports_.size() << " exports");
    1484             : }
    1485             : 
    1486             : class CellData : public HeapObjectData {
    1487             :  public:
    1488             :   CellData(JSHeapBroker* broker, ObjectData** storage, Handle<Cell> object);
    1489             : 
    1490             :   void Serialize(JSHeapBroker* broker);
    1491             :   ObjectData* value() { return value_; }
    1492             : 
    1493             :  private:
    1494             :   bool serialized_ = false;
    1495             :   ObjectData* value_ = nullptr;
    1496             : };
    1497             : 
    1498      928487 : CellData::CellData(JSHeapBroker* broker, ObjectData** storage,
    1499             :                    Handle<Cell> object)
    1500      928487 :     : HeapObjectData(broker, storage, object) {}
    1501             : 
    1502      928228 : void CellData::Serialize(JSHeapBroker* broker) {
    1503      928228 :   if (serialized_) return;
    1504      928228 :   serialized_ = true;
    1505             : 
    1506      928228 :   TraceScope tracer(broker, this, "CellData::Serialize");
    1507             :   auto cell = Handle<Cell>::cast(object());
    1508             :   DCHECK_NULL(value_);
    1509      928228 :   value_ = broker->GetOrCreateData(cell->value());
    1510             : }
    1511             : 
    1512             : class JSGlobalProxyData : public JSObjectData {
    1513             :  public:
    1514             :   JSGlobalProxyData(JSHeapBroker* broker, ObjectData** storage,
    1515             :                     Handle<JSGlobalProxy> object);
    1516             : 
    1517             :   PropertyCellData* GetPropertyCell(JSHeapBroker* broker, NameData* name,
    1518             :                                     bool serialize);
    1519             : 
    1520             :  private:
    1521             :   // Properties that either
    1522             :   // (1) are known to exist as property cells on the global object, or
    1523             :   // (2) are known not to (possibly they don't exist at all).
    1524             :   // In case (2), the second pair component is nullptr.
    1525             :   ZoneVector<std::pair<NameData*, PropertyCellData*>> properties_;
    1526             : };
    1527             : 
    1528      464115 : JSGlobalProxyData::JSGlobalProxyData(JSHeapBroker* broker, ObjectData** storage,
    1529             :                                      Handle<JSGlobalProxy> object)
    1530      928230 :     : JSObjectData(broker, storage, object), properties_(broker->zone()) {}
    1531             : 
    1532             : namespace {
    1533         246 : base::Optional<PropertyCellRef> GetPropertyCellFromHeap(JSHeapBroker* broker,
    1534             :                                                         Handle<Name> name) {
    1535             :   LookupIterator it(broker->isolate(),
    1536         738 :                     handle(broker->native_context().object()->global_object(),
    1537             :                            broker->isolate()),
    1538         492 :                     name, LookupIterator::OWN);
    1539         246 :   it.TryLookupCachedProperty();
    1540         472 :   if (it.state() == LookupIterator::DATA &&
    1541             :       it.GetHolder<JSObject>()->IsJSGlobalObject()) {
    1542         452 :     return PropertyCellRef(broker, it.GetPropertyCell());
    1543             :   }
    1544             :   return base::nullopt;
    1545             : }
    1546             : }  // namespace
    1547             : 
    1548           0 : PropertyCellData* JSGlobalProxyData::GetPropertyCell(JSHeapBroker* broker,
    1549             :                                                      NameData* name,
    1550             :                                                      bool serialize) {
    1551           0 :   CHECK_NOT_NULL(name);
    1552           0 :   for (auto const& p : properties_) {
    1553           0 :     if (p.first == name) return p.second;
    1554             :   }
    1555             : 
    1556           0 :   if (!serialize) {
    1557           0 :     TRACE_MISSING(broker, "knowledge about global property " << name);
    1558             :     return nullptr;
    1559             :   }
    1560             : 
    1561             :   PropertyCellData* result = nullptr;
    1562             :   base::Optional<PropertyCellRef> cell =
    1563           0 :       GetPropertyCellFromHeap(broker, Handle<Name>::cast(name->object()));
    1564           0 :   if (cell.has_value()) {
    1565           0 :     cell->Serialize();
    1566           0 :     result = cell->data()->AsPropertyCell();
    1567             :   }
    1568           0 :   properties_.push_back({name, result});
    1569           0 :   return result;
    1570             : }
    1571             : 
    1572             : class CodeData : public HeapObjectData {
    1573             :  public:
    1574     5951445 :   CodeData(JSHeapBroker* broker, ObjectData** storage, Handle<Code> object)
    1575     5951445 :       : HeapObjectData(broker, storage, object) {}
    1576             : };
    1577             : 
    1578             : #define DEFINE_IS_AND_AS(Name)                                            \
    1579             :   bool ObjectData::Is##Name() const {                                     \
    1580             :     if (kind() == kUnserializedHeapObject) {                              \
    1581             :       AllowHandleDereference allow_handle_dereference;                    \
    1582             :       return object()->Is##Name();                                        \
    1583             :     }                                                                     \
    1584             :     if (is_smi()) return false;                                           \
    1585             :     InstanceType instance_type =                                          \
    1586             :         static_cast<const HeapObjectData*>(this)->map()->instance_type(); \
    1587             :     return InstanceTypeChecker::Is##Name(instance_type);                  \
    1588             :   }                                                                       \
    1589             :   Name##Data* ObjectData::As##Name() {                                    \
    1590             :     CHECK_EQ(kind(), kSerializedHeapObject);                              \
    1591             :     CHECK(Is##Name());                                                    \
    1592             :     return static_cast<Name##Data*>(this);                                \
    1593             :   }
    1594   923955780 : HEAP_BROKER_OBJECT_LIST(DEFINE_IS_AND_AS)
    1595             : #undef DEFINE_IS_AND_AS
    1596             : 
    1597        3330 : const JSObjectField& JSObjectData::GetInobjectField(int property_index) const {
    1598        3330 :   CHECK_LT(static_cast<size_t>(property_index), inobject_fields_.size());
    1599        3330 :   return inobject_fields_[property_index];
    1600             : }
    1601             : 
    1602           0 : bool JSObjectData::cow_or_empty_elements_tenured() const {
    1603          40 :   return cow_or_empty_elements_tenured_;
    1604             : }
    1605             : 
    1606        7617 : FixedArrayBaseData* JSObjectData::elements() const { return elements_; }
    1607             : 
    1608           0 : void JSObjectData::SerializeAsBoilerplate(JSHeapBroker* broker) {
    1609        6061 :   SerializeRecursive(broker, kMaxFastLiteralDepth);
    1610           0 : }
    1611             : 
    1612         492 : void JSObjectData::SerializeElements(JSHeapBroker* broker) {
    1613         492 :   if (serialized_elements_) return;
    1614         492 :   serialized_elements_ = true;
    1615             : 
    1616         492 :   TraceScope tracer(broker, this, "JSObjectData::SerializeElements");
    1617             :   Handle<JSObject> boilerplate = Handle<JSObject>::cast(object());
    1618             :   Handle<FixedArrayBase> elements_object(boilerplate->elements(),
    1619             :                                          broker->isolate());
    1620             :   DCHECK_NULL(elements_);
    1621         492 :   elements_ = broker->GetOrCreateData(elements_object)->AsFixedArrayBase();
    1622             : }
    1623             : 
    1624    13467237 : void MapData::SerializeConstructor(JSHeapBroker* broker) {
    1625    13931350 :   if (serialized_constructor_) return;
    1626    13003124 :   serialized_constructor_ = true;
    1627             : 
    1628    13003124 :   TraceScope tracer(broker, this, "MapData::SerializeConstructor");
    1629             :   Handle<Map> map = Handle<Map>::cast(object());
    1630             :   DCHECK_NULL(constructor_);
    1631    13003121 :   constructor_ = broker->GetOrCreateData(map->GetConstructor());
    1632             : }
    1633             : 
    1634           0 : void MapData::SerializeBackPointer(JSHeapBroker* broker) {
    1635           0 :   if (serialized_backpointer_) return;
    1636           0 :   serialized_backpointer_ = true;
    1637             : 
    1638           0 :   TraceScope tracer(broker, this, "MapData::SerializeBackPointer");
    1639             :   Handle<Map> map = Handle<Map>::cast(object());
    1640             :   DCHECK_NULL(backpointer_);
    1641           0 :   backpointer_ = broker->GetOrCreateData(map->GetBackPointer())->AsHeapObject();
    1642             : }
    1643             : 
    1644     4653130 : void MapData::SerializePrototype(JSHeapBroker* broker) {
    1645     4653130 :   if (serialized_prototype_) return;
    1646     4653130 :   serialized_prototype_ = true;
    1647             : 
    1648     4653130 :   TraceScope tracer(broker, this, "MapData::SerializePrototype");
    1649             :   Handle<Map> map = Handle<Map>::cast(object());
    1650             :   DCHECK_NULL(prototype_);
    1651     4653130 :   prototype_ = broker->GetOrCreateData(map->prototype());
    1652             : }
    1653             : 
    1654        8988 : void MapData::SerializeOwnDescriptors(JSHeapBroker* broker) {
    1655       14267 :   if (serialized_own_descriptors_) return;
    1656        5220 :   serialized_own_descriptors_ = true;
    1657             : 
    1658        5220 :   TraceScope tracer(broker, this, "MapData::SerializeOwnDescriptors");
    1659             :   Handle<Map> map = Handle<Map>::cast(object());
    1660             : 
    1661             :   DCHECK_NULL(instance_descriptors_);
    1662             :   instance_descriptors_ =
    1663        5220 :       broker->GetOrCreateData(map->instance_descriptors())->AsDescriptorArray();
    1664             : 
    1665             :   int const number_of_own = map->NumberOfOwnDescriptors();
    1666        5220 :   ZoneVector<PropertyDescriptor>& contents = instance_descriptors_->contents();
    1667        5220 :   int const current_size = static_cast<int>(contents.size());
    1668        5220 :   if (number_of_own <= current_size) return;
    1669             : 
    1670             :   Isolate* const isolate = broker->isolate();
    1671             :   auto descriptors =
    1672             :       Handle<DescriptorArray>::cast(instance_descriptors_->object());
    1673        3709 :   CHECK_EQ(*descriptors, map->instance_descriptors());
    1674        3709 :   contents.reserve(number_of_own);
    1675             : 
    1676             :   // Copy the new descriptors.
    1677       12551 :   for (int i = current_size; i < number_of_own; ++i) {
    1678             :     PropertyDescriptor d;
    1679        4421 :     d.key = broker->GetOrCreateData(descriptors->GetKey(i))->AsName();
    1680        4421 :     d.details = descriptors->GetDetails(i);
    1681        4421 :     if (d.details.location() == kField) {
    1682        2217 :       d.field_index = FieldIndex::ForDescriptor(*map, i);
    1683             :       d.field_owner =
    1684        2217 :           broker->GetOrCreateData(map->FindFieldOwner(isolate, i))->AsMap();
    1685        2217 :       d.field_type = broker->GetOrCreateData(descriptors->GetFieldType(i));
    1686        2217 :       d.is_unboxed_double_field = map->IsUnboxedDoubleField(d.field_index);
    1687             :       // Recurse.
    1688             :     }
    1689        4421 :     contents.push_back(d);
    1690             :   }
    1691        3709 :   CHECK_EQ(number_of_own, contents.size());
    1692             : 
    1693             :   // Recurse on the new owner maps.
    1694       12551 :   for (int i = current_size; i < number_of_own; ++i) {
    1695        4421 :     const PropertyDescriptor& d = contents[i];
    1696        4421 :     if (d.details.location() == kField) {
    1697        4434 :       CHECK_LE(
    1698             :           Handle<Map>::cast(d.field_owner->object())->NumberOfOwnDescriptors(),
    1699             :           number_of_own);
    1700        2217 :       d.field_owner->SerializeOwnDescriptors(broker);
    1701             :     }
    1702             :   }
    1703             : 
    1704        3709 :   TRACE(broker, "Copied " << number_of_own - current_size
    1705             :                           << " descriptors into " << instance_descriptors_
    1706             :                           << " (" << number_of_own << " total)");
    1707             : }
    1708             : 
    1709        6982 : void JSObjectData::SerializeRecursive(JSHeapBroker* broker, int depth) {
    1710        7209 :   if (serialized_as_boilerplate_) return;
    1711        6755 :   serialized_as_boilerplate_ = true;
    1712             : 
    1713        6755 :   TraceScope tracer(broker, this, "JSObjectData::SerializeRecursive");
    1714             :   Handle<JSObject> boilerplate = Handle<JSObject>::cast(object());
    1715             : 
    1716             :   // We only serialize boilerplates that pass the IsInlinableFastLiteral
    1717             :   // check, so we only do a sanity check on the depth here.
    1718        6755 :   CHECK_GT(depth, 0);
    1719        6755 :   CHECK(!boilerplate->map()->is_deprecated());
    1720             : 
    1721             :   // Serialize the elements.
    1722             :   Isolate* const isolate = broker->isolate();
    1723             :   Handle<FixedArrayBase> elements_object(boilerplate->elements(), isolate);
    1724             : 
    1725             :   // Boilerplates need special serialization - we need to make sure COW arrays
    1726             :   // are tenured. Boilerplate objects should only be reachable from their
    1727             :   // allocation site, so it is safe to assume that the elements have not been
    1728             :   // serialized yet.
    1729             : 
    1730             :   bool const empty_or_cow =
    1731       11033 :       elements_object->length() == 0 ||
    1732             :       elements_object->map() == ReadOnlyRoots(isolate).fixed_cow_array_map();
    1733        6755 :   if (empty_or_cow) {
    1734             :     // We need to make sure copy-on-write elements are tenured.
    1735        4426 :     if (ObjectInYoungGeneration(*elements_object)) {
    1736             :       elements_object = isolate->factory()->CopyAndTenureFixedCOWArray(
    1737        1609 :           Handle<FixedArray>::cast(elements_object));
    1738        1609 :       boilerplate->set_elements(*elements_object);
    1739             :     }
    1740        4426 :     cow_or_empty_elements_tenured_ = true;
    1741             :   }
    1742             : 
    1743             :   DCHECK_NULL(elements_);
    1744        6755 :   elements_ = broker->GetOrCreateData(elements_object)->AsFixedArrayBase();
    1745             : 
    1746        6755 :   if (empty_or_cow) {
    1747             :     // No need to do anything here. Empty or copy-on-write elements
    1748             :     // do not need to be serialized because we only need to store the elements
    1749             :     // reference to the allocated object.
    1750        2329 :   } else if (boilerplate->HasSmiOrObjectElements()) {
    1751        1811 :     elements_->AsFixedArray()->SerializeContents(broker);
    1752             :     Handle<FixedArray> fast_elements =
    1753             :         Handle<FixedArray>::cast(elements_object);
    1754             :     int length = elements_object->length();
    1755       16853 :     for (int i = 0; i < length; i++) {
    1756             :       Handle<Object> value(fast_elements->get(i), isolate);
    1757        7521 :       if (value->IsJSObject()) {
    1758         637 :         ObjectData* value_data = broker->GetOrCreateData(value);
    1759         637 :         value_data->AsJSObject()->SerializeRecursive(broker, depth - 1);
    1760             :       }
    1761             :     }
    1762             :   } else {
    1763         518 :     CHECK(boilerplate->HasDoubleElements());
    1764         518 :     CHECK_LE(elements_object->Size(), kMaxRegularHeapObjectSize);
    1765         518 :     elements_->AsFixedDoubleArray()->SerializeContents(broker);
    1766             :   }
    1767             : 
    1768             :   // TODO(turbofan): Do we want to support out-of-object properties?
    1769       20265 :   CHECK(boilerplate->HasFastProperties() &&
    1770             :         boilerplate->property_array()->length() == 0);
    1771        6755 :   CHECK_EQ(inobject_fields_.size(), 0u);
    1772             : 
    1773             :   // Check the in-object properties.
    1774             :   Handle<DescriptorArray> descriptors(
    1775             :       boilerplate->map()->instance_descriptors(), isolate);
    1776             :   int const limit = boilerplate->map()->NumberOfOwnDescriptors();
    1777       20881 :   for (int i = 0; i < limit; i++) {
    1778        7063 :     PropertyDetails details = descriptors->GetDetails(i);
    1779       11263 :     if (details.location() != kField) continue;
    1780             :     DCHECK_EQ(kData, details.kind());
    1781             : 
    1782        2863 :     FieldIndex field_index = FieldIndex::ForDescriptor(boilerplate->map(), i);
    1783             :     // Make sure {field_index} agrees with {inobject_properties} on the index of
    1784             :     // this field.
    1785             :     DCHECK_EQ(field_index.property_index(),
    1786             :               static_cast<int>(inobject_fields_.size()));
    1787        2863 :     if (boilerplate->IsUnboxedDoubleField(field_index)) {
    1788             :       double value = boilerplate->RawFastDoublePropertyAt(field_index);
    1789         256 :       inobject_fields_.push_back(JSObjectField{value});
    1790             :     } else {
    1791             :       Handle<Object> value(boilerplate->RawFastPropertyAt(field_index),
    1792        5470 :                            isolate);
    1793        2735 :       ObjectData* value_data = broker->GetOrCreateData(value);
    1794        2735 :       if (value->IsJSObject()) {
    1795         284 :         value_data->AsJSObject()->SerializeRecursive(broker, depth - 1);
    1796             :       }
    1797        5470 :       inobject_fields_.push_back(JSObjectField{value_data});
    1798             :     }
    1799             :   }
    1800        6755 :   TRACE(broker, "Copied " << inobject_fields_.size() << " in-object fields");
    1801             : 
    1802        6755 :   map()->SerializeOwnDescriptors(broker);
    1803             : 
    1804        6755 :   if (IsJSArray()) AsJSArray()->Serialize(broker);
    1805             : }
    1806             : 
    1807         492 : void JSRegExpData::SerializeAsRegExpBoilerplate(JSHeapBroker* broker) {
    1808         492 :   if (serialized_as_reg_exp_boilerplate_) return;
    1809         492 :   serialized_as_reg_exp_boilerplate_ = true;
    1810             : 
    1811         492 :   TraceScope tracer(broker, this, "JSRegExpData::SerializeAsRegExpBoilerplate");
    1812             :   Handle<JSRegExp> boilerplate = Handle<JSRegExp>::cast(object());
    1813             : 
    1814         492 :   SerializeElements(broker);
    1815             : 
    1816             :   raw_properties_or_hash_ =
    1817         492 :       broker->GetOrCreateData(boilerplate->raw_properties_or_hash());
    1818         492 :   data_ = broker->GetOrCreateData(boilerplate->data());
    1819         492 :   source_ = broker->GetOrCreateData(boilerplate->source());
    1820         492 :   flags_ = broker->GetOrCreateData(boilerplate->flags());
    1821         492 :   last_index_ = broker->GetOrCreateData(boilerplate->last_index());
    1822             : }
    1823             : 
    1824     1405743 : bool ObjectRef::equals(const ObjectRef& other) const {
    1825    33852349 :   return data_ == other.data_;
    1826             : }
    1827             : 
    1828     1937778 : Isolate* ObjectRef::isolate() const { return broker()->isolate(); }
    1829             : 
    1830       23615 : ContextRef ContextRef::previous() const {
    1831       23615 :   if (broker()->mode() == JSHeapBroker::kDisabled) {
    1832             :     AllowHandleAllocation handle_allocation;
    1833             :     AllowHandleDereference handle_dereference;
    1834             :     return ContextRef(broker(),
    1835       23615 :                       handle(object()->previous(), broker()->isolate()));
    1836             :   }
    1837           0 :   return ContextRef(broker(), data()->AsContext()->previous());
    1838             : }
    1839             : 
    1840             : // Not needed for TypedLowering.
    1841       27709 : ObjectRef ContextRef::get(int index) const {
    1842       27709 :   if (broker()->mode() == JSHeapBroker::kDisabled) {
    1843             :     AllowHandleAllocation handle_allocation;
    1844             :     AllowHandleDereference handle_dereference;
    1845             :     Handle<Object> value(object()->get(index), broker()->isolate());
    1846       27693 :     return ObjectRef(broker(), value);
    1847             :   }
    1848          32 :   return ObjectRef(broker(), data()->AsContext()->GetSlot(index));
    1849             : }
    1850             : 
    1851      485858 : JSHeapBroker::JSHeapBroker(Isolate* isolate, Zone* broker_zone)
    1852             :     : isolate_(isolate),
    1853             :       broker_zone_(broker_zone),
    1854             :       current_zone_(broker_zone),
    1855             :       refs_(new (zone())
    1856      485858 :                 RefsMap(kMinimalRefsBucketCount, AddressMatcher(), zone())),
    1857             :       array_and_object_prototypes_(zone()),
    1858     1943428 :       feedback_(zone()) {
    1859             :   // Note that this initialization of the refs_ pointer with the minimal
    1860             :   // initial capacity is redundant in the normal use case (concurrent
    1861             :   // compilation enabled, standard objects to be serialized), as the map
    1862             :   // is going to be replaced immediatelly with a larger capacity one.
    1863             :   // It doesn't seem to affect the performance in a noticeable way though.
    1864      485860 :   TRACE(this, "Constructing heap broker");
    1865      485860 : }
    1866             : 
    1867           0 : std::ostream& JSHeapBroker::Trace() {
    1868           0 :   return trace_out_ << "[" << this << "] "
    1869           0 :                     << std::string(trace_indentation_ * 2, ' ');
    1870             : }
    1871             : 
    1872      464112 : void JSHeapBroker::StartSerializing() {
    1873      464112 :   CHECK_EQ(mode_, kDisabled);
    1874      464112 :   TRACE(this, "Starting serialization");
    1875      464112 :   mode_ = kSerializing;
    1876      464112 :   refs_->Clear();
    1877      464112 : }
    1878             : 
    1879      464114 : void JSHeapBroker::StopSerializing() {
    1880      464114 :   CHECK_EQ(mode_, kSerializing);
    1881      464114 :   TRACE(this, "Stopping serialization");
    1882      464114 :   mode_ = kSerialized;
    1883      464114 : }
    1884             : 
    1885      463847 : void JSHeapBroker::Retire() {
    1886      463847 :   CHECK_EQ(mode_, kSerialized);
    1887      463847 :   TRACE(this, "Retiring");
    1888      463847 :   mode_ = kRetired;
    1889      463847 : }
    1890             : 
    1891           0 : bool JSHeapBroker::SerializingAllowed() const { return mode() == kSerializing; }
    1892             : 
    1893      928725 : void JSHeapBroker::SetNativeContextRef() {
    1894     1857451 :   native_context_ = NativeContextRef(this, isolate()->native_context());
    1895      928726 : }
    1896             : 
    1897     5401764 : bool IsShareable(Handle<Object> object, Isolate* isolate) {
    1898             :   Builtins* const b = isolate->builtins();
    1899             : 
    1900             :   int index;
    1901             :   RootIndex root_index;
    1902     5401764 :   return (object->IsHeapObject() &&
    1903     5431608 :           b->IsBuiltinHandle(Handle<HeapObject>::cast(object), &index)) ||
    1904     5401764 :          isolate->roots_table().IsRootHandle(object, &root_index);
    1905             : }
    1906             : 
    1907      464110 : void JSHeapBroker::SerializeShareableObjects() {
    1908      464110 :   PerIsolateCompilerCache::Setup(isolate());
    1909      464114 :   compiler_cache_ = isolate()->compiler_cache();
    1910             : 
    1911      464114 :   if (compiler_cache_->HasSnapshot()) {
    1912             :     RefsMap* snapshot = compiler_cache_->GetSnapshot();
    1913             : 
    1914      449192 :     refs_ = new (zone()) RefsMap(snapshot, zone());
    1915      449192 :     return;
    1916             :   }
    1917             : 
    1918             :   TraceScope tracer(
    1919             :       this, "JSHeapBroker::SerializeShareableObjects (building snapshot)");
    1920             : 
    1921             :   refs_ =
    1922       29844 :       new (zone()) RefsMap(kInitialRefsBucketCount, AddressMatcher(), zone());
    1923             : 
    1924       14922 :   current_zone_ = compiler_cache_->zone();
    1925             : 
    1926             :   Builtins* const b = isolate()->builtins();
    1927             :   {
    1928             :     Builtins::Name builtins[] = {
    1929             :         Builtins::kAllocateInYoungGeneration,
    1930             :         Builtins::kAllocateInOldGeneration,
    1931             :         Builtins::kArgumentsAdaptorTrampoline,
    1932             :         Builtins::kArrayConstructorImpl,
    1933             :         Builtins::kCallFunctionForwardVarargs,
    1934             :         Builtins::kCallFunction_ReceiverIsAny,
    1935             :         Builtins::kCallFunction_ReceiverIsNotNullOrUndefined,
    1936             :         Builtins::kCallFunction_ReceiverIsNullOrUndefined,
    1937             :         Builtins::kConstructFunctionForwardVarargs,
    1938             :         Builtins::kForInFilter,
    1939             :         Builtins::kJSBuiltinsConstructStub,
    1940             :         Builtins::kJSConstructStubGeneric,
    1941             :         Builtins::kStringAdd_CheckNone,
    1942             :         Builtins::kStringAdd_ConvertLeft,
    1943             :         Builtins::kStringAdd_ConvertRight,
    1944             :         Builtins::kToNumber,
    1945             :         Builtins::kToObject,
    1946       14922 :     };
    1947      522270 :     for (auto id : builtins) {
    1948      507348 :       GetOrCreateData(b->builtin_handle(id));
    1949             :     }
    1950             :   }
    1951    45407562 :   for (int32_t id = 0; id < Builtins::builtin_count; ++id) {
    1952    22696320 :     if (Builtins::KindOf(id) == Builtins::TFJ) {
    1953    10236450 :       GetOrCreateData(b->builtin_handle(id));
    1954             :     }
    1955             :   }
    1956             : 
    1957    16235136 :   for (RefsMap::Entry* p = refs_->Start(); p != nullptr; p = refs_->Next(p)) {
    1958     5401764 :     CHECK(IsShareable(p->value->object(), isolate()));
    1959             :   }
    1960             : 
    1961             :   // TODO(mslekova):
    1962             :   // Serialize root objects (from factory).
    1963       14922 :   compiler_cache()->SetSnapshot(refs_);
    1964       14922 :   current_zone_ = broker_zone_;
    1965             : }
    1966             : 
    1967      464114 : void JSHeapBroker::CollectArrayAndObjectPrototypes() {
    1968             :   DisallowHeapAllocation no_gc;
    1969      464114 :   CHECK_EQ(mode(), kSerializing);
    1970      464114 :   CHECK(array_and_object_prototypes_.empty());
    1971             : 
    1972             :   Object maybe_context = isolate()->heap()->native_contexts_list();
    1973     3722162 :   while (!maybe_context->IsUndefined(isolate())) {
    1974     1629024 :     Context context = Context::cast(maybe_context);
    1975             :     Object array_prot = context->get(Context::INITIAL_ARRAY_PROTOTYPE_INDEX);
    1976             :     Object object_prot = context->get(Context::INITIAL_OBJECT_PROTOTYPE_INDEX);
    1977     3258048 :     array_and_object_prototypes_.emplace(JSObject::cast(array_prot), isolate());
    1978     3258048 :     array_and_object_prototypes_.emplace(JSObject::cast(object_prot),
    1979     3258048 :                                          isolate());
    1980     1629024 :     maybe_context = context->next_context_link();
    1981             :   }
    1982             : 
    1983      464114 :   CHECK(!array_and_object_prototypes_.empty());
    1984      464114 : }
    1985             : 
    1986       66798 : bool JSHeapBroker::IsArrayOrObjectPrototype(const JSObjectRef& object) const {
    1987       66798 :   if (mode() == kDisabled) {
    1988      133580 :     return isolate()->IsInAnyContext(*object.object(),
    1989      130202 :                                      Context::INITIAL_ARRAY_PROTOTYPE_INDEX) ||
    1990       63412 :            isolate()->IsInAnyContext(*object.object(),
    1991             :                                      Context::INITIAL_OBJECT_PROTOTYPE_INDEX);
    1992             :   }
    1993           8 :   CHECK(!array_and_object_prototypes_.empty());
    1994          16 :   return array_and_object_prototypes_.find(object.object()) !=
    1995             :          array_and_object_prototypes_.end();
    1996             : }
    1997             : 
    1998      464134 : void JSHeapBroker::SerializeStandardObjects() {
    1999      464158 :   if (mode() == kDisabled) return;
    2000      464110 :   CHECK_EQ(mode(), kSerializing);
    2001             : 
    2002      464110 :   SerializeShareableObjects();
    2003             : 
    2004             :   TraceScope tracer(this, "JSHeapBroker::SerializeStandardObjects");
    2005             : 
    2006      464114 :   CollectArrayAndObjectPrototypes();
    2007             : 
    2008      464114 :   SetNativeContextRef();
    2009      464114 :   native_context().Serialize();
    2010             : 
    2011             :   Factory* const f = isolate()->factory();
    2012             : 
    2013             :   // Maps, strings, oddballs
    2014      464114 :   GetOrCreateData(f->arguments_marker_map());
    2015      464114 :   GetOrCreateData(f->bigint_string());
    2016      464113 :   GetOrCreateData(f->block_context_map());
    2017      464113 :   GetOrCreateData(f->boolean_map());
    2018      464114 :   GetOrCreateData(f->boolean_string());
    2019      464114 :   GetOrCreateData(f->catch_context_map());
    2020      464114 :   GetOrCreateData(f->empty_fixed_array());
    2021      464114 :   GetOrCreateData(f->empty_string());
    2022      464113 :   GetOrCreateData(f->eval_context_map());
    2023      464113 :   GetOrCreateData(f->false_string());
    2024      464113 :   GetOrCreateData(f->false_value());
    2025      464113 :   GetOrCreateData(f->fixed_array_map());
    2026      464113 :   GetOrCreateData(f->fixed_cow_array_map());
    2027      464113 :   GetOrCreateData(f->fixed_double_array_map());
    2028      464110 :   GetOrCreateData(f->function_context_map());
    2029      464113 :   GetOrCreateData(f->function_string());
    2030      464114 :   GetOrCreateData(f->heap_number_map());
    2031      464113 :   GetOrCreateData(f->length_string());
    2032      464114 :   GetOrCreateData(f->many_closures_cell_map());
    2033      464114 :   GetOrCreateData(f->minus_zero_value());
    2034      464114 :   GetOrCreateData(f->mutable_heap_number_map());
    2035      464112 :   GetOrCreateData(f->name_dictionary_map());
    2036      464114 :   GetOrCreateData(f->NaN_string());
    2037      464114 :   GetOrCreateData(f->null_map());
    2038      464114 :   GetOrCreateData(f->null_string());
    2039      464114 :   GetOrCreateData(f->null_value());
    2040      464114 :   GetOrCreateData(f->number_string());
    2041      464114 :   GetOrCreateData(f->object_string());
    2042      464114 :   GetOrCreateData(f->one_pointer_filler_map());
    2043      464113 :   GetOrCreateData(f->optimized_out());
    2044      464113 :   GetOrCreateData(f->optimized_out_map());
    2045      464113 :   GetOrCreateData(f->property_array_map());
    2046      464112 :   GetOrCreateData(f->sloppy_arguments_elements_map());
    2047      464113 :   GetOrCreateData(f->stale_register());
    2048      464114 :   GetOrCreateData(f->stale_register_map());
    2049      464113 :   GetOrCreateData(f->string_string());
    2050      464114 :   GetOrCreateData(f->symbol_string());
    2051      464113 :   GetOrCreateData(f->termination_exception_map());
    2052      464114 :   GetOrCreateData(f->the_hole_map());
    2053      464114 :   GetOrCreateData(f->the_hole_value());
    2054      464114 :   GetOrCreateData(f->true_string());
    2055      464114 :   GetOrCreateData(f->true_value());
    2056      464114 :   GetOrCreateData(f->undefined_map());
    2057      464114 :   GetOrCreateData(f->undefined_string());
    2058      464114 :   GetOrCreateData(f->undefined_value());
    2059      464114 :   GetOrCreateData(f->uninitialized_map());
    2060      464114 :   GetOrCreateData(f->with_context_map());
    2061      464114 :   GetOrCreateData(f->zero_string());
    2062             : 
    2063             :   // Protector cells
    2064             :   GetOrCreateData(f->array_buffer_detaching_protector())
    2065             :       ->AsPropertyCell()
    2066      464114 :       ->Serialize(this);
    2067      464113 :   GetOrCreateData(f->array_constructor_protector())->AsCell()->Serialize(this);
    2068             :   GetOrCreateData(f->array_iterator_protector())
    2069             :       ->AsPropertyCell()
    2070      464114 :       ->Serialize(this);
    2071             :   GetOrCreateData(f->array_species_protector())
    2072             :       ->AsPropertyCell()
    2073      464113 :       ->Serialize(this);
    2074             :   GetOrCreateData(f->no_elements_protector())
    2075             :       ->AsPropertyCell()
    2076      464114 :       ->Serialize(this);
    2077             :   GetOrCreateData(f->promise_hook_protector())
    2078             :       ->AsPropertyCell()
    2079      464113 :       ->Serialize(this);
    2080             :   GetOrCreateData(f->promise_species_protector())
    2081             :       ->AsPropertyCell()
    2082      464114 :       ->Serialize(this);
    2083             :   GetOrCreateData(f->promise_then_protector())
    2084             :       ->AsPropertyCell()
    2085      464114 :       ->Serialize(this);
    2086      464114 :   GetOrCreateData(f->string_length_protector())->AsCell()->Serialize(this);
    2087             : 
    2088             :   // CEntry stub
    2089      928228 :   GetOrCreateData(
    2090      464114 :       CodeFactory::CEntry(isolate(), 1, kDontSaveFPRegs, kArgvOnStack, true));
    2091             : 
    2092      464114 :   TRACE(this, "Finished serializing standard objects");
    2093             : }
    2094             : 
    2095           0 : ObjectData* JSHeapBroker::GetData(Handle<Object> object) const {
    2096    51583299 :   RefsMap::Entry* entry = refs_->Lookup(object.address());
    2097    51583409 :   return entry ? entry->value : nullptr;
    2098             : }
    2099             : 
    2100             : // clang-format off
    2101   208761155 : ObjectData* JSHeapBroker::GetOrCreateData(Handle<Object> object) {
    2102   208761155 :   CHECK(SerializingAllowed());
    2103   208761155 :   RefsMap::Entry* entry = refs_->LookupOrInsert(object.address(), zone());
    2104   208762384 :   ObjectData** data_storage = &(entry->value);
    2105   208762384 :   if (*data_storage == nullptr) {
    2106             :     // TODO(neis): Remove these Allow* once we serialize everything upfront.
    2107             :     AllowHandleAllocation handle_allocation;
    2108             :     AllowHandleDereference handle_dereference;
    2109    92270206 :     if (object->IsSmi()) {
    2110     1078498 :       new (zone()) ObjectData(this, data_storage, object, kSmi);
    2111             : #define CREATE_DATA_IF_MATCH(name)                                             \
    2112             :     } else if (object->Is##name()) {                                           \
    2113             :       new (zone()) name##Data(this, data_storage, Handle<name>::cast(object));
    2114  2332421334 :     HEAP_BROKER_OBJECT_LIST(CREATE_DATA_IF_MATCH)
    2115             : #undef CREATE_DATA_IF_MATCH
    2116             :     } else {
    2117           0 :       UNREACHABLE();
    2118             :     }
    2119             :   }
    2120   208761858 :   CHECK_NOT_NULL(*data_storage);
    2121   208761858 :   return (*data_storage);
    2122             : }
    2123             : // clang-format on
    2124             : 
    2125   165260865 : ObjectData* JSHeapBroker::GetOrCreateData(Object object) {
    2126   165260297 :   return GetOrCreateData(handle(object, isolate()));
    2127             : }
    2128             : 
    2129             : #define DEFINE_IS_AND_AS(Name)                                    \
    2130             :   bool ObjectRef::Is##Name() const { return data()->Is##Name(); } \
    2131             :   Name##Ref ObjectRef::As##Name() const {                         \
    2132             :     DCHECK(Is##Name());                                           \
    2133             :     return Name##Ref(broker(), data());                           \
    2134             :   }
    2135    81801381 : HEAP_BROKER_OBJECT_LIST(DEFINE_IS_AND_AS)
    2136             : #undef DEFINE_IS_AND_AS
    2137             : 
    2138    25374349 : bool ObjectRef::IsSmi() const { return data()->is_smi(); }
    2139             : 
    2140      708934 : int ObjectRef::AsSmi() const {
    2141             :   DCHECK(IsSmi());
    2142             :   // Handle-dereference is always allowed for Handle<Smi>.
    2143      708934 :   return Handle<Smi>::cast(object())->value();
    2144             : }
    2145             : 
    2146          16 : base::Optional<MapRef> JSObjectRef::GetObjectCreateMap() const {
    2147          16 :   if (broker()->mode() == JSHeapBroker::kDisabled) {
    2148             :     AllowHandleAllocation handle_allocation;
    2149             :     AllowHandleDereference allow_handle_dereference;
    2150             :     AllowHeapAllocation heap_allocation;
    2151             :     Handle<Map> instance_map;
    2152           0 :     if (Map::TryGetObjectCreateMap(broker()->isolate(), object())
    2153             :             .ToHandle(&instance_map)) {
    2154           0 :       return MapRef(broker(), instance_map);
    2155             :     } else {
    2156           0 :       return base::Optional<MapRef>();
    2157             :     }
    2158             :   }
    2159          16 :   MapData* map_data = data()->AsJSObject()->object_create_map();
    2160             :   return map_data != nullptr ? MapRef(broker(), map_data)
    2161          24 :                              : base::Optional<MapRef>();
    2162             : }
    2163             : 
    2164             : #define DEF_TESTER(Type, ...)                              \
    2165             :   bool MapRef::Is##Type##Map() const {                     \
    2166             :     return InstanceTypeChecker::Is##Type(instance_type()); \
    2167             :   }
    2168      694075 : INSTANCE_TYPE_CHECKERS(DEF_TESTER)
    2169             : #undef DEF_TESTER
    2170             : 
    2171        2361 : base::Optional<MapRef> MapRef::AsElementsKind(ElementsKind kind) const {
    2172        2361 :   if (broker()->mode() == JSHeapBroker::kDisabled) {
    2173             :     AllowHandleAllocation handle_allocation;
    2174             :     AllowHeapAllocation heap_allocation;
    2175             :     AllowHandleDereference allow_handle_dereference;
    2176             :     return MapRef(broker(),
    2177           0 :                   Map::AsElementsKind(broker()->isolate(), object(), kind));
    2178             :   }
    2179        2361 :   if (kind == elements_kind()) return *this;
    2180             :   const ZoneVector<MapData*>& elements_kind_generalizations =
    2181        1098 :       data()->AsMap()->elements_kind_generalizations();
    2182        1990 :   for (auto data : elements_kind_generalizations) {
    2183             :     MapRef map(broker(), data);
    2184        3088 :     if (map.elements_kind() == kind) return map;
    2185             :   }
    2186           0 :   return base::Optional<MapRef>();
    2187             : }
    2188             : 
    2189           0 : void MapRef::SerializeForElementLoad() {
    2190           0 :   CHECK_EQ(broker()->mode(), JSHeapBroker::kSerializing);
    2191           0 :   data()->AsMap()->SerializeForElementLoad(broker());
    2192           0 : }
    2193             : 
    2194           0 : void MapRef::SerializeForElementStore() {
    2195           0 :   CHECK_EQ(broker()->mode(), JSHeapBroker::kSerializing);
    2196           0 :   data()->AsMap()->SerializeForElementStore(broker());
    2197           0 : }
    2198             : 
    2199             : namespace {
    2200             : // This helper function has two modes. If {prototype_maps} is nullptr, the
    2201             : // prototype chain is serialized as necessary to determine the result.
    2202             : // Otherwise, the heap is untouched and the encountered prototypes are pushed
    2203             : // onto {prototype_maps}.
    2204           0 : bool HasOnlyStablePrototypesWithFastElementsHelper(
    2205             :     JSHeapBroker* broker, MapRef const& map,
    2206             :     ZoneVector<MapRef>* prototype_maps) {
    2207           0 :   for (MapRef prototype_map = map;;) {
    2208           0 :     if (prototype_maps == nullptr) prototype_map.SerializePrototype();
    2209           0 :     prototype_map = prototype_map.prototype().AsHeapObject().map();
    2210           0 :     if (prototype_map.oddball_type() == OddballType::kNull) return true;
    2211           0 :     if (!map.prototype().IsJSObject() || !prototype_map.is_stable() ||
    2212           0 :         !IsFastElementsKind(prototype_map.elements_kind())) {
    2213             :       return false;
    2214             :     }
    2215           0 :     if (prototype_maps != nullptr) prototype_maps->push_back(prototype_map);
    2216             :   }
    2217             : }
    2218             : }  // namespace
    2219             : 
    2220           0 : void MapData::SerializeForElementLoad(JSHeapBroker* broker) {
    2221           0 :   if (serialized_for_element_load_) return;
    2222           0 :   serialized_for_element_load_ = true;
    2223             : 
    2224           0 :   TraceScope tracer(broker, this, "MapData::SerializeForElementLoad");
    2225           0 :   SerializePrototype(broker);
    2226             : }
    2227             : 
    2228           0 : void MapData::SerializeForElementStore(JSHeapBroker* broker) {
    2229           0 :   if (serialized_for_element_store_) return;
    2230           0 :   serialized_for_element_store_ = true;
    2231             : 
    2232           0 :   TraceScope tracer(broker, this, "MapData::SerializeForElementStore");
    2233           0 :   HasOnlyStablePrototypesWithFastElementsHelper(broker, MapRef(broker, this),
    2234           0 :                                                 nullptr);
    2235             : }
    2236             : 
    2237        1949 : bool MapRef::HasOnlyStablePrototypesWithFastElements(
    2238             :     ZoneVector<MapRef>* prototype_maps) {
    2239        1949 :   for (MapRef prototype_map = *this;;) {
    2240        5740 :     if (prototype_maps == nullptr) prototype_map.SerializePrototype();
    2241        5740 :     prototype_map = prototype_map.prototype().AsHeapObject().map();
    2242        5740 :     if (prototype_map.oddball_type() == OddballType::kNull) return true;
    2243       11387 :     if (!prototype().IsJSObject() || !prototype_map.is_stable() ||
    2244        3791 :         !IsFastElementsKind(prototype_map.elements_kind())) {
    2245             :       return false;
    2246             :     }
    2247        3791 :     if (prototype_maps != nullptr) prototype_maps->push_back(prototype_map);
    2248             :   }
    2249             : }
    2250             : 
    2251        4106 : bool MapRef::supports_fast_array_iteration() const {
    2252        4106 :   if (broker()->mode() == JSHeapBroker::kDisabled) {
    2253             :     AllowHandleDereference allow_handle_dereference;
    2254             :     AllowHandleAllocation handle_allocation;
    2255        4106 :     return SupportsFastArrayIteration(broker()->isolate(), object());
    2256             :   }
    2257           0 :   return data()->AsMap()->supports_fast_array_iteration();
    2258             : }
    2259             : 
    2260        3354 : bool MapRef::supports_fast_array_resize() const {
    2261        3354 :   if (broker()->mode() == JSHeapBroker::kDisabled) {
    2262             :     AllowHandleDereference allow_handle_dereference;
    2263             :     AllowHandleAllocation handle_allocation;
    2264        3354 :     return SupportsFastArrayResize(broker()->isolate(), object());
    2265             :   }
    2266           0 :   return data()->AsMap()->supports_fast_array_resize();
    2267             : }
    2268             : 
    2269      125581 : bool MapRef::IsMapOfCurrentGlobalProxy() const {
    2270      125581 :   if (broker()->mode() == JSHeapBroker::kDisabled) {
    2271             :     AllowHandleDereference allow_handle_dereference;
    2272             :     AllowHandleAllocation handle_allocation;
    2273      251113 :     return object()->IsMapOfGlobalProxy(broker()->isolate()->native_context());
    2274             :   }
    2275          24 :   return data()->AsMap()->IsMapOfCurrentGlobalProxy();
    2276             : }
    2277             : 
    2278        5448 : int JSFunctionRef::InitialMapInstanceSizeWithMinSlack() const {
    2279        5448 :   if (broker()->mode() == JSHeapBroker::kDisabled) {
    2280             :     AllowHandleDereference allow_handle_dereference;
    2281             :     AllowHandleAllocation handle_allocation;
    2282           1 :     return object()->ComputeInstanceSizeWithMinSlack(broker()->isolate());
    2283             :   }
    2284       10894 :   return data()->AsJSFunction()->initial_map_instance_size_with_min_slack();
    2285             : }
    2286             : 
    2287             : // Not needed for TypedLowering.
    2288             : base::Optional<ScriptContextTableRef::LookupResult>
    2289           0 : ScriptContextTableRef::lookup(const NameRef& name) const {
    2290             :   AllowHandleAllocation handle_allocation;
    2291             :   AllowHandleDereference handle_dereference;
    2292           0 :   if (!name.IsString()) return {};
    2293             :   ScriptContextTable::LookupResult lookup_result;
    2294             :   auto table = object();
    2295           0 :   if (!ScriptContextTable::Lookup(broker()->isolate(), *table,
    2296           0 :                                   *name.AsString().object(), &lookup_result)) {
    2297           0 :     return {};
    2298             :   }
    2299             :   Handle<Context> script_context = ScriptContextTable::GetContext(
    2300           0 :       broker()->isolate(), table, lookup_result.context_index);
    2301             :   LookupResult result{ContextRef(broker(), script_context),
    2302           0 :                       lookup_result.mode == VariableMode::kConst,
    2303           0 :                       lookup_result.slot_index};
    2304             :   return result;
    2305             : }
    2306             : 
    2307    16920021 : OddballType MapRef::oddball_type() const {
    2308    16920021 :   if (instance_type() != ODDBALL_TYPE) {
    2309             :     return OddballType::kNone;
    2310             :   }
    2311             :   Factory* f = broker()->isolate()->factory();
    2312    10295307 :   if (equals(MapRef(broker(), f->undefined_map()))) {
    2313             :     return OddballType::kUndefined;
    2314             :   }
    2315     9363644 :   if (equals(MapRef(broker(), f->null_map()))) {
    2316             :     return OddballType::kNull;
    2317             :   }
    2318     9328290 :   if (equals(MapRef(broker(), f->boolean_map()))) {
    2319             :     return OddballType::kBoolean;
    2320             :   }
    2321     2523053 :   if (equals(MapRef(broker(), f->the_hole_map()))) {
    2322             :     return OddballType::kHole;
    2323             :   }
    2324      931388 :   if (equals(MapRef(broker(), f->uninitialized_map()))) {
    2325             :     return OddballType::kUninitialized;
    2326             :   }
    2327             :   DCHECK(equals(MapRef(broker(), f->termination_exception_map())) ||
    2328             :          equals(MapRef(broker(), f->arguments_marker_map())) ||
    2329             :          equals(MapRef(broker(), f->optimized_out_map())) ||
    2330             :          equals(MapRef(broker(), f->stale_register_map())));
    2331      929433 :   return OddballType::kOther;
    2332             : }
    2333             : 
    2334       52989 : ObjectRef FeedbackVectorRef::get(FeedbackSlot slot) const {
    2335       52989 :   if (broker()->mode() == JSHeapBroker::kDisabled) {
    2336             :     AllowHandleAllocation handle_allocation;
    2337             :     AllowHandleDereference handle_dereference;
    2338             :     Handle<Object> value(object()->Get(slot)->cast<Object>(),
    2339             :                          broker()->isolate());
    2340           0 :     return ObjectRef(broker(), value);
    2341             :   }
    2342             :   int i = FeedbackVector::GetIndex(slot);
    2343      158967 :   return ObjectRef(broker(), data()->AsFeedbackVector()->feedback().at(i));
    2344             : }
    2345             : 
    2346         128 : double JSObjectRef::RawFastDoublePropertyAt(FieldIndex index) const {
    2347         128 :   if (broker()->mode() == JSHeapBroker::kDisabled) {
    2348             :     AllowHandleDereference handle_dereference;
    2349             :     return object()->RawFastDoublePropertyAt(index);
    2350             :   }
    2351         128 :   JSObjectData* object_data = data()->AsJSObject();
    2352         128 :   CHECK(index.is_inobject());
    2353         256 :   return object_data->GetInobjectField(index.property_index()).AsDouble();
    2354             : }
    2355             : 
    2356        3202 : ObjectRef JSObjectRef::RawFastPropertyAt(FieldIndex index) const {
    2357        3202 :   if (broker()->mode() == JSHeapBroker::kDisabled) {
    2358             :     AllowHandleAllocation handle_allocation;
    2359             :     AllowHandleDereference handle_dereference;
    2360             :     return ObjectRef(broker(), handle(object()->RawFastPropertyAt(index),
    2361           0 :                                       broker()->isolate()));
    2362             :   }
    2363        3202 :   JSObjectData* object_data = data()->AsJSObject();
    2364        3202 :   CHECK(index.is_inobject());
    2365             :   return ObjectRef(
    2366             :       broker(),
    2367        6404 :       object_data->GetInobjectField(index.property_index()).AsObject());
    2368             : }
    2369             : 
    2370        6274 : bool AllocationSiteRef::IsFastLiteral() const {
    2371        6274 :   if (broker()->mode() == JSHeapBroker::kDisabled) {
    2372             :     AllowHeapAllocation allow_heap_allocation;  // For TryMigrateInstance.
    2373             :     AllowHandleAllocation allow_handle_allocation;
    2374             :     AllowHandleDereference allow_handle_dereference;
    2375             :     return IsInlinableFastLiteral(
    2376             :         handle(object()->boilerplate(), broker()->isolate()));
    2377             :   }
    2378        6274 :   return data()->AsAllocationSite()->IsFastLiteral();
    2379             : }
    2380             : 
    2381          40 : void JSObjectRef::EnsureElementsTenured() {
    2382          40 :   if (broker()->mode() == JSHeapBroker::kDisabled) {
    2383             :     AllowHandleAllocation allow_handle_allocation;
    2384             :     AllowHandleDereference allow_handle_dereference;
    2385             :     AllowHeapAllocation allow_heap_allocation;
    2386             : 
    2387           0 :     Handle<FixedArrayBase> object_elements = elements().object();
    2388           0 :     if (ObjectInYoungGeneration(*object_elements)) {
    2389             :       // If we would like to pretenure a fixed cow array, we must ensure that
    2390             :       // the array is already in old space, otherwise we'll create too many
    2391             :       // old-to-new-space pointers (overflowing the store buffer).
    2392             :       object_elements =
    2393             :           broker()->isolate()->factory()->CopyAndTenureFixedCOWArray(
    2394           0 :               Handle<FixedArray>::cast(object_elements));
    2395           0 :       object()->set_elements(*object_elements);
    2396             :     }
    2397             :     return;
    2398             :   }
    2399          80 :   CHECK(data()->AsJSObject()->cow_or_empty_elements_tenured());
    2400             : }
    2401             : 
    2402        3330 : FieldIndex MapRef::GetFieldIndexFor(int descriptor_index) const {
    2403        3330 :   if (broker()->mode() == JSHeapBroker::kDisabled) {
    2404             :     AllowHandleDereference allow_handle_dereference;
    2405           0 :     return FieldIndex::ForDescriptor(*object(), descriptor_index);
    2406             :   }
    2407        3330 :   DescriptorArrayData* descriptors = data()->AsMap()->instance_descriptors();
    2408        6660 :   return descriptors->contents().at(descriptor_index).field_index;
    2409             : }
    2410             : 
    2411       34572 : int MapRef::GetInObjectPropertyOffset(int i) const {
    2412       34572 :   if (broker()->mode() == JSHeapBroker::kDisabled) {
    2413             :     AllowHandleDereference allow_handle_dereference;
    2414             :     return object()->GetInObjectPropertyOffset(i);
    2415             :   }
    2416       34568 :   return (GetInObjectPropertiesStartInWords() + i) * kTaggedSize;
    2417             : }
    2418             : 
    2419      189849 : PropertyDetails MapRef::GetPropertyDetails(int descriptor_index) const {
    2420      189849 :   if (broker()->mode() == JSHeapBroker::kDisabled) {
    2421             :     AllowHandleDereference allow_handle_dereference;
    2422      182260 :     return object()->instance_descriptors()->GetDetails(descriptor_index);
    2423             :   }
    2424        7589 :   DescriptorArrayData* descriptors = data()->AsMap()->instance_descriptors();
    2425       15178 :   return descriptors->contents().at(descriptor_index).details;
    2426             : }
    2427             : 
    2428        3330 : NameRef MapRef::GetPropertyKey(int descriptor_index) const {
    2429        3330 :   if (broker()->mode() == JSHeapBroker::kDisabled) {
    2430             :     AllowHandleAllocation handle_allocation;
    2431             :     AllowHandleDereference allow_handle_dereference;
    2432             :     return NameRef(
    2433             :         broker(),
    2434             :         handle(object()->instance_descriptors()->GetKey(descriptor_index),
    2435           0 :                broker()->isolate()));
    2436             :   }
    2437        3330 :   DescriptorArrayData* descriptors = data()->AsMap()->instance_descriptors();
    2438        9990 :   return NameRef(broker(), descriptors->contents().at(descriptor_index).key);
    2439             : }
    2440             : 
    2441        4321 : bool MapRef::IsFixedCowArrayMap() const {
    2442             :   Handle<Map> fixed_cow_array_map =
    2443             :       ReadOnlyRoots(broker()->isolate()).fixed_cow_array_map_handle();
    2444        4321 :   return equals(MapRef(broker(), fixed_cow_array_map));
    2445             : }
    2446             : 
    2447      111515 : bool MapRef::IsPrimitiveMap() const {
    2448      119638 :   return instance_type() <= LAST_PRIMITIVE_TYPE;
    2449             : }
    2450             : 
    2451      186171 : MapRef MapRef::FindFieldOwner(int descriptor_index) const {
    2452      186171 :   if (broker()->mode() == JSHeapBroker::kDisabled) {
    2453             :     AllowHandleAllocation handle_allocation;
    2454             :     AllowHandleDereference allow_handle_dereference;
    2455             :     Handle<Map> owner(
    2456             :         object()->FindFieldOwner(broker()->isolate(), descriptor_index),
    2457      372278 :         broker()->isolate());
    2458      186139 :     return MapRef(broker(), owner);
    2459             :   }
    2460          32 :   DescriptorArrayData* descriptors = data()->AsMap()->instance_descriptors();
    2461             :   return MapRef(broker(),
    2462          96 :                 descriptors->contents().at(descriptor_index).field_owner);
    2463             : }
    2464             : 
    2465        3895 : ObjectRef MapRef::GetFieldType(int descriptor_index) const {
    2466        3895 :   if (broker()->mode() == JSHeapBroker::kDisabled) {
    2467             :     AllowHandleAllocation handle_allocation;
    2468             :     AllowHandleDereference allow_handle_dereference;
    2469             :     Handle<FieldType> field_type(
    2470        7758 :         object()->instance_descriptors()->GetFieldType(descriptor_index),
    2471        3879 :         broker()->isolate());
    2472        3879 :     return ObjectRef(broker(), field_type);
    2473             :   }
    2474          16 :   DescriptorArrayData* descriptors = data()->AsMap()->instance_descriptors();
    2475             :   return ObjectRef(broker(),
    2476          48 :                    descriptors->contents().at(descriptor_index).field_type);
    2477             : }
    2478             : 
    2479        3330 : bool MapRef::IsUnboxedDoubleField(int descriptor_index) const {
    2480        3330 :   if (broker()->mode() == JSHeapBroker::kDisabled) {
    2481             :     AllowHandleDereference allow_handle_dereference;
    2482           0 :     return object()->IsUnboxedDoubleField(
    2483           0 :         FieldIndex::ForDescriptor(*object(), descriptor_index));
    2484             :   }
    2485        3330 :   DescriptorArrayData* descriptors = data()->AsMap()->instance_descriptors();
    2486        6660 :   return descriptors->contents().at(descriptor_index).is_unboxed_double_field;
    2487             : }
    2488             : 
    2489         104 : uint16_t StringRef::GetFirstChar() {
    2490         104 :   if (broker()->mode() == JSHeapBroker::kDisabled) {
    2491             :     AllowHandleDereference allow_handle_dereference;
    2492             :     return object()->Get(0);
    2493             :   }
    2494         104 :   return data()->AsString()->first_char();
    2495             : }
    2496             : 
    2497         842 : base::Optional<double> StringRef::ToNumber() {
    2498         842 :   if (broker()->mode() == JSHeapBroker::kDisabled) {
    2499             :     AllowHandleDereference allow_handle_dereference;
    2500             :     AllowHandleAllocation allow_handle_allocation;
    2501             :     AllowHeapAllocation allow_heap_allocation;
    2502             :     int flags = ALLOW_HEX | ALLOW_OCTAL | ALLOW_BINARY;
    2503           0 :     return StringToDouble(broker()->isolate(), object(), flags);
    2504             :   }
    2505         842 :   return data()->AsString()->to_number();
    2506             : }
    2507             : 
    2508        7751 : ObjectRef FixedArrayRef::get(int i) const {
    2509        7751 :   if (broker()->mode() == JSHeapBroker::kDisabled) {
    2510             :     AllowHandleAllocation handle_allocation;
    2511             :     AllowHandleDereference allow_handle_dereference;
    2512         202 :     return ObjectRef(broker(), handle(object()->get(i), broker()->isolate()));
    2513             :   }
    2514       15098 :   return ObjectRef(broker(), data()->AsFixedArray()->Get(i));
    2515             : }
    2516             : 
    2517        7211 : bool FixedDoubleArrayRef::is_the_hole(int i) const {
    2518        7211 :   if (broker()->mode() == JSHeapBroker::kDisabled) {
    2519             :     AllowHandleDereference allow_handle_dereference;
    2520             :     return object()->is_the_hole(i);
    2521             :   }
    2522       14422 :   return data()->AsFixedDoubleArray()->Get(i).is_hole_nan();
    2523             : }
    2524             : 
    2525        7112 : double FixedDoubleArrayRef::get_scalar(int i) const {
    2526        7112 :   if (broker()->mode() == JSHeapBroker::kDisabled) {
    2527             :     AllowHandleDereference allow_handle_dereference;
    2528             :     return object()->get_scalar(i);
    2529             :   }
    2530       14224 :   CHECK(!data()->AsFixedDoubleArray()->Get(i).is_hole_nan());
    2531        7112 :   return data()->AsFixedDoubleArray()->Get(i).get_scalar();
    2532             : }
    2533             : 
    2534             : #define IF_BROKER_DISABLED_ACCESS_HANDLE_C(holder, name) \
    2535             :   if (broker()->mode() == JSHeapBroker::kDisabled) {     \
    2536             :     AllowHandleAllocation handle_allocation;             \
    2537             :     AllowHandleDereference allow_handle_dereference;     \
    2538             :     return object()->name();                             \
    2539             :   }
    2540             : 
    2541             : #define IF_BROKER_DISABLED_ACCESS_HANDLE(holder, result, name)         \
    2542             :   if (broker()->mode() == JSHeapBroker::kDisabled) {                   \
    2543             :     AllowHandleAllocation handle_allocation;                           \
    2544             :     AllowHandleDereference allow_handle_dereference;                   \
    2545             :     return result##Ref(broker(),                                       \
    2546             :                        handle(object()->name(), broker()->isolate())); \
    2547             :   }
    2548             : 
    2549             : // Macros for definining a const getter that, depending on the broker mode,
    2550             : // either looks into the handle or into the serialized data.
    2551             : #define BIMODAL_ACCESSOR(holder, result, name)                             \
    2552             :   result##Ref holder##Ref::name() const {                                  \
    2553             :     IF_BROKER_DISABLED_ACCESS_HANDLE(holder, result, name);                \
    2554             :     return result##Ref(broker(), ObjectRef::data()->As##holder()->name()); \
    2555             :   }
    2556             : 
    2557             : // Like above except that the result type is not an XYZRef.
    2558             : #define BIMODAL_ACCESSOR_C(holder, result, name)      \
    2559             :   result holder##Ref::name() const {                  \
    2560             :     IF_BROKER_DISABLED_ACCESS_HANDLE_C(holder, name); \
    2561             :     return ObjectRef::data()->As##holder()->name();   \
    2562             :   }
    2563             : 
    2564             : // Like above but for BitFields.
    2565             : #define BIMODAL_ACCESSOR_B(holder, field, name, BitField)              \
    2566             :   typename BitField::FieldType holder##Ref::name() const {             \
    2567             :     IF_BROKER_DISABLED_ACCESS_HANDLE_C(holder, name);                  \
    2568             :     return BitField::decode(ObjectRef::data()->As##holder()->field()); \
    2569             :   }
    2570             : 
    2571       37692 : BIMODAL_ACCESSOR(AllocationSite, Object, nested_site)
    2572        1611 : BIMODAL_ACCESSOR_C(AllocationSite, bool, CanInlineCall)
    2573       23355 : BIMODAL_ACCESSOR_C(AllocationSite, bool, PointsToLiteral)
    2574        9018 : BIMODAL_ACCESSOR_C(AllocationSite, ElementsKind, GetElementsKind)
    2575       15116 : BIMODAL_ACCESSOR_C(AllocationSite, AllocationType, GetAllocationType)
    2576             : 
    2577        1515 : BIMODAL_ACCESSOR_C(BytecodeArray, int, register_count)
    2578             : 
    2579       75783 : BIMODAL_ACCESSOR(Cell, Object, value)
    2580             : 
    2581   203850022 : BIMODAL_ACCESSOR(HeapObject, Map, map)
    2582             : 
    2583       12729 : BIMODAL_ACCESSOR(JSArray, Object, length)
    2584             : 
    2585         648 : BIMODAL_ACCESSOR(JSBoundFunction, Object, bound_target_function)
    2586         477 : BIMODAL_ACCESSOR(JSBoundFunction, Object, bound_this)
    2587         648 : BIMODAL_ACCESSOR(JSBoundFunction, FixedArray, bound_arguments)
    2588             : 
    2589         848 : BIMODAL_ACCESSOR_C(JSDataView, size_t, byte_length)
    2590         424 : BIMODAL_ACCESSOR_C(JSDataView, size_t, byte_offset)
    2591             : 
    2592         232 : BIMODAL_ACCESSOR_C(JSFunction, bool, has_feedback_vector)
    2593       21809 : BIMODAL_ACCESSOR_C(JSFunction, bool, has_initial_map)
    2594        4560 : BIMODAL_ACCESSOR_C(JSFunction, bool, has_prototype)
    2595        4458 : BIMODAL_ACCESSOR_C(JSFunction, bool, PrototypeRequiresRuntimeLookup)
    2596        4797 : BIMODAL_ACCESSOR(JSFunction, Context, context)
    2597     1002285 : BIMODAL_ACCESSOR(JSFunction, NativeContext, native_context)
    2598       89943 : BIMODAL_ACCESSOR(JSFunction, Map, initial_map)
    2599        5396 : BIMODAL_ACCESSOR(JSFunction, Object, prototype)
    2600     1667877 : BIMODAL_ACCESSOR(JSFunction, SharedFunctionInfo, shared)
    2601         348 : BIMODAL_ACCESSOR(JSFunction, FeedbackVector, feedback_vector)
    2602             : 
    2603        8420 : BIMODAL_ACCESSOR_C(JSTypedArray, bool, is_on_heap)
    2604        2692 : BIMODAL_ACCESSOR_C(JSTypedArray, size_t, length)
    2605        4038 : BIMODAL_ACCESSOR(JSTypedArray, HeapObject, buffer)
    2606             : 
    2607     2168435 : BIMODAL_ACCESSOR_B(Map, bit_field2, elements_kind, Map::ElementsKindBits)
    2608           0 : BIMODAL_ACCESSOR_B(Map, bit_field2, is_extensible, Map::IsExtensibleBit)
    2609           0 : BIMODAL_ACCESSOR_B(Map, bit_field3, is_deprecated, Map::IsDeprecatedBit)
    2610         410 : BIMODAL_ACCESSOR_B(Map, bit_field3, is_dictionary_map, Map::IsDictionaryMapBit)
    2611       28004 : BIMODAL_ACCESSOR_B(Map, bit_field3, NumberOfOwnDescriptors,
    2612             :                    Map::NumberOfOwnDescriptorsBits)
    2613         296 : BIMODAL_ACCESSOR_B(Map, bit_field3, has_hidden_prototype,
    2614             :                    Map::HasHiddenPrototypeBit)
    2615      185986 : BIMODAL_ACCESSOR_B(Map, bit_field3, is_migration_target,
    2616             :                    Map::IsMigrationTargetBit)
    2617      157862 : BIMODAL_ACCESSOR_B(Map, bit_field, has_prototype_slot, Map::HasPrototypeSlotBit)
    2618      108736 : BIMODAL_ACCESSOR_B(Map, bit_field, is_access_check_needed,
    2619             :                    Map::IsAccessCheckNeededBit)
    2620    66872856 : BIMODAL_ACCESSOR_B(Map, bit_field, is_callable, Map::IsCallableBit)
    2621      105270 : BIMODAL_ACCESSOR_B(Map, bit_field, has_indexed_interceptor,
    2622             :                    Map::HasIndexedInterceptorBit)
    2623       49164 : BIMODAL_ACCESSOR_B(Map, bit_field, is_constructor, Map::IsConstructorBit)
    2624    66845120 : BIMODAL_ACCESSOR_B(Map, bit_field, is_undetectable, Map::IsUndetectableBit)
    2625      143496 : BIMODAL_ACCESSOR_C(Map, int, instance_size)
    2626        6885 : BIMODAL_ACCESSOR_C(Map, int, NextFreePropertyIndex)
    2627       65955 : BIMODAL_ACCESSOR_C(Map, int, UnusedPropertyFields)
    2628      307062 : BIMODAL_ACCESSOR(Map, HeapObject, prototype)
    2629   102147358 : BIMODAL_ACCESSOR_C(Map, InstanceType, instance_type)
    2630       28726 : BIMODAL_ACCESSOR(Map, Object, GetConstructor)
    2631       87940 : BIMODAL_ACCESSOR(Map, HeapObject, GetBackPointer)
    2632             : 
    2633             : #define DEF_NATIVE_CONTEXT_ACCESSOR(type, name) \
    2634             :   BIMODAL_ACCESSOR(NativeContext, type, name)
    2635      465984 : BROKER_NATIVE_CONTEXT_FIELDS(DEF_NATIVE_CONTEXT_ACCESSOR)
    2636             : #undef DEF_NATIVE_CONTEXT_ACCESSOR
    2637             : 
    2638      645786 : BIMODAL_ACCESSOR(PropertyCell, Object, value)
    2639     1131798 : BIMODAL_ACCESSOR_C(PropertyCell, PropertyDetails, property_details)
    2640             : 
    2641         384 : BIMODAL_ACCESSOR(FunctionTemplateInfo, Object, call_code)
    2642             : 
    2643         384 : BIMODAL_ACCESSOR(CallHandlerInfo, Object, data)
    2644             : 
    2645      280965 : BIMODAL_ACCESSOR_C(SharedFunctionInfo, int, builtin_id)
    2646      437983 : BIMODAL_ACCESSOR(SharedFunctionInfo, BytecodeArray, GetBytecodeArray)
    2647             : #define DEF_SFI_ACCESSOR(type, name) \
    2648             :   BIMODAL_ACCESSOR_C(SharedFunctionInfo, type, name)
    2649     3438125 : BROKER_SFI_FIELDS(DEF_SFI_ACCESSOR)
    2650             : #undef DEF_SFI_ACCESSOR
    2651             : 
    2652      164225 : BIMODAL_ACCESSOR_C(String, int, length)
    2653             : 
    2654        1346 : void* JSTypedArrayRef::elements_external_pointer() const {
    2655        1346 :   if (broker()->mode() == JSHeapBroker::kDisabled) {
    2656             :     AllowHandleDereference allow_handle_dereference;
    2657             :     return FixedTypedArrayBase::cast(object()->elements())->external_pointer();
    2658             :   }
    2659           0 :   return data()->AsJSTypedArray()->elements_external_pointer();
    2660             : }
    2661             : 
    2662          32 : bool MapRef::IsInobjectSlackTrackingInProgress() const {
    2663          32 :   IF_BROKER_DISABLED_ACCESS_HANDLE_C(Map, IsInobjectSlackTrackingInProgress);
    2664          32 :   return Map::ConstructionCounterBits::decode(data()->AsMap()->bit_field3()) !=
    2665          32 :          Map::kNoSlackTracking;
    2666             : }
    2667             : 
    2668        8123 : int MapRef::constructor_function_index() const {
    2669        8123 :   IF_BROKER_DISABLED_ACCESS_HANDLE_C(Map, GetConstructorFunctionIndex);
    2670           0 :   CHECK(IsPrimitiveMap());
    2671           0 :   return data()->AsMap()->constructor_function_index();
    2672             : }
    2673             : 
    2674      232152 : bool MapRef::is_stable() const {
    2675      232152 :   IF_BROKER_DISABLED_ACCESS_HANDLE_C(Map, is_stable);
    2676       27386 :   return !Map::IsUnstableBit::decode(data()->AsMap()->bit_field3());
    2677             : }
    2678             : 
    2679       22030 : bool MapRef::CanBeDeprecated() const {
    2680       44060 :   IF_BROKER_DISABLED_ACCESS_HANDLE_C(Map, CanBeDeprecated);
    2681           0 :   CHECK_GT(NumberOfOwnDescriptors(), 0);
    2682           0 :   return data()->AsMap()->can_be_deprecated();
    2683             : }
    2684             : 
    2685      164472 : bool MapRef::CanTransition() const {
    2686      164472 :   IF_BROKER_DISABLED_ACCESS_HANDLE_C(Map, CanTransition);
    2687          43 :   return data()->AsMap()->can_transition();
    2688             : }
    2689             : 
    2690       40982 : int MapRef::GetInObjectPropertiesStartInWords() const {
    2691       40982 :   IF_BROKER_DISABLED_ACCESS_HANDLE_C(Map, GetInObjectPropertiesStartInWords);
    2692       81962 :   return data()->AsMap()->in_object_properties_start_in_words();
    2693             : }
    2694             : 
    2695       79217 : int MapRef::GetInObjectProperties() const {
    2696       81656 :   IF_BROKER_DISABLED_ACCESS_HANDLE_C(Map, GetInObjectProperties);
    2697      153556 :   return data()->AsMap()->in_object_properties();
    2698             : }
    2699             : 
    2700        9400 : int ScopeInfoRef::ContextLength() const {
    2701        9400 :   IF_BROKER_DISABLED_ACCESS_HANDLE_C(ScopeInfo, ContextLength);
    2702        9400 :   return data()->AsScopeInfo()->context_length();
    2703             : }
    2704             : 
    2705           0 : bool StringRef::IsExternalString() const {
    2706           0 :   IF_BROKER_DISABLED_ACCESS_HANDLE_C(String, IsExternalString);
    2707           0 :   return data()->AsString()->is_external_string();
    2708             : }
    2709             : 
    2710         128 : Address CallHandlerInfoRef::callback() const {
    2711         128 :   if (broker()->mode() == JSHeapBroker::kDisabled) {
    2712             :     return v8::ToCData<Address>(object()->callback());
    2713             :   }
    2714           0 :   return HeapObjectRef::data()->AsCallHandlerInfo()->callback();
    2715             : }
    2716             : 
    2717           0 : bool StringRef::IsSeqString() const {
    2718           0 :   IF_BROKER_DISABLED_ACCESS_HANDLE_C(String, IsSeqString);
    2719           0 :   return data()->AsString()->is_seq_string();
    2720             : }
    2721             : 
    2722       32152 : MapRef NativeContextRef::GetFunctionMapFromIndex(int index) const {
    2723             :   DCHECK_GE(index, Context::FIRST_FUNCTION_MAP_INDEX);
    2724             :   DCHECK_LE(index, Context::LAST_FUNCTION_MAP_INDEX);
    2725       32152 :   if (broker()->mode() == JSHeapBroker::kDisabled) {
    2726           0 :     return get(index).AsMap();
    2727             :   }
    2728       32152 :   return MapRef(broker(), data()->AsNativeContext()->function_maps().at(
    2729       96456 :                               index - Context::FIRST_FUNCTION_MAP_INDEX));
    2730             : }
    2731             : 
    2732        2118 : MapRef NativeContextRef::GetInitialJSArrayMap(ElementsKind kind) const {
    2733        2118 :   switch (kind) {
    2734             :     case PACKED_SMI_ELEMENTS:
    2735         910 :       return js_array_packed_smi_elements_map();
    2736             :     case HOLEY_SMI_ELEMENTS:
    2737          46 :       return js_array_holey_smi_elements_map();
    2738             :     case PACKED_DOUBLE_ELEMENTS:
    2739          42 :       return js_array_packed_double_elements_map();
    2740             :     case HOLEY_DOUBLE_ELEMENTS:
    2741         354 :       return js_array_holey_double_elements_map();
    2742             :     case PACKED_ELEMENTS:
    2743         430 :       return js_array_packed_elements_map();
    2744             :     case HOLEY_ELEMENTS:
    2745         336 :       return js_array_holey_elements_map();
    2746             :     default:
    2747           0 :       UNREACHABLE();
    2748             :   }
    2749             : }
    2750             : 
    2751        8123 : base::Optional<JSFunctionRef> NativeContextRef::GetConstructorFunction(
    2752             :     const MapRef& map) const {
    2753        8123 :   CHECK(map.IsPrimitiveMap());
    2754        8123 :   switch (map.constructor_function_index()) {
    2755             :     case Map::kNoConstructorFunctionIndex:
    2756             :       return base::nullopt;
    2757             :     case Context::BIGINT_FUNCTION_INDEX:
    2758           0 :       return bigint_function();
    2759             :     case Context::BOOLEAN_FUNCTION_INDEX:
    2760        1054 :       return boolean_function();
    2761             :     case Context::NUMBER_FUNCTION_INDEX:
    2762        2768 :       return number_function();
    2763             :     case Context::STRING_FUNCTION_INDEX:
    2764       12354 :       return string_function();
    2765             :     case Context::SYMBOL_FUNCTION_INDEX:
    2766          70 :       return symbol_function();
    2767             :     default:
    2768           0 :       UNREACHABLE();
    2769             :   }
    2770             : }
    2771             : 
    2772         159 : bool ObjectRef::IsNullOrUndefined() const {
    2773         159 :   if (IsSmi()) return false;
    2774         159 :   OddballType type = AsHeapObject().map().oddball_type();
    2775         159 :   return type == OddballType::kNull || type == OddballType::kUndefined;
    2776             : }
    2777             : 
    2778      120580 : bool ObjectRef::BooleanValue() const {
    2779      120580 :   if (broker()->mode() == JSHeapBroker::kDisabled) {
    2780             :     AllowHandleDereference allow_handle_dereference;
    2781        9613 :     return object()->BooleanValue(broker()->isolate());
    2782             :   }
    2783      110968 :   return IsSmi() ? (AsSmi() != 0) : data()->AsHeapObject()->boolean_value();
    2784             : }
    2785             : 
    2786        1086 : Maybe<double> ObjectRef::OddballToNumber() const {
    2787        1086 :   OddballType type = AsHeapObject().map().oddball_type();
    2788             : 
    2789        1086 :   switch (type) {
    2790             :     case OddballType::kBoolean: {
    2791             :       ObjectRef true_ref(broker(),
    2792         494 :                          broker()->isolate()->factory()->true_value());
    2793         494 :       return this->equals(true_ref) ? Just(1.0) : Just(0.0);
    2794             :       break;
    2795             :     }
    2796             :     case OddballType::kUndefined: {
    2797             :       return Just(std::numeric_limits<double>::quiet_NaN());
    2798             :       break;
    2799             :     }
    2800             :     case OddballType::kNull: {
    2801             :       return Just(0.0);
    2802             :       break;
    2803             :     }
    2804             :     default: {
    2805             :       return Nothing<double>();
    2806             :       break;
    2807             :     }
    2808             :   }
    2809             : }
    2810             : 
    2811        1565 : base::Optional<ObjectRef> ObjectRef::GetOwnConstantElement(
    2812             :     uint32_t index, bool serialize) const {
    2813        1565 :   if (broker()->mode() == JSHeapBroker::kDisabled) {
    2814          73 :     return (IsJSObject() || IsString())
    2815             :                ? GetOwnElementFromHeap(broker(), object(), index, true)
    2816        3106 :                : base::nullopt;
    2817             :   }
    2818             :   ObjectData* element = nullptr;
    2819           9 :   if (IsJSObject()) {
    2820             :     element =
    2821          18 :         data()->AsJSObject()->GetOwnConstantElement(broker(), index, serialize);
    2822           0 :   } else if (IsString()) {
    2823           0 :     element = data()->AsString()->GetCharAsString(broker(), index, serialize);
    2824             :   }
    2825           9 :   if (element == nullptr) return base::nullopt;
    2826             :   return ObjectRef(broker(), element);
    2827             : }
    2828             : 
    2829        1038 : base::Optional<ObjectRef> JSArrayRef::GetOwnCowElement(uint32_t index,
    2830             :                                                        bool serialize) const {
    2831        1038 :   if (broker()->mode() == JSHeapBroker::kDisabled) {
    2832        1038 :     if (!object()->elements()->IsCowArray()) return base::nullopt;
    2833          92 :     return GetOwnElementFromHeap(broker(), object(), index, false);
    2834             :   }
    2835             : 
    2836           0 :   if (serialize) {
    2837           0 :     data()->AsJSObject()->SerializeElements(broker());
    2838           0 :   } else if (!data()->AsJSObject()->serialized_elements()) {
    2839           0 :     TRACE(broker(), "'elements' on data " << this);
    2840             :     return base::nullopt;
    2841             :   }
    2842           0 :   if (!elements().map().IsFixedCowArrayMap()) return base::nullopt;
    2843             : 
    2844             :   ObjectData* element =
    2845           0 :       data()->AsJSArray()->GetOwnElement(broker(), index, serialize);
    2846           0 :   if (element == nullptr) return base::nullopt;
    2847             :   return ObjectRef(broker(), element);
    2848             : }
    2849             : 
    2850     2723081 : double HeapNumberRef::value() const {
    2851     2723081 :   IF_BROKER_DISABLED_ACCESS_HANDLE_C(HeapNumber, value);
    2852         146 :   return data()->AsHeapNumber()->value();
    2853             : }
    2854             : 
    2855           0 : double MutableHeapNumberRef::value() const {
    2856           0 :   IF_BROKER_DISABLED_ACCESS_HANDLE_C(MutableHeapNumber, value);
    2857           0 :   return data()->AsMutableHeapNumber()->value();
    2858             : }
    2859             : 
    2860         138 : CellRef ModuleRef::GetCell(int cell_index) const {
    2861         138 :   if (broker()->mode() == JSHeapBroker::kDisabled) {
    2862             :     AllowHandleAllocation handle_allocation;
    2863             :     AllowHandleDereference allow_handle_dereference;
    2864             :     return CellRef(broker(),
    2865           0 :                    handle(object()->GetCell(cell_index), broker()->isolate()));
    2866             :   }
    2867         276 :   return CellRef(broker(), data()->AsModule()->GetCell(cell_index));
    2868             : }
    2869             : 
    2870    72479944 : ObjectRef::ObjectRef(JSHeapBroker* broker, Handle<Object> object)
    2871    72479944 :     : broker_(broker) {
    2872    72479944 :   switch (broker->mode()) {
    2873             :     case JSHeapBroker::kSerialized:
    2874    51583409 :       data_ = broker->GetData(object);
    2875    51583409 :       break;
    2876             :     case JSHeapBroker::kSerializing:
    2877     8872048 :       data_ = broker->GetOrCreateData(object);
    2878     8872042 :       break;
    2879             :     case JSHeapBroker::kDisabled: {
    2880             :       RefsMap::Entry* entry =
    2881    12024947 :           broker->refs_->LookupOrInsert(object.address(), broker->zone());
    2882    12024947 :       ObjectData** storage = &(entry->value);
    2883    12024947 :       if (*storage == nullptr) {
    2884             :         AllowHandleDereference handle_dereference;
    2885             :         entry->value = new (broker->zone())
    2886             :             ObjectData(broker, storage, object,
    2887     5947662 :                        object->IsSmi() ? kSmi : kUnserializedHeapObject);
    2888             :       }
    2889    12024945 :       data_ = *storage;
    2890    12024945 :       break;
    2891             :     }
    2892             :     case JSHeapBroker::kRetired:
    2893           0 :       UNREACHABLE();
    2894             :   }
    2895    72480046 :   CHECK_WITH_MSG(data_ != nullptr, "Object is not known to the heap broker");
    2896    72480046 : }
    2897             : 
    2898             : namespace {
    2899     2716803 : OddballType GetOddballType(Isolate* isolate, Map map) {
    2900     2716803 :   if (map->instance_type() != ODDBALL_TYPE) {
    2901             :     return OddballType::kNone;
    2902             :   }
    2903             :   ReadOnlyRoots roots(isolate);
    2904      592795 :   if (map == roots.undefined_map()) {
    2905             :     return OddballType::kUndefined;
    2906             :   }
    2907      554785 :   if (map == roots.null_map()) {
    2908             :     return OddballType::kNull;
    2909             :   }
    2910      554607 :   if (map == roots.boolean_map()) {
    2911             :     return OddballType::kBoolean;
    2912             :   }
    2913      540728 :   if (map == roots.the_hole_map()) {
    2914             :     return OddballType::kHole;
    2915             :   }
    2916      540049 :   if (map == roots.uninitialized_map()) {
    2917             :     return OddballType::kUninitialized;
    2918             :   }
    2919             :   DCHECK(map == roots.termination_exception_map() ||
    2920             :          map == roots.arguments_marker_map() ||
    2921             :          map == roots.optimized_out_map() || map == roots.stale_register_map());
    2922           0 :   return OddballType::kOther;
    2923             : }
    2924             : }  // namespace
    2925             : 
    2926    19424809 : HeapObjectType HeapObjectRef::GetHeapObjectType() const {
    2927    19424809 :   if (broker()->mode() == JSHeapBroker::kDisabled) {
    2928             :     AllowHandleDereference handle_dereference;
    2929             :     Map map = Handle<HeapObject>::cast(object())->map();
    2930             :     HeapObjectType::Flags flags(0);
    2931     2716803 :     if (map->is_undetectable()) flags |= HeapObjectType::kUndetectable;
    2932     2716803 :     if (map->is_callable()) flags |= HeapObjectType::kCallable;
    2933             :     return HeapObjectType(map->instance_type(), flags,
    2934     5433606 :                           GetOddballType(broker()->isolate(), map));
    2935             :   }
    2936             :   HeapObjectType::Flags flags(0);
    2937    16708006 :   if (map().is_undetectable()) flags |= HeapObjectType::kUndetectable;
    2938    16707976 :   if (map().is_callable()) flags |= HeapObjectType::kCallable;
    2939    16707954 :   return HeapObjectType(map().instance_type(), flags, map().oddball_type());
    2940             : }
    2941       12337 : base::Optional<JSObjectRef> AllocationSiteRef::boilerplate() const {
    2942       12337 :   if (broker()->mode() == JSHeapBroker::kDisabled) {
    2943             :     AllowHandleAllocation handle_allocation;
    2944             :     AllowHandleDereference allow_handle_dereference;
    2945             :     return JSObjectRef(broker(),
    2946           0 :                        handle(object()->boilerplate(), broker()->isolate()));
    2947             :   }
    2948       12337 :   JSObjectData* boilerplate = data()->AsAllocationSite()->boilerplate();
    2949       12337 :   if (boilerplate) {
    2950             :     return JSObjectRef(broker(), boilerplate);
    2951             :   } else {
    2952             :     return base::nullopt;
    2953             :   }
    2954             : }
    2955             : 
    2956       10525 : ElementsKind JSObjectRef::GetElementsKind() const {
    2957       10525 :   return map().elements_kind();
    2958             : }
    2959             : 
    2960        7709 : FixedArrayBaseRef JSObjectRef::elements() const {
    2961        7709 :   if (broker()->mode() == JSHeapBroker::kDisabled) {
    2962             :     AllowHandleAllocation handle_allocation;
    2963             :     AllowHandleDereference allow_handle_dereference;
    2964             :     return FixedArrayBaseRef(broker(),
    2965          92 :                              handle(object()->elements(), broker()->isolate()));
    2966             :   }
    2967       15234 :   return FixedArrayBaseRef(broker(), data()->AsJSObject()->elements());
    2968             : }
    2969             : 
    2970      289920 : int FixedArrayBaseRef::length() const {
    2971      289920 :   IF_BROKER_DISABLED_ACCESS_HANDLE_C(FixedArrayBase, length);
    2972       14216 :   return data()->AsFixedArrayBase()->length();
    2973             : }
    2974             : 
    2975        7549 : ObjectData* FixedArrayData::Get(int i) const {
    2976        7549 :   CHECK_LT(i, static_cast<int>(contents_.size()));
    2977       15098 :   CHECK_NOT_NULL(contents_[i]);
    2978        7549 :   return contents_[i];
    2979             : }
    2980             : 
    2981       21435 : Float64 FixedDoubleArrayData::Get(int i) const {
    2982       21435 :   CHECK_LT(i, static_cast<int>(contents_.size()));
    2983       42870 :   return contents_[i];
    2984             : }
    2985             : 
    2986       53205 : void FeedbackVectorRef::SerializeSlots() {
    2987       53205 :   data()->AsFeedbackVector()->SerializeSlots(broker());
    2988       53205 : }
    2989             : 
    2990           0 : bool NameRef::IsUniqueName() const {
    2991             :   // Must match Name::IsUniqueName.
    2992           0 :   return IsInternalizedString() || IsSymbol();
    2993             : }
    2994             : 
    2995         576 : ObjectRef JSRegExpRef::data() const {
    2996         576 :   IF_BROKER_DISABLED_ACCESS_HANDLE(JSRegExp, Object, data);
    2997        1152 :   return ObjectRef(broker(), ObjectRef::data()->AsJSRegExp()->data());
    2998             : }
    2999             : 
    3000         576 : ObjectRef JSRegExpRef::flags() const {
    3001         576 :   IF_BROKER_DISABLED_ACCESS_HANDLE(JSRegExp, Object, flags);
    3002        1152 :   return ObjectRef(broker(), ObjectRef::data()->AsJSRegExp()->flags());
    3003             : }
    3004             : 
    3005         576 : ObjectRef JSRegExpRef::last_index() const {
    3006         576 :   IF_BROKER_DISABLED_ACCESS_HANDLE(JSRegExp, Object, last_index);
    3007        1152 :   return ObjectRef(broker(), ObjectRef::data()->AsJSRegExp()->last_index());
    3008             : }
    3009             : 
    3010         576 : ObjectRef JSRegExpRef::raw_properties_or_hash() const {
    3011         576 :   IF_BROKER_DISABLED_ACCESS_HANDLE(JSRegExp, Object, raw_properties_or_hash);
    3012             :   return ObjectRef(broker(),
    3013        1152 :                    ObjectRef::data()->AsJSRegExp()->raw_properties_or_hash());
    3014             : }
    3015             : 
    3016         576 : ObjectRef JSRegExpRef::source() const {
    3017         576 :   IF_BROKER_DISABLED_ACCESS_HANDLE(JSRegExp, Object, source);
    3018        1152 :   return ObjectRef(broker(), ObjectRef::data()->AsJSRegExp()->source());
    3019             : }
    3020             : 
    3021      921499 : Handle<Object> ObjectRef::object() const { return data_->object(); }
    3022             : 
    3023             : #define DEF_OBJECT_GETTER(T)                                                 \
    3024             :   Handle<T> T##Ref::object() const {                                         \
    3025             :     return Handle<T>(reinterpret_cast<Address*>(data_->object().address())); \
    3026             :   }
    3027    41611993 : HEAP_BROKER_OBJECT_LIST(DEF_OBJECT_GETTER)
    3028             : #undef DEF_OBJECT_GETTER
    3029             : 
    3030   441743878 : JSHeapBroker* ObjectRef::broker() const { return broker_; }
    3031             : 
    3032   216588772 : ObjectData* ObjectRef::data() const {
    3033   216588772 :   switch (broker()->mode()) {
    3034             :     case JSHeapBroker::kDisabled:
    3035    22348508 :       CHECK_NE(data_->kind(), kSerializedHeapObject);
    3036             :       return data_;
    3037             :     case JSHeapBroker::kSerializing:
    3038             :     case JSHeapBroker::kSerialized:
    3039   194240264 :       CHECK_NE(data_->kind(), kUnserializedHeapObject);
    3040             :       return data_;
    3041             :     case JSHeapBroker::kRetired:
    3042           0 :       UNREACHABLE();
    3043             :   }
    3044           0 : }
    3045             : 
    3046           0 : Reduction NoChangeBecauseOfMissingData(JSHeapBroker* broker,
    3047             :                                        const char* function, int line) {
    3048           0 :   TRACE_MISSING(broker, "data in function " << function << " at line " << line);
    3049           0 :   return AdvancedReducer::NoChange();
    3050             : }
    3051             : 
    3052      464120 : NativeContextData::NativeContextData(JSHeapBroker* broker, ObjectData** storage,
    3053             :                                      Handle<NativeContext> object)
    3054      928236 :     : ContextData(broker, storage, object), function_maps_(broker->zone()) {}
    3055             : 
    3056      464111 : void NativeContextData::Serialize(JSHeapBroker* broker) {
    3057      464111 :   if (serialized_) return;
    3058      464111 :   serialized_ = true;
    3059             : 
    3060      464111 :   TraceScope tracer(broker, this, "NativeContextData::Serialize");
    3061             :   Handle<NativeContext> context = Handle<NativeContext>::cast(object());
    3062             : 
    3063             : #define SERIALIZE_MEMBER(type, name)                                       \
    3064             :   DCHECK_NULL(name##_);                                                    \
    3065             :   name##_ = broker->GetOrCreateData(context->name())->As##type();          \
    3066             :   if (name##_->IsJSFunction()) name##_->AsJSFunction()->Serialize(broker); \
    3067             :   if (name##_->IsMap()) name##_->AsMap()->SerializeConstructor(broker);
    3068    14387513 :   BROKER_COMPULSORY_NATIVE_CONTEXT_FIELDS(SERIALIZE_MEMBER)
    3069      464114 :   if (!broker->isolate()->bootstrapper()->IsActive()) {
    3070     2780658 :     BROKER_OPTIONAL_NATIVE_CONTEXT_FIELDS(SERIALIZE_MEMBER)
    3071             :   }
    3072             : #undef SERIALIZE_MEMBER
    3073             : 
    3074      464114 :   bound_function_with_constructor_map_->SerializePrototype(broker);
    3075      464113 :   bound_function_without_constructor_map_->SerializePrototype(broker);
    3076             : 
    3077             :   DCHECK(function_maps_.empty());
    3078             :   int const first = Context::FIRST_FUNCTION_MAP_INDEX;
    3079             :   int const last = Context::LAST_FUNCTION_MAP_INDEX;
    3080      464113 :   function_maps_.reserve(last + 1 - first);
    3081    22741460 :   for (int i = first; i <= last; ++i) {
    3082    33416019 :     function_maps_.push_back(broker->GetOrCreateData(context->get(i))->AsMap());
    3083             :   }
    3084             : }
    3085             : 
    3086     1341523 : void JSFunctionRef::Serialize() {
    3087     1341523 :   if (broker()->mode() == JSHeapBroker::kDisabled) return;
    3088     1040768 :   CHECK_EQ(broker()->mode(), JSHeapBroker::kSerializing);
    3089     1040768 :   data()->AsJSFunction()->Serialize(broker());
    3090             : }
    3091             : 
    3092         116 : bool JSFunctionRef::serialized() const {
    3093         116 :   CHECK_NE(broker()->mode(), JSHeapBroker::kDisabled);
    3094         116 :   return data()->AsJSFunction()->serialized();
    3095             : }
    3096             : 
    3097       98058 : bool JSFunctionRef::IsSerializedForCompilation() const {
    3098       98058 :   if (broker()->mode() == JSHeapBroker::kDisabled) {
    3099       97942 :     return handle(object()->shared(), broker()->isolate())->HasBytecodeArray();
    3100             :   }
    3101             : 
    3102             :   // We get a crash if we try to access the shared() getter without
    3103             :   // checking for `serialized` first. Also it's possible to have a
    3104             :   // JSFunctionRef without a feedback vector.
    3105         232 :   return serialized() && has_feedback_vector() &&
    3106         232 :          shared().IsSerializedForCompilation(feedback_vector());
    3107             : }
    3108             : 
    3109         162 : void SharedFunctionInfoRef::SetSerializedForCompilation(
    3110             :     FeedbackVectorRef feedback) {
    3111         162 :   CHECK_EQ(broker()->mode(), JSHeapBroker::kSerializing);
    3112         162 :   data()->AsSharedFunctionInfo()->SetSerializedForCompilation(broker(),
    3113         162 :                                                               feedback);
    3114         162 : }
    3115             : 
    3116         416 : bool SharedFunctionInfoRef::IsSerializedForCompilation(
    3117             :     FeedbackVectorRef feedback) const {
    3118         416 :   CHECK_NE(broker()->mode(), JSHeapBroker::kDisabled);
    3119         832 :   return data()->AsSharedFunctionInfo()->IsSerializedForCompilation(feedback);
    3120             : }
    3121             : 
    3122     1141481 : void JSObjectRef::SerializeObjectCreateMap() {
    3123     1141481 :   if (broker()->mode() == JSHeapBroker::kDisabled) return;
    3124     1141481 :   CHECK_EQ(broker()->mode(), JSHeapBroker::kSerializing);
    3125     1141481 :   data()->AsJSObject()->SerializeObjectCreateMap(broker());
    3126             : }
    3127             : 
    3128      182767 : void MapRef::SerializeOwnDescriptors() {
    3129      182767 :   if (broker()->mode() == JSHeapBroker::kDisabled) return;
    3130          16 :   CHECK_EQ(broker()->mode(), JSHeapBroker::kSerializing);
    3131          16 :   data()->AsMap()->SerializeOwnDescriptors(broker());
    3132             : }
    3133             : 
    3134       21985 : void MapRef::SerializeBackPointer() {
    3135       21985 :   if (broker()->mode() == JSHeapBroker::kDisabled) return;
    3136           0 :   CHECK_EQ(broker()->mode(), JSHeapBroker::kSerializing);
    3137           0 :   data()->AsMap()->SerializeBackPointer(broker());
    3138             : }
    3139             : 
    3140       92684 : void MapRef::SerializePrototype() {
    3141       92684 :   if (broker()->mode() == JSHeapBroker::kDisabled) return;
    3142           5 :   CHECK_EQ(broker()->mode(), JSHeapBroker::kSerializing);
    3143           5 :   data()->AsMap()->SerializePrototype(broker());
    3144             : }
    3145             : 
    3146           5 : bool MapRef::serialized_prototype() const {
    3147           5 :   CHECK_NE(broker()->mode(), JSHeapBroker::kDisabled);
    3148           5 :   return data()->AsMap()->serialized_prototype();
    3149             : }
    3150             : 
    3151         170 : void ModuleRef::Serialize() {
    3152         170 :   if (broker()->mode() == JSHeapBroker::kDisabled) return;
    3153         170 :   CHECK_EQ(broker()->mode(), JSHeapBroker::kSerializing);
    3154         170 :   data()->AsModule()->Serialize(broker());
    3155             : }
    3156             : 
    3157     1358167 : void ContextRef::SerializeContextChain() {
    3158     1358167 :   if (broker()->mode() == JSHeapBroker::kDisabled) return;
    3159     1084248 :   CHECK_EQ(broker()->mode(), JSHeapBroker::kSerializing);
    3160     1084248 :   data()->AsContext()->SerializeContextChain(broker());
    3161             : }
    3162             : 
    3163       27740 : void ContextRef::SerializeSlot(int index) {
    3164       27740 :   if (broker()->mode() == JSHeapBroker::kDisabled) return;
    3165          16 :   CHECK_EQ(broker()->mode(), JSHeapBroker::kSerializing);
    3166          16 :   data()->AsContext()->SerializeSlot(broker(), index);
    3167             : }
    3168             : 
    3169      464112 : void NativeContextRef::Serialize() {
    3170      464112 :   if (broker()->mode() == JSHeapBroker::kDisabled) return;
    3171      464112 :   CHECK_EQ(broker()->mode(), JSHeapBroker::kSerializing);
    3172      464112 :   data()->AsNativeContext()->Serialize(broker());
    3173             : }
    3174             : 
    3175        1346 : void JSTypedArrayRef::Serialize() {
    3176        1346 :   if (broker()->mode() == JSHeapBroker::kDisabled) return;
    3177           0 :   CHECK_EQ(broker()->mode(), JSHeapBroker::kSerializing);
    3178           0 :   data()->AsJSTypedArray()->Serialize(broker());
    3179             : }
    3180             : 
    3181           0 : bool JSTypedArrayRef::serialized() const {
    3182           0 :   CHECK_NE(broker()->mode(), JSHeapBroker::kDisabled);
    3183           0 :   return data()->AsJSTypedArray()->serialized();
    3184             : }
    3185             : 
    3186         216 : void JSBoundFunctionRef::Serialize() {
    3187         216 :   if (broker()->mode() == JSHeapBroker::kDisabled) return;
    3188           0 :   CHECK_EQ(broker()->mode(), JSHeapBroker::kSerializing);
    3189           0 :   data()->AsJSBoundFunction()->Serialize(broker());
    3190             : }
    3191             : 
    3192      194305 : void PropertyCellRef::Serialize() {
    3193      194305 :   if (broker()->mode() == JSHeapBroker::kDisabled) return;
    3194           0 :   CHECK_EQ(broker()->mode(), JSHeapBroker::kSerializing);
    3195           0 :   data()->AsPropertyCell()->Serialize(broker());
    3196             : }
    3197             : 
    3198         128 : void FunctionTemplateInfoRef::Serialize() {
    3199         128 :   if (broker()->mode() == JSHeapBroker::kDisabled) return;
    3200           0 :   CHECK_EQ(broker()->mode(), JSHeapBroker::kSerializing);
    3201           0 :   data()->AsFunctionTemplateInfo()->Serialize(broker());
    3202             : }
    3203             : 
    3204         246 : base::Optional<PropertyCellRef> JSGlobalProxyRef::GetPropertyCell(
    3205             :     NameRef const& name, bool serialize) const {
    3206         246 :   if (broker()->mode() == JSHeapBroker::kDisabled) {
    3207         246 :     return GetPropertyCellFromHeap(broker(), name.object());
    3208             :   }
    3209             :   PropertyCellData* property_cell_data =
    3210           0 :       data()->AsJSGlobalProxy()->GetPropertyCell(
    3211           0 :           broker(), name.data()->AsName(), serialize);
    3212           0 :   if (property_cell_data == nullptr) return base::nullopt;
    3213             :   return PropertyCellRef(broker(), property_cell_data);
    3214             : }
    3215             : 
    3216       54381 : bool CanInlineElementAccess(MapRef const& map) {
    3217       54381 :   if (!map.IsJSObjectMap()) return false;
    3218       52740 :   if (map.is_access_check_needed()) return false;
    3219       52635 :   if (map.has_indexed_interceptor()) return false;
    3220       52627 :   ElementsKind const elements_kind = map.elements_kind();
    3221       52627 :   if (IsFastElementsKind(elements_kind)) return true;
    3222       16254 :   if (IsFixedTypedArrayElementsKind(elements_kind) &&
    3223       16254 :       elements_kind != BIGUINT64_ELEMENTS &&
    3224             :       elements_kind != BIGINT64_ELEMENTS) {
    3225             :     return true;
    3226             :   }
    3227        2368 :   return false;
    3228             : }
    3229             : 
    3230           0 : GlobalAccessFeedback::GlobalAccessFeedback(PropertyCellRef cell)
    3231             :     : ProcessedFeedback(kGlobalAccess),
    3232             :       cell_or_context_(cell),
    3233      194305 :       index_and_immutable_(0 /* doesn't matter */) {}
    3234             : 
    3235           0 : GlobalAccessFeedback::GlobalAccessFeedback(ContextRef script_context,
    3236             :                                            int slot_index, bool immutable)
    3237             :     : ProcessedFeedback(kGlobalAccess),
    3238             :       cell_or_context_(script_context),
    3239         109 :       index_and_immutable_(FeedbackNexus::SlotIndexBits::encode(slot_index) |
    3240         218 :                            FeedbackNexus::ImmutabilityBit::encode(immutable)) {
    3241             :   DCHECK_EQ(this->slot_index(), slot_index);
    3242             :   DCHECK_EQ(this->immutable(), immutable);
    3243           0 : }
    3244             : 
    3245      388719 : bool GlobalAccessFeedback::IsPropertyCell() const {
    3246      777656 :   return cell_or_context_.IsPropertyCell();
    3247             : }
    3248      194305 : PropertyCellRef GlobalAccessFeedback::property_cell() const {
    3249             :   DCHECK(IsPropertyCell());
    3250      194305 :   return cell_or_context_.AsPropertyCell();
    3251             : }
    3252         109 : ContextRef GlobalAccessFeedback::script_context() const {
    3253             :   DCHECK(IsScriptContextSlot());
    3254         109 :   return cell_or_context_.AsContext();
    3255             : }
    3256         109 : int GlobalAccessFeedback::slot_index() const {
    3257         109 :   CHECK(IsScriptContextSlot());
    3258         218 :   return FeedbackNexus::SlotIndexBits::decode(index_and_immutable_);
    3259             : }
    3260         109 : bool GlobalAccessFeedback::immutable() const {
    3261         109 :   CHECK(IsScriptContextSlot());
    3262         218 :   return FeedbackNexus::ImmutabilityBit::decode(index_and_immutable_);
    3263             : }
    3264             : 
    3265           0 : base::Optional<ObjectRef> GlobalAccessFeedback::GetConstantHint() const {
    3266           0 :   if (IsScriptContextSlot()) {
    3267           0 :     if (immutable()) return script_context().get(slot_index());
    3268             :   } else {
    3269           0 :     return property_cell().value();
    3270             :   }
    3271           0 :   return {};
    3272             : }
    3273             : 
    3274           0 : ElementAccessFeedback::ElementAccessFeedback(Zone* zone)
    3275             :     : ProcessedFeedback(kElementAccess),
    3276             :       receiver_maps(zone),
    3277           0 :       transitions(zone) {}
    3278             : 
    3279       14996 : ElementAccessFeedback::MapIterator::MapIterator(
    3280             :     ElementAccessFeedback const& processed, JSHeapBroker* broker)
    3281       14996 :     : processed_(processed), broker_(broker) {
    3282       29992 :   CHECK_LT(processed.receiver_maps.size(),
    3283             :            std::numeric_limits<size_t>::max() - processed.transitions.size());
    3284       14996 : }
    3285             : 
    3286       30226 : bool ElementAccessFeedback::MapIterator::done() const {
    3287       61900 :   return index_ >=
    3288      123800 :          processed_.receiver_maps.size() + processed_.transitions.size();
    3289             : }
    3290             : 
    3291       15230 : void ElementAccessFeedback::MapIterator::advance() { index_++; }
    3292             : 
    3293       31674 : MapRef ElementAccessFeedback::MapIterator::current() const {
    3294       31674 :   CHECK(!done());
    3295             :   size_t receiver_maps_size = processed_.receiver_maps.size();
    3296             :   Handle<Map> map;
    3297       31674 :   if (index_ < receiver_maps_size) {
    3298       30572 :     map = processed_.receiver_maps[index_];
    3299             :   } else {
    3300        2204 :     map = processed_.transitions[index_ - receiver_maps_size].first;
    3301             :   }
    3302       63348 :   return MapRef(broker_, map);
    3303             : }
    3304             : 
    3305       14996 : ElementAccessFeedback::MapIterator ElementAccessFeedback::all_maps(
    3306             :     JSHeapBroker* broker) const {
    3307       14996 :   return MapIterator(*this, broker);
    3308             : }
    3309             : 
    3310          41 : FeedbackSource::FeedbackSource(FeedbackNexus const& nexus)
    3311          41 :     : vector(nexus.vector_handle()), slot(nexus.slot()) {}
    3312             : 
    3313      950361 : FeedbackSource::FeedbackSource(VectorSlotPair const& pair)
    3314      950361 :     : vector(pair.vector()), slot(pair.slot()) {}
    3315             : 
    3316          72 : void JSHeapBroker::SetFeedback(FeedbackSource const& source,
    3317             :                                ProcessedFeedback const* feedback) {
    3318          72 :   auto insertion = feedback_.insert({source, feedback});
    3319          72 :   CHECK(insertion.second);
    3320          72 : }
    3321             : 
    3322          84 : bool JSHeapBroker::HasFeedback(FeedbackSource const& source) const {
    3323          84 :   return feedback_.find(source) != feedback_.end();
    3324             : }
    3325             : 
    3326          63 : ProcessedFeedback const* JSHeapBroker::GetFeedback(
    3327             :     FeedbackSource const& source) const {
    3328             :   auto it = feedback_.find(source);
    3329          63 :   CHECK_NE(it, feedback_.end());
    3330          63 :   return it->second;
    3331             : }
    3332             : 
    3333           8 : ElementAccessFeedback const* JSHeapBroker::GetElementAccessFeedback(
    3334             :     FeedbackSource const& source) const {
    3335           8 :   ProcessedFeedback const* feedback = GetFeedback(source);
    3336           8 :   if (feedback == nullptr) return nullptr;
    3337           0 :   CHECK_EQ(feedback->kind(), ProcessedFeedback::kElementAccess);
    3338             :   return static_cast<ElementAccessFeedback const*>(feedback);
    3339             : }
    3340             : 
    3341          55 : GlobalAccessFeedback const* JSHeapBroker::GetGlobalAccessFeedback(
    3342             :     FeedbackSource const& source) const {
    3343          55 :   ProcessedFeedback const* feedback = GetFeedback(source);
    3344          55 :   if (feedback == nullptr) return nullptr;
    3345           0 :   CHECK_EQ(feedback->kind(), ProcessedFeedback::kGlobalAccess);
    3346             :   return static_cast<GlobalAccessFeedback const*>(feedback);
    3347             : }
    3348             : 
    3349       23552 : ElementAccessFeedback const* JSHeapBroker::ProcessFeedbackMapsForElementAccess(
    3350             :     MapHandles const& maps) {
    3351             :   // Collect possible transition targets.
    3352             :   MapHandles possible_transition_targets;
    3353       23552 :   possible_transition_targets.reserve(maps.size());
    3354       50484 :   for (Handle<Map> map : maps) {
    3355       79000 :     if (CanInlineElementAccess(MapRef(this, map)) &&
    3356       45225 :         IsFastElementsKind(map->elements_kind()) &&
    3357             :         GetInitialFastElementsKind() != map->elements_kind()) {
    3358       13163 :       possible_transition_targets.push_back(map);
    3359             :     }
    3360             :   }
    3361             : 
    3362       23552 :   if (maps.empty()) return nullptr;
    3363             : 
    3364             :   ElementAccessFeedback* result = new (zone()) ElementAccessFeedback(zone());
    3365             : 
    3366             :   // Separate the actual receiver maps and the possible transition sources.
    3367       50468 :   for (Handle<Map> map : maps) {
    3368             :     // Don't generate elements kind transitions from stable maps.
    3369             :     Map transition_target = map->is_stable()
    3370             :                                 ? Map()
    3371             :                                 : map->FindElementsKindTransitionedMap(
    3372       42885 :                                       isolate(), possible_transition_targets);
    3373       26932 :     if (transition_target.is_null()) {
    3374       25301 :       result->receiver_maps.push_back(map);
    3375             :     } else {
    3376        1631 :       result->transitions.emplace_back(map,
    3377        3262 :                                        handle(transition_target, isolate()));
    3378             :     }
    3379             :   }
    3380             : 
    3381             : #ifdef ENABLE_SLOW_DCHECKS
    3382             :   // No transition sources appear in {receiver_maps}.
    3383             :   // All transition targets appear in {receiver_maps}.
    3384             :   for (auto& transition : result->transitions) {
    3385             :     CHECK(std::none_of(
    3386             :         result->receiver_maps.cbegin(), result->receiver_maps.cend(),
    3387             :         [&](Handle<Map> map) { return map.equals(transition.first); }));
    3388             :     CHECK(std::any_of(
    3389             :         result->receiver_maps.cbegin(), result->receiver_maps.cend(),
    3390             :         [&](Handle<Map> map) { return map.equals(transition.second); }));
    3391             :   }
    3392             : #endif
    3393       23536 :   CHECK(!result->receiver_maps.empty());
    3394             : 
    3395             :   return result;
    3396             : }
    3397             : 
    3398      950357 : GlobalAccessFeedback const* JSHeapBroker::ProcessFeedbackForGlobalAccess(
    3399             :     FeedbackSource const& source) {
    3400             :   FeedbackNexus nexus(source.vector, source.slot);
    3401             :   DCHECK(nexus.kind() == FeedbackSlotKind::kLoadGlobalInsideTypeof ||
    3402             :          nexus.kind() == FeedbackSlotKind::kLoadGlobalNotInsideTypeof ||
    3403             :          nexus.kind() == FeedbackSlotKind::kStoreGlobalSloppy ||
    3404             :          nexus.kind() == FeedbackSlotKind::kStoreGlobalStrict);
    3405     1144895 :   if (nexus.ic_state() != MONOMORPHIC || nexus.GetFeedback()->IsCleared()) {
    3406             :     return nullptr;
    3407             :   }
    3408             : 
    3409      388828 :   Handle<Object> feedback_value(nexus.GetFeedback()->GetHeapObjectOrSmi(),
    3410             :                                 isolate());
    3411             : 
    3412      194414 :   if (feedback_value->IsSmi()) {
    3413             :     // The wanted name belongs to a script-scope variable and the feedback tells
    3414             :     // us where to find its value.
    3415         109 :     int number = feedback_value->Number();
    3416             :     int const script_context_index =
    3417         218 :         FeedbackNexus::ContextIndexBits::decode(number);
    3418         109 :     int const context_slot_index = FeedbackNexus::SlotIndexBits::decode(number);
    3419             :     bool const immutable = FeedbackNexus::ImmutabilityBit::decode(number);
    3420             :     Handle<Context> context = ScriptContextTable::GetContext(
    3421         218 :         isolate(), native_context().script_context_table().object(),
    3422         109 :         script_context_index);
    3423             :     {
    3424             :       ObjectRef contents(this,
    3425         109 :                          handle(context->get(context_slot_index), isolate()));
    3426         218 :       CHECK(!contents.equals(
    3427             :           ObjectRef(this, isolate()->factory()->the_hole_value())));
    3428             :     }
    3429             :     ContextRef context_ref(this, context);
    3430         109 :     if (immutable) {
    3431          31 :       context_ref.SerializeSlot(context_slot_index);
    3432             :     }
    3433             :     return new (zone())
    3434         109 :         GlobalAccessFeedback(context_ref, context_slot_index, immutable);
    3435             :   }
    3436             : 
    3437      194305 :   CHECK(feedback_value->IsPropertyCell());
    3438             :   // The wanted name belongs (or did belong) to a property on the global
    3439             :   // object and the feedback is the cell holding its value.
    3440             :   PropertyCellRef cell(this, Handle<PropertyCell>::cast(feedback_value));
    3441      194305 :   cell.Serialize();
    3442      194305 :   return new (zone()) GlobalAccessFeedback(cell);
    3443             : }
    3444             : 
    3445           0 : std::ostream& operator<<(std::ostream& os, const ObjectRef& ref) {
    3446           0 :   return os << ref.data();
    3447             : }
    3448             : 
    3449             : #undef BIMODAL_ACCESSOR
    3450             : #undef BIMODAL_ACCESSOR_B
    3451             : #undef BIMODAL_ACCESSOR_C
    3452             : #undef IF_BROKER_DISABLED_ACCESS_HANDLE
    3453             : #undef IF_BROKER_DISABLED_ACCESS_HANDLE_C
    3454             : #undef TRACE
    3455             : #undef TRACE_MISSING
    3456             : 
    3457             : }  // namespace compiler
    3458             : }  // namespace internal
    3459      121996 : }  // namespace v8

Generated by: LCOV version 1.10