LCOV - code coverage report
Current view: top level - src/compiler - js-heap-broker.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 1009 1153 87.5 %
Date: 2019-03-21 Functions: 375 583 64.3 %

          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/ast/modules.h"
      12             : #include "src/bootstrapper.h"
      13             : #include "src/boxed-float.h"
      14             : #include "src/code-factory.h"
      15             : #include "src/compiler/graph-reducer.h"
      16             : #include "src/compiler/per-isolate-compiler-cache.h"
      17             : #include "src/objects-inl.h"
      18             : #include "src/objects/allocation-site-inl.h"
      19             : #include "src/objects/cell-inl.h"
      20             : #include "src/objects/heap-number-inl.h"
      21             : #include "src/objects/instance-type-inl.h"
      22             : #include "src/objects/js-array-buffer-inl.h"
      23             : #include "src/objects/js-array-inl.h"
      24             : #include "src/objects/js-regexp-inl.h"
      25             : #include "src/objects/module-inl.h"
      26             : #include "src/utils.h"
      27             : #include "src/vector-slot-pair.h"
      28             : 
      29             : namespace v8 {
      30             : namespace internal {
      31             : namespace compiler {
      32             : 
      33             : #define TRACE(broker, x) TRACE_BROKER(broker, x)
      34             : 
      35             : #define FORWARD_DECL(Name) class Name##Data;
      36             : HEAP_BROKER_OBJECT_LIST(FORWARD_DECL)
      37             : #undef FORWARD_DECL
      38             : 
      39             : // There are three kinds of ObjectData values.
      40             : //
      41             : // kSmi: The underlying V8 object is a Smi and the data is an instance of the
      42             : //   base class (ObjectData), i.e. it's basically just the handle.  Because the
      43             : //   object is a Smi, it's safe to access the handle in order to extract the
      44             : //   number value, and AsSmi() does exactly that.
      45             : //
      46             : // kSerializedHeapObject: The underlying V8 object is a HeapObject and the
      47             : //   data is an instance of the corresponding (most-specific) subclass, e.g.
      48             : //   JSFunctionData, which provides serialized information about the object.
      49             : //
      50             : // kUnserializedHeapObject: The underlying V8 object is a HeapObject and the
      51             : //   data is an instance of the base class (ObjectData), i.e. it basically
      52             : //   carries no information other than the handle.
      53             : //
      54             : enum ObjectDataKind { kSmi, kSerializedHeapObject, kUnserializedHeapObject };
      55             : 
      56             : class ObjectData : public ZoneObject {
      57             :  public:
      58    93469348 :   ObjectData(JSHeapBroker* broker, ObjectData** storage, Handle<Object> object,
      59             :              ObjectDataKind kind)
      60    93469348 :       : object_(object), kind_(kind) {
      61             :     // This assignment ensures we don't end up inserting the same object
      62             :     // in an endless recursion.
      63    93469348 :     *storage = this;
      64             : 
      65    93469348 :     TRACE(broker, "Creating data " << this << " for handle " << object.address()
      66             :                                    << " (" << Brief(*object) << ")");
      67             : 
      68    93469348 :     CHECK_NOT_NULL(broker->isolate()->handle_scope_data()->canonical_scope);
      69    93469348 :   }
      70             : 
      71             : #define DECLARE_IS_AND_AS(Name) \
      72             :   bool Is##Name() const;        \
      73             :   Name##Data* As##Name();
      74             :   HEAP_BROKER_OBJECT_LIST(DECLARE_IS_AND_AS)
      75             : #undef DECLARE_IS_AND_AS
      76             : 
      77             :   Handle<Object> object() const { return object_; }
      78             :   ObjectDataKind kind() const { return kind_; }
      79    12048702 :   bool is_smi() const { return kind_ == kSmi; }
      80             : 
      81             :  private:
      82             :   Handle<Object> const object_;
      83             :   ObjectDataKind const kind_;
      84             : };
      85             : 
      86             : class HeapObjectData : public ObjectData {
      87             :  public:
      88             :   HeapObjectData(JSHeapBroker* broker, ObjectData** storage,
      89             :                  Handle<HeapObject> object);
      90             : 
      91             :   bool boolean_value() const { return boolean_value_; }
      92             :   MapData* map() const { return map_; }
      93             : 
      94             :   static HeapObjectData* Serialize(JSHeapBroker* broker,
      95             :                                    Handle<HeapObject> object);
      96             : 
      97             :  private:
      98             :   bool const boolean_value_;
      99             :   MapData* const map_;
     100             : };
     101             : 
     102             : class PropertyCellData : public HeapObjectData {
     103             :  public:
     104             :   PropertyCellData(JSHeapBroker* broker, ObjectData** storage,
     105             :                    Handle<PropertyCell> object);
     106             : 
     107             :   PropertyDetails property_details() const { return property_details_; }
     108             : 
     109             :   void Serialize(JSHeapBroker* broker);
     110             :   ObjectData* value() { return value_; }
     111             : 
     112             :  private:
     113             :   PropertyDetails const property_details_;
     114             : 
     115             :   bool serialized_ = false;
     116             :   ObjectData* value_ = nullptr;
     117             : };
     118             : 
     119    29178764 : void JSHeapBroker::IncrementTracingIndentation() { ++trace_indentation_; }
     120             : 
     121    29179008 : void JSHeapBroker::DecrementTracingIndentation() { --trace_indentation_; }
     122             : 
     123             : class TraceScope {
     124             :  public:
     125             :   TraceScope(JSHeapBroker* broker, const char* label)
     126      478555 :       : TraceScope(broker, static_cast<void*>(broker), label) {}
     127             : 
     128             :   TraceScope(JSHeapBroker* broker, ObjectData* data, const char* label)
     129    28700454 :       : TraceScope(broker, static_cast<void*>(data), label) {}
     130             : 
     131    58356781 :   ~TraceScope() { broker_->DecrementTracingIndentation(); }
     132             : 
     133             :  private:
     134             :   JSHeapBroker* const broker_;
     135             : 
     136    29178764 :   TraceScope(JSHeapBroker* broker, void* self, const char* label)
     137    29178764 :       : broker_(broker) {
     138    29178764 :     TRACE(broker_, "Running " << label << " on " << self << ".");
     139    29178764 :     broker_->IncrementTracingIndentation();
     140    29178764 :   }
     141             : };
     142             : 
     143     3257607 : PropertyCellData::PropertyCellData(JSHeapBroker* broker, ObjectData** storage,
     144             :                                    Handle<PropertyCell> object)
     145             :     : HeapObjectData(broker, storage, object),
     146     6515214 :       property_details_(object->property_details()) {}
     147             : 
     148     3247126 : void PropertyCellData::Serialize(JSHeapBroker* broker) {
     149     3247126 :   if (serialized_) return;
     150     3247126 :   serialized_ = true;
     151             : 
     152     3247126 :   TraceScope tracer(broker, this, "PropertyCellData::Serialize");
     153             :   auto cell = Handle<PropertyCell>::cast(object());
     154             :   DCHECK_NULL(value_);
     155     3247134 :   value_ = broker->GetOrCreateData(cell->value());
     156             : }
     157             : 
     158             : class JSObjectField {
     159             :  public:
     160             :   bool IsDouble() const { return object_ == nullptr; }
     161             :   double AsDouble() const {
     162           0 :     CHECK(IsDouble());
     163           0 :     return number_;
     164             :   }
     165             : 
     166             :   bool IsObject() const { return object_ != nullptr; }
     167             :   ObjectData* AsObject() const {
     168        3274 :     CHECK(IsObject());
     169             :     return object_;
     170             :   }
     171             : 
     172             :   explicit JSObjectField(double value) : number_(value) {}
     173        2810 :   explicit JSObjectField(ObjectData* value) : object_(value) {}
     174             : 
     175             :  private:
     176             :   ObjectData* object_ = nullptr;
     177             :   double number_ = 0;
     178             : };
     179             : 
     180             : class JSObjectData : public HeapObjectData {
     181             :  public:
     182             :   JSObjectData(JSHeapBroker* broker, ObjectData** storage,
     183             :                Handle<JSObject> object);
     184             : 
     185             :   // Recursively serializes all reachable JSObjects.
     186             :   void SerializeAsBoilerplate(JSHeapBroker* broker);
     187             :   // Shallow serialization of {elements}.
     188             :   void SerializeElements(JSHeapBroker* broker);
     189             : 
     190             :   const JSObjectField& GetInobjectField(int property_index) const;
     191             :   FixedArrayBaseData* elements() const;
     192             : 
     193             :   // This method is only used to assert our invariants.
     194             :   bool cow_or_empty_elements_tenured() const;
     195             : 
     196             :   void SerializeObjectCreateMap(JSHeapBroker* broker);
     197             :   MapData* object_create_map() const {  // Can be nullptr.
     198          16 :     CHECK(serialized_object_create_map_);
     199          16 :     return object_create_map_;
     200             :   }
     201             : 
     202             :  private:
     203             :   void SerializeRecursive(JSHeapBroker* broker, int max_depths);
     204             : 
     205             :   FixedArrayBaseData* elements_ = nullptr;
     206             :   bool cow_or_empty_elements_tenured_ = false;
     207             :   // The {serialized_as_boilerplate} flag is set when all recursively
     208             :   // reachable JSObjects are serialized.
     209             :   bool serialized_as_boilerplate_ = false;
     210             :   bool serialized_elements_ = false;
     211             : 
     212             :   ZoneVector<JSObjectField> inobject_fields_;
     213             : 
     214             :   bool serialized_object_create_map_ = false;
     215             :   MapData* object_create_map_ = nullptr;
     216             : };
     217             : 
     218     1138302 : void JSObjectData::SerializeObjectCreateMap(JSHeapBroker* broker) {
     219     1652956 :   if (serialized_object_create_map_) return;
     220      623648 :   serialized_object_create_map_ = true;
     221             : 
     222      623648 :   TraceScope tracer(broker, this, "JSObjectData::SerializeObjectCreateMap");
     223             :   Handle<JSObject> jsobject = Handle<JSObject>::cast(object());
     224             : 
     225      623647 :   if (jsobject->map()->is_prototype_map()) {
     226             :     Handle<Object> maybe_proto_info(jsobject->map()->prototype_info(),
     227             :                                     broker->isolate());
     228       20900 :     if (maybe_proto_info->IsPrototypeInfo()) {
     229             :       auto proto_info = Handle<PrototypeInfo>::cast(maybe_proto_info);
     230       14611 :       if (proto_info->HasObjectCreateMap()) {
     231             :         DCHECK_NULL(object_create_map_);
     232             :         object_create_map_ =
     233          50 :             broker->GetOrCreateData(proto_info->ObjectCreateMap())->AsMap();
     234             :       }
     235             :     }
     236             :   }
     237             : }
     238             : 
     239             : class JSTypedArrayData : public JSObjectData {
     240             :  public:
     241             :   JSTypedArrayData(JSHeapBroker* broker, ObjectData** storage,
     242             :                    Handle<JSTypedArray> object);
     243             : 
     244             :   bool is_on_heap() const { return is_on_heap_; }
     245             :   size_t length_value() const { return length_value_; }
     246             :   void* elements_external_pointer() const { return elements_external_pointer_; }
     247             : 
     248             :   void Serialize(JSHeapBroker* broker);
     249             :   bool serialized() const { return serialized_; }
     250             : 
     251             :   HeapObjectData* buffer() const { return buffer_; }
     252             : 
     253             :  private:
     254             :   bool const is_on_heap_;
     255             :   size_t const length_value_;
     256             :   void* const elements_external_pointer_;
     257             : 
     258             :   bool serialized_ = false;
     259             :   HeapObjectData* buffer_ = nullptr;
     260             : };
     261             : 
     262         787 : JSTypedArrayData::JSTypedArrayData(JSHeapBroker* broker, ObjectData** storage,
     263             :                                    Handle<JSTypedArray> object)
     264             :     : JSObjectData(broker, storage, object),
     265        1574 :       is_on_heap_(object->is_on_heap()),
     266             :       length_value_(object->length_value()),
     267             :       elements_external_pointer_(
     268        2361 :           FixedTypedArrayBase::cast(object->elements())->external_pointer()) {}
     269             : 
     270           0 : void JSTypedArrayData::Serialize(JSHeapBroker* broker) {
     271           0 :   if (serialized_) return;
     272           0 :   serialized_ = true;
     273             : 
     274           0 :   TraceScope tracer(broker, this, "JSTypedArrayData::Serialize");
     275             :   Handle<JSTypedArray> typed_array = Handle<JSTypedArray>::cast(object());
     276             : 
     277           0 :   if (!is_on_heap()) {
     278             :     DCHECK_NULL(buffer_);
     279           0 :     buffer_ = broker->GetOrCreateData(typed_array->buffer())->AsHeapObject();
     280             :   }
     281             : }
     282             : 
     283             : class JSDataViewData : public JSObjectData {
     284             :  public:
     285             :   JSDataViewData(JSHeapBroker* broker, ObjectData** storage,
     286             :                  Handle<JSDataView> object);
     287             : 
     288             :   size_t byte_length() const { return byte_length_; }
     289             :   size_t byte_offset() const { return byte_offset_; }
     290             : 
     291             :  private:
     292             :   size_t const byte_length_;
     293             :   size_t const byte_offset_;
     294             : };
     295             : 
     296             : class JSBoundFunctionData : public JSObjectData {
     297             :  public:
     298             :   JSBoundFunctionData(JSHeapBroker* broker, ObjectData** storage,
     299             :                       Handle<JSBoundFunction> object);
     300             : 
     301             :   void Serialize(JSHeapBroker* broker);
     302             : 
     303             :   ObjectData* bound_target_function() const { return bound_target_function_; }
     304             :   ObjectData* bound_this() const { return bound_this_; }
     305             :   FixedArrayData* bound_arguments() const { return bound_arguments_; }
     306             : 
     307             :  private:
     308             :   bool serialized_ = false;
     309             : 
     310             :   ObjectData* bound_target_function_ = nullptr;
     311             :   ObjectData* bound_this_ = nullptr;
     312             :   FixedArrayData* bound_arguments_ = nullptr;
     313             : };
     314             : 
     315             : class JSFunctionData : public JSObjectData {
     316             :  public:
     317             :   JSFunctionData(JSHeapBroker* broker, ObjectData** storage,
     318             :                  Handle<JSFunction> object);
     319             : 
     320             :   bool has_feedback_vector() const { return has_feedback_vector_; }
     321             :   bool has_initial_map() const { return has_initial_map_; }
     322             :   bool has_prototype() const { return has_prototype_; }
     323             :   bool PrototypeRequiresRuntimeLookup() const {
     324             :     return PrototypeRequiresRuntimeLookup_;
     325             :   }
     326             : 
     327             :   void Serialize(JSHeapBroker* broker);
     328             : 
     329             :   ContextData* context() const { return context_; }
     330             :   NativeContextData* native_context() const { return native_context_; }
     331             :   MapData* initial_map() const { return initial_map_; }
     332             :   ObjectData* prototype() const { return prototype_; }
     333             :   SharedFunctionInfoData* shared() const { return shared_; }
     334             :   FeedbackVectorData* feedback_vector() const { return feedback_vector_; }
     335             :   int initial_map_instance_size_with_min_slack() const {
     336        5057 :     CHECK(serialized_);
     337        5057 :     return initial_map_instance_size_with_min_slack_;
     338             :   }
     339             : 
     340             :  private:
     341             :   bool has_feedback_vector_;
     342             :   bool has_initial_map_;
     343             :   bool has_prototype_;
     344             :   bool PrototypeRequiresRuntimeLookup_;
     345             : 
     346             :   bool serialized_ = false;
     347             : 
     348             :   ContextData* context_ = nullptr;
     349             :   NativeContextData* native_context_ = nullptr;
     350             :   MapData* initial_map_ = nullptr;
     351             :   ObjectData* prototype_ = nullptr;
     352             :   SharedFunctionInfoData* shared_ = nullptr;
     353             :   FeedbackVectorData* feedback_vector_ = nullptr;
     354             :   int initial_map_instance_size_with_min_slack_;
     355             : };
     356             : 
     357             : class JSRegExpData : public JSObjectData {
     358             :  public:
     359         647 :   JSRegExpData(JSHeapBroker* broker, ObjectData** storage,
     360             :                Handle<JSRegExp> object)
     361         647 :       : JSObjectData(broker, storage, object) {}
     362             : 
     363             :   void SerializeAsRegExpBoilerplate(JSHeapBroker* broker);
     364             : 
     365             :   ObjectData* raw_properties_or_hash() const { return raw_properties_or_hash_; }
     366             :   ObjectData* data() const { return data_; }
     367             :   ObjectData* source() const { return source_; }
     368             :   ObjectData* flags() const { return flags_; }
     369             :   ObjectData* last_index() const { return last_index_; }
     370             : 
     371             :  private:
     372             :   bool serialized_as_reg_exp_boilerplate_ = false;
     373             : 
     374             :   ObjectData* raw_properties_or_hash_ = nullptr;
     375             :   ObjectData* data_ = nullptr;
     376             :   ObjectData* source_ = nullptr;
     377             :   ObjectData* flags_ = nullptr;
     378             :   ObjectData* last_index_ = nullptr;
     379             : };
     380             : 
     381             : class HeapNumberData : public HeapObjectData {
     382             :  public:
     383      464003 :   HeapNumberData(JSHeapBroker* broker, ObjectData** storage,
     384             :                  Handle<HeapNumber> object)
     385      928004 :       : HeapObjectData(broker, storage, object), value_(object->value()) {}
     386             : 
     387             :   double value() const { return value_; }
     388             : 
     389             :  private:
     390             :   double const value_;
     391             : };
     392             : 
     393             : class MutableHeapNumberData : public HeapObjectData {
     394             :  public:
     395         128 :   MutableHeapNumberData(JSHeapBroker* broker, ObjectData** storage,
     396             :                         Handle<MutableHeapNumber> object)
     397         256 :       : HeapObjectData(broker, storage, object), value_(object->value()) {}
     398             : 
     399             :   double value() const { return value_; }
     400             : 
     401             :  private:
     402             :   double const value_;
     403             : };
     404             : 
     405             : class ContextData : public HeapObjectData {
     406             :  public:
     407             :   ContextData(JSHeapBroker* broker, ObjectData** storage,
     408             :               Handle<Context> object);
     409             :   void SerializeContextChain(JSHeapBroker* broker);
     410             : 
     411             :   ContextData* previous() const {
     412           0 :     CHECK(serialized_context_chain_);
     413           0 :     return previous_;
     414             :   }
     415             : 
     416             :   void SerializeSlot(JSHeapBroker* broker, int index);
     417             : 
     418          16 :   ObjectData* GetSlot(int index) {
     419             :     auto search = slots_.find(index);
     420          16 :     CHECK(search != slots_.end());
     421          16 :     return search->second;
     422             :   }
     423             : 
     424             :  private:
     425             :   ZoneMap<int, ObjectData*> slots_;
     426             :   bool serialized_context_chain_ = false;
     427             :   ContextData* previous_ = nullptr;
     428             : };
     429             : 
     430      191622 : ContextData::ContextData(JSHeapBroker* broker, ObjectData** storage,
     431             :                          Handle<Context> object)
     432     1310999 :     : HeapObjectData(broker, storage, object), slots_(broker->zone()) {}
     433             : 
     434     1174840 : void ContextData::SerializeContextChain(JSHeapBroker* broker) {
     435     1792516 :   if (serialized_context_chain_) return;
     436      557164 :   serialized_context_chain_ = true;
     437             : 
     438      557164 :   TraceScope tracer(broker, this, "ContextData::SerializeContextChain");
     439             :   Handle<Context> context = Handle<Context>::cast(object());
     440             : 
     441             :   DCHECK_NULL(previous_);
     442             :   // Context::previous DCHECK-fails when called on the native context.
     443      557170 :   if (!context->IsNativeContext()) {
     444       93296 :     previous_ = broker->GetOrCreateData(context->previous())->AsContext();
     445       93296 :     previous_->SerializeContextChain(broker);
     446             :   }
     447             : }
     448             : 
     449          16 : void ContextData::SerializeSlot(JSHeapBroker* broker, int index) {
     450          16 :   TraceScope tracer(broker, this, "ContextData::SerializeSlot");
     451          16 :   TRACE(broker, "Serializing script context slot " << index << ".");
     452             :   Handle<Context> context = Handle<Context>::cast(object());
     453          32 :   CHECK(index >= 0 && index < context->length());
     454          16 :   ObjectData* odata = broker->GetOrCreateData(context->get(index));
     455          32 :   slots_.insert(std::make_pair(index, odata));
     456          16 : }
     457             : 
     458             : class NativeContextData : public ContextData {
     459             :  public:
     460             : #define DECL_ACCESSOR(type, name) \
     461             :   type##Data* name() const { return name##_; }
     462             :   BROKER_NATIVE_CONTEXT_FIELDS(DECL_ACCESSOR)
     463             : #undef DECL_ACCESSOR
     464             : 
     465             :   const ZoneVector<MapData*>& function_maps() const {
     466       31995 :     CHECK(serialized_);
     467             :     return function_maps_;
     468             :   }
     469             : 
     470             :   NativeContextData(JSHeapBroker* broker, ObjectData** storage,
     471             :                     Handle<NativeContext> object);
     472             :   void Serialize(JSHeapBroker* broker);
     473             : 
     474             :  private:
     475             :   bool serialized_ = false;
     476             : #define DECL_MEMBER(type, name) type##Data* name##_ = nullptr;
     477             :   BROKER_NATIVE_CONTEXT_FIELDS(DECL_MEMBER)
     478             : #undef DECL_MEMBER
     479             :   ZoneVector<MapData*> function_maps_;
     480             : };
     481             : 
     482             : class NameData : public HeapObjectData {
     483             :  public:
     484           0 :   NameData(JSHeapBroker* broker, ObjectData** storage, Handle<Name> object)
     485     7654305 :       : HeapObjectData(broker, storage, object) {}
     486             : };
     487             : 
     488             : class StringData : public NameData {
     489             :  public:
     490             :   StringData(JSHeapBroker* broker, ObjectData** storage, Handle<String> object);
     491             : 
     492             :   int length() const { return length_; }
     493             :   uint16_t first_char() const { return first_char_; }
     494         841 :   base::Optional<double> to_number() const { return to_number_; }
     495             :   bool is_external_string() const { return is_external_string_; }
     496             :   bool is_seq_string() const { return is_seq_string_; }
     497             : 
     498             :  private:
     499             :   int const length_;
     500             :   uint16_t const first_char_;
     501             :   base::Optional<double> to_number_;
     502             :   bool const is_external_string_;
     503             :   bool const is_seq_string_;
     504             : 
     505             :   static constexpr int kMaxLengthForDoubleConversion = 23;
     506             : };
     507             : 
     508             : class SymbolData : public NameData {
     509             :  public:
     510       36558 :   SymbolData(JSHeapBroker* broker, ObjectData** storage, Handle<Symbol> object)
     511       36558 :       : NameData(broker, storage, object) {}
     512             : };
     513             : 
     514     7617747 : StringData::StringData(JSHeapBroker* broker, ObjectData** storage,
     515             :                        Handle<String> object)
     516             :     : NameData(broker, storage, object),
     517             :       length_(object->length()),
     518             :       first_char_(length_ > 0 ? object->Get(0) : 0),
     519             :       is_external_string_(object->IsExternalString()),
     520    30470933 :       is_seq_string_(object->IsSeqString()) {
     521             :   int flags = ALLOW_HEX | ALLOW_OCTAL | ALLOW_BINARY;
     522     7617732 :   if (length_ <= kMaxLengthForDoubleConversion) {
     523     7570080 :     to_number_ = StringToDouble(broker->isolate(), object, flags);
     524             :   }
     525     7617773 : }
     526             : 
     527             : class InternalizedStringData : public StringData {
     528             :  public:
     529             :   InternalizedStringData(JSHeapBroker* broker, ObjectData** storage,
     530             :                          Handle<InternalizedString> object);
     531             : 
     532             :   uint32_t array_index() const { return array_index_; }
     533             : 
     534             :  private:
     535             :   uint32_t array_index_;
     536             : };
     537             : 
     538     7617413 : InternalizedStringData::InternalizedStringData(
     539             :     JSHeapBroker* broker, ObjectData** storage,
     540             :     Handle<InternalizedString> object)
     541     7617413 :     : StringData(broker, storage, object) {
     542    15234838 :   if (!object->AsArrayIndex(&array_index_)) {
     543     7150885 :     array_index_ = InternalizedStringRef::kNotAnArrayIndex;
     544             :   }
     545     7617419 : }
     546             : 
     547             : namespace {
     548             : 
     549        6672 : bool IsFastLiteralHelper(Handle<JSObject> boilerplate, int max_depth,
     550             :                          int* max_properties) {
     551             :   DCHECK_GE(max_depth, 0);
     552             :   DCHECK_GE(*max_properties, 0);
     553             : 
     554             :   // Make sure the boilerplate map is not deprecated.
     555        6672 :   if (!JSObject::TryMigrateInstance(boilerplate)) return false;
     556             : 
     557             :   // Check for too deep nesting.
     558        6672 :   if (max_depth == 0) return false;
     559             : 
     560             :   // Check the elements.
     561             :   Isolate* const isolate = boilerplate->GetIsolate();
     562             :   Handle<FixedArrayBase> elements(boilerplate->elements(), isolate);
     563       10943 :   if (elements->length() > 0 &&
     564             :       elements->map() != ReadOnlyRoots(isolate).fixed_cow_array_map()) {
     565        4430 :     if (boilerplate->HasSmiOrObjectElements()) {
     566             :       Handle<FixedArray> fast_elements = Handle<FixedArray>::cast(elements);
     567             :       int length = elements->length();
     568       22319 :       for (int i = 0; i < length; i++) {
     569       10364 :         if ((*max_properties)-- == 0) return false;
     570             :         Handle<Object> value(fast_elements->get(i), isolate);
     571       10350 :         if (value->IsJSObject()) {
     572         465 :           Handle<JSObject> value_object = Handle<JSObject>::cast(value);
     573         465 :           if (!IsFastLiteralHelper(value_object, max_depth - 1,
     574             :                                    max_properties)) {
     575           0 :             return false;
     576             :           }
     577             :         }
     578             :       }
     579        1192 :     } else if (boilerplate->HasDoubleElements()) {
     580         560 :       if (elements->Size() > kMaxRegularHeapObjectSize) return false;
     581             :     } else {
     582             :       return false;
     583             :     }
     584             :   }
     585             : 
     586             :   // TODO(turbofan): Do we want to support out-of-object properties?
     587       13230 :   if (!(boilerplate->HasFastProperties() &&
     588       19681 :         boilerplate->property_array()->length() == 0)) {
     589             :     return false;
     590             :   }
     591             : 
     592             :   // Check the in-object properties.
     593             :   Handle<DescriptorArray> descriptors(
     594             :       boilerplate->map()->instance_descriptors(), isolate);
     595             :   int limit = boilerplate->map()->NumberOfOwnDescriptors();
     596       20637 :   for (int i = 0; i < limit; i++) {
     597        7059 :     PropertyDetails details = descriptors->GetDetails(i);
     598       11301 :     if (details.location() != kField) continue;
     599             :     DCHECK_EQ(kData, details.kind());
     600        2824 :     if ((*max_properties)-- == 0) return false;
     601        2817 :     FieldIndex field_index = FieldIndex::ForDescriptor(boilerplate->map(), i);
     602             :     if (boilerplate->IsUnboxedDoubleField(field_index)) continue;
     603        5634 :     Handle<Object> value(boilerplate->RawFastPropertyAt(field_index), isolate);
     604        2817 :     if (value->IsJSObject()) {
     605         293 :       Handle<JSObject> value_object = Handle<JSObject>::cast(value);
     606         293 :       if (!IsFastLiteralHelper(value_object, max_depth - 1, max_properties)) {
     607           7 :         return false;
     608             :       }
     609             :     }
     610             :   }
     611             :   return true;
     612             : }
     613             : 
     614             : // Maximum depth and total number of elements and properties for literal
     615             : // graphs to be considered for fast deep-copying. The limit is chosen to
     616             : // match the maximum number of inobject properties, to ensure that the
     617             : // performance of using object literals is not worse than using constructor
     618             : // functions, see crbug.com/v8/6211 for details.
     619             : const int kMaxFastLiteralDepth = 3;
     620             : const int kMaxFastLiteralProperties = JSObject::kMaxInObjectProperties;
     621             : 
     622             : // Determines whether the given array or object literal boilerplate satisfies
     623             : // all limits to be considered for fast deep-copying and computes the total
     624             : // size of all objects that are part of the graph.
     625             : bool IsInlinableFastLiteral(Handle<JSObject> boilerplate) {
     626        5914 :   int max_properties = kMaxFastLiteralProperties;
     627             :   return IsFastLiteralHelper(boilerplate, kMaxFastLiteralDepth,
     628        5914 :                              &max_properties);
     629             : }
     630             : 
     631             : }  // namespace
     632             : 
     633             : class AllocationSiteData : public HeapObjectData {
     634             :  public:
     635             :   AllocationSiteData(JSHeapBroker* broker, ObjectData** storage,
     636             :                      Handle<AllocationSite> object);
     637             :   void SerializeBoilerplate(JSHeapBroker* broker);
     638             : 
     639             :   bool PointsToLiteral() const { return PointsToLiteral_; }
     640             :   AllocationType GetAllocationType() const { return GetAllocationType_; }
     641             :   ObjectData* nested_site() const { return nested_site_; }
     642             :   bool IsFastLiteral() const { return IsFastLiteral_; }
     643             :   JSObjectData* boilerplate() const { return boilerplate_; }
     644             : 
     645             :   // These are only valid if PointsToLiteral is false.
     646             :   ElementsKind GetElementsKind() const { return GetElementsKind_; }
     647             :   bool CanInlineCall() const { return CanInlineCall_; }
     648             : 
     649             :  private:
     650             :   bool const PointsToLiteral_;
     651             :   AllocationType const GetAllocationType_;
     652             :   ObjectData* nested_site_ = nullptr;
     653             :   bool IsFastLiteral_ = false;
     654             :   JSObjectData* boilerplate_ = nullptr;
     655             :   ElementsKind GetElementsKind_ = NO_ELEMENTS;
     656             :   bool CanInlineCall_ = false;
     657             :   bool serialized_boilerplate_ = false;
     658             : };
     659             : 
     660             : // Only used in JSNativeContextSpecialization.
     661             : class ScriptContextTableData : public HeapObjectData {
     662             :  public:
     663      463875 :   ScriptContextTableData(JSHeapBroker* broker, ObjectData** storage,
     664             :                          Handle<ScriptContextTable> object)
     665      463875 :       : HeapObjectData(broker, storage, object) {}
     666             : };
     667             : 
     668        8190 : struct PropertyDescriptor {
     669             :   NameData* key = nullptr;
     670             :   PropertyDetails details = PropertyDetails::Empty();
     671             :   FieldIndex field_index;
     672             :   MapData* field_owner = nullptr;
     673             :   ObjectData* field_type = nullptr;
     674             :   bool is_unboxed_double_field = false;
     675             : };
     676             : 
     677             : class MapData : public HeapObjectData {
     678             :  public:
     679             :   MapData(JSHeapBroker* broker, ObjectData** storage, Handle<Map> object);
     680             : 
     681             :   InstanceType instance_type() const { return instance_type_; }
     682             :   int instance_size() const { return instance_size_; }
     683             :   byte bit_field() const { return bit_field_; }
     684             :   byte bit_field2() const { return bit_field2_; }
     685             :   uint32_t bit_field3() const { return bit_field3_; }
     686             :   bool can_be_deprecated() const { return can_be_deprecated_; }
     687             :   bool can_transition() const { return can_transition_; }
     688             :   int in_object_properties_start_in_words() const {
     689       38821 :     CHECK(InstanceTypeChecker::IsJSObject(instance_type()));
     690       38821 :     return in_object_properties_start_in_words_;
     691             :   }
     692             :   int in_object_properties() const {
     693       74892 :     CHECK(InstanceTypeChecker::IsJSObject(instance_type()));
     694       74892 :     return in_object_properties_;
     695             :   }
     696             :   int constructor_function_index() const { return constructor_function_index_; }
     697             :   int NextFreePropertyIndex() const { return next_free_property_index_; }
     698             :   int UnusedPropertyFields() const { return unused_property_fields_; }
     699             :   bool supports_fast_array_iteration() const {
     700             :     return supports_fast_array_iteration_;
     701             :   }
     702             :   bool supports_fast_array_resize() const {
     703             :     return supports_fast_array_resize_;
     704             :   }
     705             : 
     706             :   // Extra information.
     707             : 
     708             :   void SerializeElementsKindGeneralizations(JSHeapBroker* broker);
     709             :   const ZoneVector<MapData*>& elements_kind_generalizations() const {
     710         846 :     CHECK(serialized_elements_kind_generalizations_);
     711             :     return elements_kind_generalizations_;
     712             :   }
     713             : 
     714             :   // Serialize the own part of the descriptor array and, recursively, that of
     715             :   // any field owner.
     716             :   void SerializeOwnDescriptors(JSHeapBroker* broker);
     717             :   DescriptorArrayData* instance_descriptors() const {
     718       17147 :     CHECK(serialized_own_descriptors_);
     719       17147 :     return instance_descriptors_;
     720             :   }
     721             : 
     722             :   void SerializeConstructor(JSHeapBroker* broker);
     723             :   ObjectData* GetConstructor() const {
     724        4542 :     CHECK(serialized_constructor_);
     725        4542 :     return constructor_;
     726             :   }
     727             : 
     728             :   void SerializePrototype(JSHeapBroker* broker);
     729             :   ObjectData* prototype() const {
     730          40 :     CHECK(serialized_prototype_);
     731          40 :     return prototype_;
     732             :   }
     733             : 
     734             :   void SerializeForElementLoad(JSHeapBroker* broker);
     735             : 
     736             :   void SerializeForElementStore(JSHeapBroker* broker);
     737             : 
     738             :  private:
     739             :   InstanceType const instance_type_;
     740             :   int const instance_size_;
     741             :   byte const bit_field_;
     742             :   byte const bit_field2_;
     743             :   uint32_t const bit_field3_;
     744             :   bool const can_be_deprecated_;
     745             :   bool const can_transition_;
     746             :   int const in_object_properties_start_in_words_;
     747             :   int const in_object_properties_;
     748             :   int const constructor_function_index_;
     749             :   int const next_free_property_index_;
     750             :   int const unused_property_fields_;
     751             :   bool const supports_fast_array_iteration_;
     752             :   bool const supports_fast_array_resize_;
     753             : 
     754             :   bool serialized_elements_kind_generalizations_ = false;
     755             :   ZoneVector<MapData*> elements_kind_generalizations_;
     756             : 
     757             :   bool serialized_own_descriptors_ = false;
     758             :   DescriptorArrayData* instance_descriptors_ = nullptr;
     759             : 
     760             :   bool serialized_constructor_ = false;
     761             :   ObjectData* constructor_ = nullptr;
     762             : 
     763             :   bool serialized_prototype_ = false;
     764             :   ObjectData* prototype_ = nullptr;
     765             : 
     766             :   bool serialized_for_element_load_ = false;
     767             : 
     768             :   bool serialized_for_element_store_ = false;
     769             : };
     770             : 
     771        7363 : AllocationSiteData::AllocationSiteData(JSHeapBroker* broker,
     772             :                                        ObjectData** storage,
     773             :                                        Handle<AllocationSite> object)
     774             :     : HeapObjectData(broker, storage, object),
     775             :       PointsToLiteral_(object->PointsToLiteral()),
     776       22089 :       GetAllocationType_(object->GetAllocationType()) {
     777        7363 :   if (PointsToLiteral_) {
     778             :     IsFastLiteral_ = IsInlinableFastLiteral(
     779        5914 :         handle(object->boilerplate(), broker->isolate()));
     780             :   } else {
     781        1449 :     GetElementsKind_ = object->GetElementsKind();
     782        1449 :     CanInlineCall_ = object->CanInlineCall();
     783             :   }
     784        7363 : }
     785             : 
     786        5775 : void AllocationSiteData::SerializeBoilerplate(JSHeapBroker* broker) {
     787        5775 :   if (serialized_boilerplate_) return;
     788        5775 :   serialized_boilerplate_ = true;
     789             : 
     790        5775 :   TraceScope tracer(broker, this, "AllocationSiteData::SerializeBoilerplate");
     791             :   Handle<AllocationSite> site = Handle<AllocationSite>::cast(object());
     792             : 
     793        5775 :   CHECK(IsFastLiteral_);
     794             :   DCHECK_NULL(boilerplate_);
     795        5775 :   boilerplate_ = broker->GetOrCreateData(site->boilerplate())->AsJSObject();
     796             :   boilerplate_->SerializeAsBoilerplate(broker);
     797             : 
     798             :   DCHECK_NULL(nested_site_);
     799        5775 :   nested_site_ = broker->GetOrCreateData(site->nested_site());
     800        5775 :   if (nested_site_->IsAllocationSite()) {
     801         248 :     nested_site_->AsAllocationSite()->SerializeBoilerplate(broker);
     802             :   }
     803             : }
     804             : 
     805    91540406 : HeapObjectData::HeapObjectData(JSHeapBroker* broker, ObjectData** storage,
     806             :                                Handle<HeapObject> object)
     807             :     : ObjectData(broker, storage, object, kSerializedHeapObject),
     808   183078964 :       boolean_value_(object->BooleanValue(broker->isolate())),
     809             :       // We have to use a raw cast below instead of AsMap() because of
     810             :       // recursion. AsMap() would call IsMap(), which accesses the
     811             :       // instance_type_ member. In the case of constructing the MapData for the
     812             :       // meta map (whose map is itself), this member has not yet been
     813             :       // initialized.
     814   274618684 :       map_(static_cast<MapData*>(broker->GetOrCreateData(object->map()))) {
     815    91539272 :   CHECK(broker->SerializingAllowed());
     816    91539272 : }
     817             : 
     818             : namespace {
     819     2761748 : bool IsReadOnlyLengthDescriptor(Isolate* isolate, Handle<Map> jsarray_map) {
     820             :   DCHECK(!jsarray_map->is_dictionary_map());
     821             :   Handle<Name> length_string = isolate->factory()->length_string();
     822     2761748 :   DescriptorArray descriptors = jsarray_map->instance_descriptors();
     823             :   int number = descriptors->Search(*length_string, *jsarray_map);
     824             :   DCHECK_NE(DescriptorArray::kNotFound, number);
     825     5523501 :   return descriptors->GetDetails(number).IsReadOnly();
     826             : }
     827             : 
     828    96292780 : bool SupportsFastArrayIteration(Isolate* isolate, Handle<Map> map) {
     829     6507115 :   return map->instance_type() == JS_ARRAY_TYPE &&
     830     6504992 :          IsFastElementsKind(map->elements_kind()) &&
     831     5575936 :          map->prototype()->IsJSArray() &&
     832     5575939 :          isolate->IsAnyInitialArrayPrototype(
     833   101868350 :              handle(JSArray::cast(map->prototype()), isolate)) &&
     834   101868363 :          isolate->IsNoElementsProtectorIntact();
     835             : }
     836             : 
     837    48146487 : bool SupportsFastArrayResize(Isolate* isolate, Handle<Map> map) {
     838    53669993 :   return SupportsFastArrayIteration(isolate, map) && map->is_extensible() &&
     839    50908095 :          !map->is_dictionary_map() && !IsReadOnlyLengthDescriptor(isolate, map);
     840             : }
     841             : }  // namespace
     842             : 
     843    48143569 : MapData::MapData(JSHeapBroker* broker, ObjectData** storage, Handle<Map> object)
     844             :     : HeapObjectData(broker, storage, object),
     845             :       instance_type_(object->instance_type()),
     846             :       instance_size_(object->instance_size()),
     847             :       bit_field_(object->bit_field()),
     848             :       bit_field2_(object->bit_field2()),
     849             :       bit_field3_(object->bit_field3()),
     850             :       can_be_deprecated_(object->NumberOfOwnDescriptors() > 0
     851    73299355 :                              ? object->CanBeDeprecated()
     852             :                              : false),
     853             :       can_transition_(object->CanTransition()),
     854             :       in_object_properties_start_in_words_(
     855             :           object->IsJSObjectMap() ? object->GetInObjectPropertiesStartInWords()
     856             :                                   : 0),
     857             :       in_object_properties_(
     858    80740285 :           object->IsJSObjectMap() ? object->GetInObjectProperties() : 0),
     859             :       constructor_function_index_(object->IsPrimitiveMap()
     860             :                                       ? object->GetConstructorFunctionIndex()
     861             :                                       : Map::kNoConstructorFunctionIndex),
     862    96286436 :       next_free_property_index_(object->NextFreePropertyIndex()),
     863    96286252 :       unused_property_fields_(object->UnusedPropertyFields()),
     864             :       supports_fast_array_iteration_(
     865    48143128 :           SupportsFastArrayIteration(broker->isolate(), object)),
     866             :       supports_fast_array_resize_(
     867    48143075 :           SupportsFastArrayResize(broker->isolate(), object)),
     868   924329153 :       elements_kind_generalizations_(broker->zone()) {}
     869             : 
     870     7495124 : JSFunctionData::JSFunctionData(JSHeapBroker* broker, ObjectData** storage,
     871             :                                Handle<JSFunction> object)
     872             :     : JSObjectData(broker, storage, object),
     873    14990206 :       has_feedback_vector_(object->has_feedback_vector()),
     874    21448058 :       has_initial_map_(object->has_prototype_slot() &&
     875    13952937 :                        object->has_initial_map()),
     876    21448030 :       has_prototype_(object->has_prototype_slot() && object->has_prototype()),
     877             :       PrototypeRequiresRuntimeLookup_(
     878    29980428 :           object->PrototypeRequiresRuntimeLookup()) {}
     879             : 
     880     5204157 : void JSFunctionData::Serialize(JSHeapBroker* broker) {
     881     5694101 :   if (serialized_) return;
     882     4714213 :   serialized_ = true;
     883             : 
     884     4714213 :   TraceScope tracer(broker, this, "JSFunctionData::Serialize");
     885             :   Handle<JSFunction> function = Handle<JSFunction>::cast(object());
     886             : 
     887             :   DCHECK_NULL(context_);
     888             :   DCHECK_NULL(native_context_);
     889             :   DCHECK_NULL(initial_map_);
     890             :   DCHECK_NULL(prototype_);
     891             :   DCHECK_NULL(shared_);
     892             :   DCHECK_NULL(feedback_vector_);
     893             : 
     894     4714212 :   context_ = broker->GetOrCreateData(function->context())->AsContext();
     895             :   native_context_ =
     896     4714204 :       broker->GetOrCreateData(function->native_context())->AsNativeContext();
     897     4714202 :   shared_ = broker->GetOrCreateData(function->shared())->AsSharedFunctionInfo();
     898             :   feedback_vector_ = has_feedback_vector()
     899     5651706 :                          ? broker->GetOrCreateData(function->feedback_vector())
     900      468746 :                                ->AsFeedbackVector()
     901     9428410 :                          : nullptr;
     902             :   initial_map_ = has_initial_map()
     903     3721674 :                      ? broker->GetOrCreateData(function->initial_map())->AsMap()
     904     8435871 :                      : nullptr;
     905    12163539 :   prototype_ = has_prototype() ? broker->GetOrCreateData(function->prototype())
     906     9428432 :                                : nullptr;
     907             : 
     908     4714224 :   if (initial_map_ != nullptr) {
     909             :     initial_map_instance_size_with_min_slack_ =
     910     3721683 :         function->ComputeInstanceSizeWithMinSlack(broker->isolate());
     911     3721682 :     if (initial_map_->instance_type() == JS_ARRAY_TYPE) {
     912      464027 :       initial_map_->SerializeElementsKindGeneralizations(broker);
     913             :     }
     914     3721685 :     initial_map_->SerializeConstructor(broker);
     915             :     // TODO(neis): This is currently only needed for native_context's
     916             :     // object_function, as used by GetObjectCreateMap. If no further use sites
     917             :     // show up, we should move this into NativeContextData::Serialize.
     918     3721669 :     initial_map_->SerializePrototype(broker);
     919             :   }
     920             : }
     921             : 
     922      464025 : void MapData::SerializeElementsKindGeneralizations(JSHeapBroker* broker) {
     923      464025 :   if (serialized_elements_kind_generalizations_) return;
     924      464025 :   serialized_elements_kind_generalizations_ = true;
     925             : 
     926             :   TraceScope tracer(broker, this,
     927      464025 :                     "MapData::SerializeElementsKindGeneralizations");
     928             :   DCHECK_EQ(instance_type(), JS_ARRAY_TYPE);
     929             :   MapRef self(broker, this);
     930      464026 :   ElementsKind from_kind = self.elements_kind();
     931             :   DCHECK(elements_kind_generalizations_.empty());
     932     6032348 :   for (int i = FIRST_FAST_ELEMENTS_KIND; i <= LAST_FAST_ELEMENTS_KIND; i++) {
     933             :     ElementsKind to_kind = static_cast<ElementsKind>(i);
     934     2784161 :     if (IsMoreGeneralElementsKindTransition(from_kind, to_kind)) {
     935             :       Handle<Map> target =
     936     2320137 :           Map::AsElementsKind(broker->isolate(), self.object(), to_kind);
     937     4640249 :       elements_kind_generalizations_.push_back(
     938     4640277 :           broker->GetOrCreateData(target)->AsMap());
     939             :     }
     940             :   }
     941             : }
     942             : 
     943             : class DescriptorArrayData : public HeapObjectData {
     944             :  public:
     945        3631 :   DescriptorArrayData(JSHeapBroker* broker, ObjectData** storage,
     946             :                       Handle<DescriptorArray> object)
     947        7262 :       : HeapObjectData(broker, storage, object), contents_(broker->zone()) {}
     948             : 
     949             :   ZoneVector<PropertyDescriptor>& contents() { return contents_; }
     950             : 
     951             :  private:
     952             :   ZoneVector<PropertyDescriptor> contents_;
     953             : };
     954             : 
     955             : class FeedbackVectorData : public HeapObjectData {
     956             :  public:
     957             :   const ZoneVector<ObjectData*>& feedback() { return feedback_; }
     958             : 
     959             :   FeedbackVectorData(JSHeapBroker* broker, ObjectData** storage,
     960             :                      Handle<FeedbackVector> object);
     961             : 
     962             :   void SerializeSlots(JSHeapBroker* broker);
     963             : 
     964             :  private:
     965             :   bool serialized_ = false;
     966             :   ZoneVector<ObjectData*> feedback_;
     967             : };
     968             : 
     969      469306 : FeedbackVectorData::FeedbackVectorData(JSHeapBroker* broker,
     970             :                                        ObjectData** storage,
     971             :                                        Handle<FeedbackVector> object)
     972      938601 :     : HeapObjectData(broker, storage, object), feedback_(broker->zone()) {}
     973             : 
     974       52495 : void FeedbackVectorData::SerializeSlots(JSHeapBroker* broker) {
     975       70661 :   if (serialized_) return;
     976       34329 :   serialized_ = true;
     977             : 
     978       34329 :   TraceScope tracer(broker, this, "FeedbackVectorData::SerializeSlots");
     979             :   Handle<FeedbackVector> vector = Handle<FeedbackVector>::cast(object());
     980             :   DCHECK(feedback_.empty());
     981       34329 :   feedback_.reserve(vector->length());
     982     1356334 :   for (int i = 0; i < vector->length(); ++i) {
     983             :     MaybeObject value = vector->get(i);
     984             :     ObjectData* slot_value =
     985             :         value->IsObject() ? broker->GetOrCreateData(value->cast<Object>())
     986      661002 :                           : nullptr;
     987      661009 :     feedback_.push_back(slot_value);
     988      760986 :     if (slot_value == nullptr) continue;
     989             : 
     990      567708 :     if (slot_value->IsAllocationSite() &&
     991        6686 :         slot_value->AsAllocationSite()->IsFastLiteral()) {
     992        5527 :       slot_value->AsAllocationSite()->SerializeBoilerplate(broker);
     993      555494 :     } else if (slot_value->IsJSRegExp()) {
     994         498 :       slot_value->AsJSRegExp()->SerializeAsRegExpBoilerplate(broker);
     995             :     }
     996             :   }
     997             :   DCHECK_EQ(vector->length(), feedback_.size());
     998       34330 :   TRACE(broker, "Copied " << feedback_.size() << " slots.");
     999             : }
    1000             : 
    1001             : class FixedArrayBaseData : public HeapObjectData {
    1002             :  public:
    1003     1127226 :   FixedArrayBaseData(JSHeapBroker* broker, ObjectData** storage,
    1004             :                      Handle<FixedArrayBase> object)
    1005     2254460 :       : HeapObjectData(broker, storage, object), length_(object->length()) {}
    1006             : 
    1007             :   int length() const { return length_; }
    1008             : 
    1009             :  private:
    1010             :   int const length_;
    1011             : };
    1012             : 
    1013             : class FixedArrayData : public FixedArrayBaseData {
    1014             :  public:
    1015             :   FixedArrayData(JSHeapBroker* broker, ObjectData** storage,
    1016             :                  Handle<FixedArray> object);
    1017             : 
    1018             :   // Creates all elements of the fixed array.
    1019             :   void SerializeContents(JSHeapBroker* broker);
    1020             : 
    1021             :   ObjectData* Get(int i) const;
    1022             : 
    1023             :  private:
    1024             :   bool serialized_contents_ = false;
    1025             :   ZoneVector<ObjectData*> contents_;
    1026             : };
    1027             : 
    1028         160 : JSDataViewData::JSDataViewData(JSHeapBroker* broker, ObjectData** storage,
    1029             :                                Handle<JSDataView> object)
    1030             :     : JSObjectData(broker, storage, object),
    1031             :       byte_length_(object->byte_length()),
    1032         320 :       byte_offset_(object->byte_offset()) {}
    1033             : 
    1034         165 : JSBoundFunctionData::JSBoundFunctionData(JSHeapBroker* broker,
    1035             :                                          ObjectData** storage,
    1036             :                                          Handle<JSBoundFunction> object)
    1037         165 :     : JSObjectData(broker, storage, object) {}
    1038             : 
    1039           0 : void JSBoundFunctionData::Serialize(JSHeapBroker* broker) {
    1040           0 :   if (serialized_) return;
    1041           0 :   serialized_ = true;
    1042             : 
    1043           0 :   TraceScope tracer(broker, this, "JSBoundFunctionData::Serialize");
    1044             :   Handle<JSBoundFunction> function = Handle<JSBoundFunction>::cast(object());
    1045             : 
    1046             :   DCHECK_NULL(bound_target_function_);
    1047             :   DCHECK_NULL(bound_this_);
    1048             :   DCHECK_NULL(bound_arguments_);
    1049             : 
    1050             :   bound_target_function_ =
    1051           0 :       broker->GetOrCreateData(function->bound_target_function());
    1052           0 :   bound_this_ = broker->GetOrCreateData(function->bound_this());
    1053             :   bound_arguments_ =
    1054           0 :       broker->GetOrCreateData(function->bound_arguments())->AsFixedArray();
    1055             : 
    1056           0 :   bound_arguments_->SerializeContents(broker);
    1057             : }
    1058             : 
    1059     3313878 : JSObjectData::JSObjectData(JSHeapBroker* broker, ObjectData** storage,
    1060             :                            Handle<JSObject> object)
    1061             :     : HeapObjectData(broker, storage, object),
    1062    23494763 :       inobject_fields_(broker->zone()) {}
    1063             : 
    1064      512937 : FixedArrayData::FixedArrayData(JSHeapBroker* broker, ObjectData** storage,
    1065             :                                Handle<FixedArray> object)
    1066     1025876 :     : FixedArrayBaseData(broker, storage, object), contents_(broker->zone()) {}
    1067             : 
    1068        1567 : void FixedArrayData::SerializeContents(JSHeapBroker* broker) {
    1069        1567 :   if (serialized_contents_) return;
    1070        1567 :   serialized_contents_ = true;
    1071             : 
    1072        1567 :   TraceScope tracer(broker, this, "FixedArrayData::SerializeContents");
    1073             :   Handle<FixedArray> array = Handle<FixedArray>::cast(object());
    1074        1567 :   CHECK_EQ(array->length(), length());
    1075        1567 :   CHECK(contents_.empty());
    1076        1567 :   contents_.reserve(static_cast<size_t>(length()));
    1077             : 
    1078       14547 :   for (int i = 0; i < length(); i++) {
    1079             :     Handle<Object> value(array->get(i), broker->isolate());
    1080       12980 :     contents_.push_back(broker->GetOrCreateData(value));
    1081             :   }
    1082        1567 :   TRACE(broker, "Copied " << contents_.size() << " elements.");
    1083             : }
    1084             : 
    1085             : class FixedDoubleArrayData : public FixedArrayBaseData {
    1086             :  public:
    1087             :   FixedDoubleArrayData(JSHeapBroker* broker, ObjectData** storage,
    1088             :                        Handle<FixedDoubleArray> object);
    1089             : 
    1090             :   // Serializes all elements of the fixed array.
    1091             :   void SerializeContents(JSHeapBroker* broker);
    1092             : 
    1093             :   Float64 Get(int i) const;
    1094             : 
    1095             :  private:
    1096             :   bool serialized_contents_ = false;
    1097             :   ZoneVector<Float64> contents_;
    1098             : };
    1099             : 
    1100         531 : FixedDoubleArrayData::FixedDoubleArrayData(JSHeapBroker* broker,
    1101             :                                            ObjectData** storage,
    1102             :                                            Handle<FixedDoubleArray> object)
    1103        1062 :     : FixedArrayBaseData(broker, storage, object), contents_(broker->zone()) {}
    1104             : 
    1105         531 : void FixedDoubleArrayData::SerializeContents(JSHeapBroker* broker) {
    1106         531 :   if (serialized_contents_) return;
    1107         531 :   serialized_contents_ = true;
    1108             : 
    1109         531 :   TraceScope tracer(broker, this, "FixedDoubleArrayData::SerializeContents");
    1110             :   Handle<FixedDoubleArray> self = Handle<FixedDoubleArray>::cast(object());
    1111         531 :   CHECK_EQ(self->length(), length());
    1112         531 :   CHECK(contents_.empty());
    1113         531 :   contents_.reserve(static_cast<size_t>(length()));
    1114             : 
    1115       14921 :   for (int i = 0; i < length(); i++) {
    1116       14390 :     contents_.push_back(Float64::FromBits(self->get_representation(i)));
    1117             :   }
    1118         531 :   TRACE(broker, "Copied " << contents_.size() << " elements.");
    1119             : }
    1120             : 
    1121             : class BytecodeArrayData : public FixedArrayBaseData {
    1122             :  public:
    1123             :   int register_count() const { return register_count_; }
    1124             : 
    1125      613762 :   BytecodeArrayData(JSHeapBroker* broker, ObjectData** storage,
    1126             :                     Handle<BytecodeArray> object)
    1127             :       : FixedArrayBaseData(broker, storage, object),
    1128     1227526 :         register_count_(object->register_count()) {}
    1129             : 
    1130             :  private:
    1131             :   int const register_count_;
    1132             : };
    1133             : 
    1134             : class JSArrayData : public JSObjectData {
    1135             :  public:
    1136             :   JSArrayData(JSHeapBroker* broker, ObjectData** storage,
    1137             :               Handle<JSArray> object);
    1138             :   void Serialize(JSHeapBroker* broker);
    1139             : 
    1140             :   ObjectData* length() const { return length_; }
    1141             : 
    1142             :  private:
    1143             :   bool serialized_ = false;
    1144             :   ObjectData* length_ = nullptr;
    1145             : };
    1146             : 
    1147      472770 : JSArrayData::JSArrayData(JSHeapBroker* broker, ObjectData** storage,
    1148             :                          Handle<JSArray> object)
    1149      472770 :     : JSObjectData(broker, storage, object) {}
    1150             : 
    1151        3948 : void JSArrayData::Serialize(JSHeapBroker* broker) {
    1152        3948 :   if (serialized_) return;
    1153        3948 :   serialized_ = true;
    1154             : 
    1155        3948 :   TraceScope tracer(broker, this, "JSArrayData::Serialize");
    1156             :   Handle<JSArray> jsarray = Handle<JSArray>::cast(object());
    1157             :   DCHECK_NULL(length_);
    1158        3948 :   length_ = broker->GetOrCreateData(jsarray->length());
    1159             : }
    1160             : 
    1161             : class ScopeInfoData : public HeapObjectData {
    1162             :  public:
    1163             :   ScopeInfoData(JSHeapBroker* broker, ObjectData** storage,
    1164             :                 Handle<ScopeInfo> object);
    1165             : 
    1166             :   int context_length() const { return context_length_; }
    1167             : 
    1168             :  private:
    1169             :   int const context_length_;
    1170             : };
    1171             : 
    1172       55558 : ScopeInfoData::ScopeInfoData(JSHeapBroker* broker, ObjectData** storage,
    1173             :                              Handle<ScopeInfo> object)
    1174             :     : HeapObjectData(broker, storage, object),
    1175      111116 :       context_length_(object->ContextLength()) {}
    1176             : 
    1177             : class SharedFunctionInfoData : public HeapObjectData {
    1178             :  public:
    1179             :   SharedFunctionInfoData(JSHeapBroker* broker, ObjectData** storage,
    1180             :                          Handle<SharedFunctionInfo> object);
    1181             : 
    1182             :   int builtin_id() const { return builtin_id_; }
    1183             :   BytecodeArrayData* GetBytecodeArray() const { return GetBytecodeArray_; }
    1184             :   void SetSerializedForCompilation(JSHeapBroker* broker,
    1185             :                                    FeedbackVectorRef feedback);
    1186             :   bool IsSerializedForCompilation(FeedbackVectorRef feedback) const;
    1187             : #define DECL_ACCESSOR(type, name) \
    1188             :   type name() const { return name##_; }
    1189             :   BROKER_SFI_FIELDS(DECL_ACCESSOR)
    1190             : #undef DECL_ACCESSOR
    1191             : 
    1192             :  private:
    1193             :   int const builtin_id_;
    1194             :   BytecodeArrayData* const GetBytecodeArray_;
    1195             :   ZoneUnorderedSet<Handle<FeedbackVector>, Handle<FeedbackVector>::hash,
    1196             :                    Handle<FeedbackVector>::equal_to>
    1197             :       serialized_for_compilation_;
    1198             : #define DECL_MEMBER(type, name) type const name##_;
    1199             :   BROKER_SFI_FIELDS(DECL_MEMBER)
    1200             : #undef DECL_MEMBER
    1201             : };
    1202             : 
    1203     7015655 : SharedFunctionInfoData::SharedFunctionInfoData(
    1204             :     JSHeapBroker* broker, ObjectData** storage,
    1205             :     Handle<SharedFunctionInfo> object)
    1206             :     : HeapObjectData(broker, storage, object),
    1207             :       builtin_id_(object->HasBuiltinId() ? object->builtin_id()
    1208             :                                          : Builtins::kNoBuiltinId),
    1209             :       GetBytecodeArray_(
    1210    14031259 :           object->HasBytecodeArray()
    1211     7629388 :               ? broker->GetOrCreateData(object->GetBytecodeArray())
    1212      613765 :                     ->AsBytecodeArray()
    1213             :               : nullptr),
    1214             :       serialized_for_compilation_(broker->zone())
    1215             : #define INIT_MEMBER(type, name) , name##_(object->name())
    1216   112863598 :           BROKER_SFI_FIELDS(INIT_MEMBER)
    1217             : #undef INIT_MEMBER
    1218             : {
    1219             :   DCHECK_EQ(HasBuiltinId_, builtin_id_ != Builtins::kNoBuiltinId);
    1220             :   DCHECK_EQ(HasBytecodeArray_, GetBytecodeArray_ != nullptr);
    1221     7015639 : }
    1222             : 
    1223         147 : void SharedFunctionInfoData::SetSerializedForCompilation(
    1224             :     JSHeapBroker* broker, FeedbackVectorRef feedback) {
    1225         294 :   CHECK(serialized_for_compilation_.insert(feedback.object()).second);
    1226         147 :   TRACE(broker, "Set function " << object() << " with " << feedback.object()
    1227             :                                 << " as serialized for compilation.");
    1228         147 : }
    1229             : 
    1230           0 : bool SharedFunctionInfoData::IsSerializedForCompilation(
    1231             :     FeedbackVectorRef feedback) const {
    1232         648 :   return serialized_for_compilation_.find(feedback.object()) !=
    1233           0 :          serialized_for_compilation_.end();
    1234             : }
    1235             : 
    1236             : class ModuleData : public HeapObjectData {
    1237             :  public:
    1238             :   ModuleData(JSHeapBroker* broker, ObjectData** storage, Handle<Module> object);
    1239             :   void Serialize(JSHeapBroker* broker);
    1240             : 
    1241             :   CellData* GetCell(int cell_index) const;
    1242             : 
    1243             :  private:
    1244             :   bool serialized_ = false;
    1245             :   ZoneVector<CellData*> imports_;
    1246             :   ZoneVector<CellData*> exports_;
    1247             : };
    1248             : 
    1249          85 : ModuleData::ModuleData(JSHeapBroker* broker, ObjectData** storage,
    1250             :                        Handle<Module> object)
    1251             :     : HeapObjectData(broker, storage, object),
    1252             :       imports_(broker->zone()),
    1253         170 :       exports_(broker->zone()) {}
    1254             : 
    1255         138 : CellData* ModuleData::GetCell(int cell_index) const {
    1256         138 :   CHECK(serialized_);
    1257             :   CellData* cell;
    1258         138 :   switch (ModuleDescriptor::GetCellIndexKind(cell_index)) {
    1259             :     case ModuleDescriptor::kImport:
    1260          62 :       cell = imports_.at(Module::ImportIndex(cell_index));
    1261          31 :       break;
    1262             :     case ModuleDescriptor::kExport:
    1263         214 :       cell = exports_.at(Module::ExportIndex(cell_index));
    1264         107 :       break;
    1265             :     case ModuleDescriptor::kInvalid:
    1266           0 :       UNREACHABLE();
    1267             :       break;
    1268             :   }
    1269         138 :   CHECK_NOT_NULL(cell);
    1270         138 :   return cell;
    1271             : }
    1272             : 
    1273         170 : void ModuleData::Serialize(JSHeapBroker* broker) {
    1274         255 :   if (serialized_) return;
    1275          85 :   serialized_ = true;
    1276             : 
    1277          85 :   TraceScope tracer(broker, this, "ModuleData::Serialize");
    1278             :   Handle<Module> module = Handle<Module>::cast(object());
    1279             : 
    1280             :   // TODO(neis): We could be smarter and only serialize the cells we care about.
    1281             :   // TODO(neis): Define a helper for serializing a FixedArray into a ZoneVector.
    1282             : 
    1283             :   DCHECK(imports_.empty());
    1284             :   Handle<FixedArray> imports(module->regular_imports(), broker->isolate());
    1285             :   int const imports_length = imports->length();
    1286          85 :   imports_.reserve(imports_length);
    1287         273 :   for (int i = 0; i < imports_length; ++i) {
    1288         188 :     imports_.push_back(broker->GetOrCreateData(imports->get(i))->AsCell());
    1289             :   }
    1290          85 :   TRACE(broker, "Copied " << imports_.size() << " imports.");
    1291             : 
    1292             :   DCHECK(exports_.empty());
    1293             :   Handle<FixedArray> exports(module->regular_exports(), broker->isolate());
    1294             :   int const exports_length = exports->length();
    1295          85 :   exports_.reserve(exports_length);
    1296         433 :   for (int i = 0; i < exports_length; ++i) {
    1297         348 :     exports_.push_back(broker->GetOrCreateData(exports->get(i))->AsCell());
    1298             :   }
    1299          85 :   TRACE(broker, "Copied " << exports_.size() << " exports.");
    1300             : }
    1301             : 
    1302             : class CellData : public HeapObjectData {
    1303             :  public:
    1304             :   CellData(JSHeapBroker* broker, ObjectData** storage, Handle<Cell> object);
    1305             : 
    1306             :   void Serialize(JSHeapBroker* broker);
    1307             :   ObjectData* value() { return value_; }
    1308             : 
    1309             :  private:
    1310             :   bool serialized_ = false;
    1311             :   ObjectData* value_ = nullptr;
    1312             : };
    1313             : 
    1314      928012 : CellData::CellData(JSHeapBroker* broker, ObjectData** storage,
    1315             :                    Handle<Cell> object)
    1316      928012 :     : HeapObjectData(broker, storage, object) {}
    1317             : 
    1318      927753 : void CellData::Serialize(JSHeapBroker* broker) {
    1319      927753 :   if (serialized_) return;
    1320      927753 :   serialized_ = true;
    1321             : 
    1322      927753 :   TraceScope tracer(broker, this, "CellData::Serialize");
    1323             :   auto cell = Handle<Cell>::cast(object());
    1324             :   DCHECK_NULL(value_);
    1325      927754 :   value_ = broker->GetOrCreateData(cell->value());
    1326             : }
    1327             : 
    1328             : class JSGlobalProxyData : public JSObjectData {
    1329             :  public:
    1330      463879 :   JSGlobalProxyData(JSHeapBroker* broker, ObjectData** storage,
    1331             :                     Handle<JSGlobalProxy> object)
    1332      463873 :       : JSObjectData(broker, storage, object) {}
    1333             : };
    1334             : 
    1335             : class CodeData : public HeapObjectData {
    1336             :  public:
    1337     5820584 :   CodeData(JSHeapBroker* broker, ObjectData** storage, Handle<Code> object)
    1338     5820584 :       : HeapObjectData(broker, storage, object) {}
    1339             : };
    1340             : 
    1341             : #define DEFINE_IS_AND_AS(Name)                                            \
    1342             :   bool ObjectData::Is##Name() const {                                     \
    1343             :     if (kind() == kUnserializedHeapObject) {                              \
    1344             :       AllowHandleDereference allow_handle_dereference;                    \
    1345             :       return object()->Is##Name();                                        \
    1346             :     }                                                                     \
    1347             :     if (is_smi()) return false;                                           \
    1348             :     InstanceType instance_type =                                          \
    1349             :         static_cast<const HeapObjectData*>(this)->map()->instance_type(); \
    1350             :     return InstanceTypeChecker::Is##Name(instance_type);                  \
    1351             :   }                                                                       \
    1352             :   Name##Data* ObjectData::As##Name() {                                    \
    1353             :     CHECK_EQ(kind(), kSerializedHeapObject);                              \
    1354             :     CHECK(Is##Name());                                                    \
    1355             :     return static_cast<Name##Data*>(this);                                \
    1356             :   }
    1357   921596597 : HEAP_BROKER_OBJECT_LIST(DEFINE_IS_AND_AS)
    1358             : #undef DEFINE_IS_AND_AS
    1359             : 
    1360        3274 : const JSObjectField& JSObjectData::GetInobjectField(int property_index) const {
    1361        3274 :   CHECK_LT(static_cast<size_t>(property_index), inobject_fields_.size());
    1362        3274 :   return inobject_fields_[property_index];
    1363             : }
    1364             : 
    1365           0 : bool JSObjectData::cow_or_empty_elements_tenured() const {
    1366          40 :   return cow_or_empty_elements_tenured_;
    1367             : }
    1368             : 
    1369        7106 : FixedArrayBaseData* JSObjectData::elements() const { return elements_; }
    1370             : 
    1371           0 : void JSObjectData::SerializeAsBoilerplate(JSHeapBroker* broker) {
    1372        5775 :   SerializeRecursive(broker, kMaxFastLiteralDepth);
    1373           0 : }
    1374             : 
    1375         498 : void JSObjectData::SerializeElements(JSHeapBroker* broker) {
    1376         498 :   if (serialized_elements_) return;
    1377         498 :   serialized_elements_ = true;
    1378             : 
    1379         498 :   TraceScope tracer(broker, this, "JSObjectData::SerializeElements");
    1380             :   Handle<JSObject> boilerplate = Handle<JSObject>::cast(object());
    1381             :   Handle<FixedArrayBase> elements_object(boilerplate->elements(),
    1382             :                                          broker->isolate());
    1383             :   DCHECK_NULL(elements_);
    1384         498 :   elements_ = broker->GetOrCreateData(elements_object)->AsFixedArrayBase();
    1385             : }
    1386             : 
    1387    13459027 : void MapData::SerializeConstructor(JSHeapBroker* broker) {
    1388    13922905 :   if (serialized_constructor_) return;
    1389    12995149 :   serialized_constructor_ = true;
    1390             : 
    1391    12995149 :   TraceScope tracer(broker, this, "MapData::SerializeConstructor");
    1392             :   Handle<Map> map = Handle<Map>::cast(object());
    1393             :   DCHECK_NULL(constructor_);
    1394    12995148 :   constructor_ = broker->GetOrCreateData(map->GetConstructor());
    1395             : }
    1396             : 
    1397     4649419 : void MapData::SerializePrototype(JSHeapBroker* broker) {
    1398     4649419 :   if (serialized_prototype_) return;
    1399     4649419 :   serialized_prototype_ = true;
    1400             : 
    1401     4649419 :   TraceScope tracer(broker, this, "MapData::SerializePrototype");
    1402             :   Handle<Map> map = Handle<Map>::cast(object());
    1403             :   DCHECK_NULL(prototype_);
    1404     4649418 :   prototype_ = broker->GetOrCreateData(map->prototype());
    1405             : }
    1406             : 
    1407        8397 : void MapData::SerializeOwnDescriptors(JSHeapBroker* broker) {
    1408       13387 :   if (serialized_own_descriptors_) return;
    1409        4642 :   serialized_own_descriptors_ = true;
    1410             : 
    1411        4642 :   TraceScope tracer(broker, this, "MapData::SerializeOwnDescriptors");
    1412             :   Handle<Map> map = Handle<Map>::cast(object());
    1413             : 
    1414             :   DCHECK_NULL(instance_descriptors_);
    1415             :   instance_descriptors_ =
    1416        4642 :       broker->GetOrCreateData(map->instance_descriptors())->AsDescriptorArray();
    1417             : 
    1418             :   int const number_of_own = map->NumberOfOwnDescriptors();
    1419        4642 :   ZoneVector<PropertyDescriptor>& contents = instance_descriptors_->contents();
    1420        4642 :   int const current_size = static_cast<int>(contents.size());
    1421        4642 :   if (number_of_own <= current_size) return;
    1422             : 
    1423             :   Isolate* const isolate = broker->isolate();
    1424             :   auto descriptors =
    1425             :       Handle<DescriptorArray>::cast(instance_descriptors_->object());
    1426        3407 :   CHECK_EQ(*descriptors, map->instance_descriptors());
    1427        3407 :   contents.reserve(number_of_own);
    1428             : 
    1429             :   // Copy the new descriptors.
    1430       11597 :   for (int i = current_size; i < number_of_own; ++i) {
    1431             :     PropertyDescriptor d;
    1432        4095 :     d.key = broker->GetOrCreateData(descriptors->GetKey(i))->AsName();
    1433        4095 :     d.details = descriptors->GetDetails(i);
    1434        4095 :     if (d.details.location() == kField) {
    1435        2169 :       d.field_index = FieldIndex::ForDescriptor(*map, i);
    1436             :       d.field_owner =
    1437        2169 :           broker->GetOrCreateData(map->FindFieldOwner(isolate, i))->AsMap();
    1438        4338 :       d.field_type = broker->GetOrCreateData(descriptors->GetFieldType(i));
    1439        2169 :       d.is_unboxed_double_field = map->IsUnboxedDoubleField(d.field_index);
    1440             :       // Recurse.
    1441             :     }
    1442        4095 :     contents.push_back(d);
    1443             :   }
    1444        3407 :   CHECK_EQ(number_of_own, contents.size());
    1445             : 
    1446             :   // Recurse on the new owner maps.
    1447       11597 :   for (int i = current_size; i < number_of_own; ++i) {
    1448        4095 :     const PropertyDescriptor& d = contents[i];
    1449        4095 :     if (d.details.location() == kField) {
    1450        4338 :       CHECK_LE(
    1451             :           Handle<Map>::cast(d.field_owner->object())->NumberOfOwnDescriptors(),
    1452             :           number_of_own);
    1453        2169 :       d.field_owner->SerializeOwnDescriptors(broker);
    1454             :     }
    1455             :   }
    1456             : 
    1457        3407 :   TRACE(broker, "Copied " << number_of_own - current_size
    1458             :                           << " descriptors into " << instance_descriptors_
    1459             :                           << " (" << number_of_own << " total).");
    1460             : }
    1461             : 
    1462        6460 : void JSObjectData::SerializeRecursive(JSHeapBroker* broker, int depth) {
    1463        6708 :   if (serialized_as_boilerplate_) return;
    1464        6212 :   serialized_as_boilerplate_ = true;
    1465             : 
    1466        6212 :   TraceScope tracer(broker, this, "JSObjectData::SerializeRecursive");
    1467             :   Handle<JSObject> boilerplate = Handle<JSObject>::cast(object());
    1468             : 
    1469             :   // We only serialize boilerplates that pass the IsInlinableFastLiteral
    1470             :   // check, so we only do a sanity check on the depth here.
    1471        6212 :   CHECK_GT(depth, 0);
    1472        6212 :   CHECK(!boilerplate->map()->is_deprecated());
    1473             : 
    1474             :   // Serialize the elements.
    1475             :   Isolate* const isolate = broker->isolate();
    1476             :   Handle<FixedArrayBase> elements_object(boilerplate->elements(), isolate);
    1477             : 
    1478             :   // Boilerplates need special serialization - we need to make sure COW arrays
    1479             :   // are tenured. Boilerplate objects should only be reachable from their
    1480             :   // allocation site, so it is safe to assume that the elements have not been
    1481             :   // serialized yet.
    1482             : 
    1483             :   bool const empty_or_cow =
    1484       10236 :       elements_object->length() == 0 ||
    1485             :       elements_object->map() == ReadOnlyRoots(isolate).fixed_cow_array_map();
    1486        6212 :   if (empty_or_cow) {
    1487             :     // We need to make sure copy-on-write elements are tenured.
    1488        4114 :     if (ObjectInYoungGeneration(*elements_object)) {
    1489             :       elements_object = isolate->factory()->CopyAndTenureFixedCOWArray(
    1490        1584 :           Handle<FixedArray>::cast(elements_object));
    1491        1584 :       boilerplate->set_elements(*elements_object);
    1492             :     }
    1493        4114 :     cow_or_empty_elements_tenured_ = true;
    1494             :   }
    1495             : 
    1496             :   DCHECK_NULL(elements_);
    1497        6212 :   elements_ = broker->GetOrCreateData(elements_object)->AsFixedArrayBase();
    1498             : 
    1499        6212 :   if (empty_or_cow) {
    1500             :     // No need to do anything here. Empty or copy-on-write elements
    1501             :     // do not need to be serialized because we only need to store the elements
    1502             :     // reference to the allocated object.
    1503        4196 :   } else if (boilerplate->HasSmiOrObjectElements()) {
    1504        1567 :     elements_->AsFixedArray()->SerializeContents(broker);
    1505             :     Handle<FixedArray> fast_elements =
    1506             :         Handle<FixedArray>::cast(elements_object);
    1507             :     int length = elements_object->length();
    1508       14547 :     for (int i = 0; i < length; i++) {
    1509             :       Handle<Object> value(fast_elements->get(i), isolate);
    1510        6490 :       if (value->IsJSObject()) {
    1511         399 :         ObjectData* value_data = broker->GetOrCreateData(value);
    1512         399 :         value_data->AsJSObject()->SerializeRecursive(broker, depth - 1);
    1513             :       }
    1514             :     }
    1515             :   } else {
    1516        1062 :     CHECK(boilerplate->HasDoubleElements());
    1517         531 :     CHECK_LE(elements_object->Size(), kMaxRegularHeapObjectSize);
    1518         531 :     elements_->AsFixedDoubleArray()->SerializeContents(broker);
    1519             :   }
    1520             : 
    1521             :   // TODO(turbofan): Do we want to support out-of-object properties?
    1522       18636 :   CHECK(boilerplate->HasFastProperties() &&
    1523             :         boilerplate->property_array()->length() == 0);
    1524        6212 :   CHECK_EQ(inobject_fields_.size(), 0u);
    1525             : 
    1526             :   // Check the in-object properties.
    1527             :   Handle<DescriptorArray> descriptors(
    1528             :       boilerplate->map()->instance_descriptors(), isolate);
    1529             :   int const limit = boilerplate->map()->NumberOfOwnDescriptors();
    1530       19728 :   for (int i = 0; i < limit; i++) {
    1531        6758 :     PropertyDetails details = descriptors->GetDetails(i);
    1532       10706 :     if (details.location() != kField) continue;
    1533             :     DCHECK_EQ(kData, details.kind());
    1534             : 
    1535        2810 :     FieldIndex field_index = FieldIndex::ForDescriptor(boilerplate->map(), i);
    1536             :     // Make sure {field_index} agrees with {inobject_properties} on the index of
    1537             :     // this field.
    1538             :     DCHECK_EQ(field_index.property_index(),
    1539             :               static_cast<int>(inobject_fields_.size()));
    1540             :     if (boilerplate->IsUnboxedDoubleField(field_index)) {
    1541             :       double value = boilerplate->RawFastDoublePropertyAt(field_index);
    1542             :       inobject_fields_.push_back(JSObjectField{value});
    1543             :     } else {
    1544             :       Handle<Object> value(boilerplate->RawFastPropertyAt(field_index),
    1545        5620 :                            isolate);
    1546        2810 :       ObjectData* value_data = broker->GetOrCreateData(value);
    1547        2810 :       if (value->IsJSObject()) {
    1548         286 :         value_data->AsJSObject()->SerializeRecursive(broker, depth - 1);
    1549             :       }
    1550        5620 :       inobject_fields_.push_back(JSObjectField{value_data});
    1551             :     }
    1552             :   }
    1553        6212 :   TRACE(broker, "Copied " << inobject_fields_.size() << " in-object fields.");
    1554             : 
    1555        6212 :   map()->SerializeOwnDescriptors(broker);
    1556             : 
    1557        6212 :   if (IsJSArray()) AsJSArray()->Serialize(broker);
    1558             : }
    1559             : 
    1560         498 : void JSRegExpData::SerializeAsRegExpBoilerplate(JSHeapBroker* broker) {
    1561         498 :   if (serialized_as_reg_exp_boilerplate_) return;
    1562         498 :   serialized_as_reg_exp_boilerplate_ = true;
    1563             : 
    1564         498 :   TraceScope tracer(broker, this, "JSRegExpData::SerializeAsRegExpBoilerplate");
    1565             :   Handle<JSRegExp> boilerplate = Handle<JSRegExp>::cast(object());
    1566             : 
    1567         498 :   SerializeElements(broker);
    1568             : 
    1569             :   raw_properties_or_hash_ =
    1570         498 :       broker->GetOrCreateData(boilerplate->raw_properties_or_hash());
    1571         498 :   data_ = broker->GetOrCreateData(boilerplate->data());
    1572         498 :   source_ = broker->GetOrCreateData(boilerplate->source());
    1573         498 :   flags_ = broker->GetOrCreateData(boilerplate->flags());
    1574         498 :   last_index_ = broker->GetOrCreateData(boilerplate->last_index());
    1575             : }
    1576             : 
    1577     1262254 : bool ObjectRef::equals(const ObjectRef& other) const {
    1578    33665044 :   return data_ == other.data_;
    1579             : }
    1580             : 
    1581     1690724 : Isolate* ObjectRef::isolate() const { return broker()->isolate(); }
    1582             : 
    1583       22900 : ContextRef ContextRef::previous() const {
    1584       22900 :   if (broker()->mode() == JSHeapBroker::kDisabled) {
    1585             :     AllowHandleAllocation handle_allocation;
    1586             :     AllowHandleDereference handle_dereference;
    1587             :     return ContextRef(broker(),
    1588       45800 :                       handle(object()->previous(), broker()->isolate()));
    1589             :   }
    1590           0 :   return ContextRef(broker(), data()->AsContext()->previous());
    1591             : }
    1592             : 
    1593             : // Not needed for TypedLowering.
    1594       26463 : ObjectRef ContextRef::get(int index) const {
    1595       26463 :   if (broker()->mode() == JSHeapBroker::kDisabled) {
    1596             :     AllowHandleAllocation handle_allocation;
    1597             :     AllowHandleDereference handle_dereference;
    1598             :     Handle<Object> value(object()->get(index), broker()->isolate());
    1599       26447 :     return ObjectRef(broker(), value);
    1600             :   }
    1601          32 :   return ObjectRef(broker(), data()->AsContext()->GetSlot(index));
    1602             : }
    1603             : 
    1604      485563 : JSHeapBroker::JSHeapBroker(Isolate* isolate, Zone* broker_zone)
    1605             :     : isolate_(isolate),
    1606             :       broker_zone_(broker_zone),
    1607             :       current_zone_(broker_zone),
    1608             :       refs_(new (zone())
    1609      485566 :                 RefsMap(kMinimalRefsBucketCount, AddressMatcher(), zone())),
    1610             :       array_and_object_prototypes_(zone()),
    1611     1942257 :       feedback_(zone()) {
    1612             :   // Note that this initialization of the refs_ pointer with the minimal
    1613             :   // initial capacity is redundant in the normal use case (concurrent
    1614             :   // compilation enabled, standard objects to be serialized), as the map
    1615             :   // is going to be replaced immediatelly with a larger capacity one.
    1616             :   // It doesn't seem to affect the performance in a noticeable way though.
    1617      485572 :   TRACE(this, "Constructing heap broker.");
    1618      485572 : }
    1619             : 
    1620           0 : std::ostream& JSHeapBroker::Trace() {
    1621           0 :   return trace_out_ << "[" << this << "] "
    1622           0 :                     << std::string(trace_indentation_ * 2, ' ');
    1623             : }
    1624             : 
    1625      463859 : void JSHeapBroker::StartSerializing() {
    1626      463859 :   CHECK_EQ(mode_, kDisabled);
    1627      463859 :   TRACE(this, "Starting serialization.");
    1628      463867 :   mode_ = kSerializing;
    1629      463867 :   refs_->Clear();
    1630      463867 : }
    1631             : 
    1632      463870 : void JSHeapBroker::StopSerializing() {
    1633      463870 :   CHECK_EQ(mode_, kSerializing);
    1634      463870 :   TRACE(this, "Stopping serialization.");
    1635      463870 :   mode_ = kSerialized;
    1636      463870 : }
    1637             : 
    1638      463571 : void JSHeapBroker::Retire() {
    1639      463571 :   CHECK_EQ(mode_, kSerialized);
    1640      463571 :   TRACE(this, "Retiring.");
    1641      463571 :   mode_ = kRetired;
    1642      463571 : }
    1643             : 
    1644           0 : bool JSHeapBroker::SerializingAllowed() const { return mode() == kSerializing; }
    1645             : 
    1646      928239 : void JSHeapBroker::SetNativeContextRef() {
    1647     1856481 :   native_context_ = NativeContextRef(this, isolate()->native_context());
    1648      928242 : }
    1649             : 
    1650     5268098 : bool IsShareable(Handle<Object> object, Isolate* isolate) {
    1651             :   Builtins* const b = isolate->builtins();
    1652             : 
    1653             :   int index;
    1654             :   RootIndex root_index;
    1655     5268104 :   return (object->IsHeapObject() &&
    1656     5297452 :           b->IsBuiltinHandle(Handle<HeapObject>::cast(object), &index)) ||
    1657     5268070 :          isolate->roots_table().IsRootHandle(object, &root_index);
    1658             : }
    1659             : 
    1660      463855 : void JSHeapBroker::SerializeShareableObjects() {
    1661      463855 :   PerIsolateCompilerCache::Setup(isolate());
    1662      463858 :   compiler_cache_ = isolate()->compiler_cache();
    1663             : 
    1664      463858 :   if (compiler_cache_->HasSnapshot()) {
    1665             :     RefsMap* snapshot = compiler_cache_->GetSnapshot();
    1666             : 
    1667      449190 :     refs_ = new (zone()) RefsMap(snapshot, zone());
    1668      449201 :     return;
    1669             :   }
    1670             : 
    1671             :   TraceScope tracer(
    1672             :       this, "JSHeapBroker::SerializeShareableObjects (building snapshot)");
    1673             : 
    1674             :   refs_ =
    1675       29354 :       new (zone()) RefsMap(kInitialRefsBucketCount, AddressMatcher(), zone());
    1676             : 
    1677       14748 :   current_zone_ = compiler_cache_->zone();
    1678             : 
    1679             :   Builtins* const b = isolate()->builtins();
    1680             :   {
    1681             :     Builtins::Name builtins[] = {
    1682             :         Builtins::kAllocateInYoungGeneration,
    1683             :         Builtins::kAllocateInOldGeneration,
    1684             :         Builtins::kArgumentsAdaptorTrampoline,
    1685             :         Builtins::kArrayConstructorImpl,
    1686             :         Builtins::kCallFunctionForwardVarargs,
    1687             :         Builtins::kCallFunction_ReceiverIsAny,
    1688             :         Builtins::kCallFunction_ReceiverIsNotNullOrUndefined,
    1689             :         Builtins::kCallFunction_ReceiverIsNullOrUndefined,
    1690             :         Builtins::kConstructFunctionForwardVarargs,
    1691             :         Builtins::kForInFilter,
    1692             :         Builtins::kJSBuiltinsConstructStub,
    1693             :         Builtins::kJSConstructStubGeneric,
    1694             :         Builtins::kStringAdd_CheckNone,
    1695             :         Builtins::kStringAdd_ConvertLeft,
    1696             :         Builtins::kStringAdd_ConvertRight,
    1697             :         Builtins::kToNumber,
    1698             :         Builtins::kToObject,
    1699       14748 :     };
    1700      513732 :     for (auto id : builtins) {
    1701      498985 :       GetOrCreateData(b->builtin_handle(id));
    1702             :     }
    1703             :   }
    1704    44481010 :   for (int32_t id = 0; id < Builtins::builtin_count; ++id) {
    1705    22233201 :     if (Builtins::KindOf(id) == Builtins::TFJ) {
    1706     9978506 :       GetOrCreateData(b->builtin_handle(id));
    1707             :     }
    1708             :   }
    1709             : 
    1710    15833651 :   for (RefsMap::Entry* p = refs_->Start(); p != nullptr; p = refs_->Next(p)) {
    1711     5268099 :     CHECK(IsShareable(p->value->object(), isolate()));
    1712             :   }
    1713             : 
    1714             :   // TODO(mslekova):
    1715             :   // Serialize root objects (from factory).
    1716       14677 :   compiler_cache()->SetSnapshot(refs_);
    1717       14677 :   current_zone_ = broker_zone_;
    1718             : }
    1719             : 
    1720      463876 : void JSHeapBroker::CollectArrayAndObjectPrototypes() {
    1721             :   DisallowHeapAllocation no_gc;
    1722      463876 :   CHECK_EQ(mode(), kSerializing);
    1723      463876 :   CHECK(array_and_object_prototypes_.empty());
    1724             : 
    1725             :   Object maybe_context = isolate()->heap()->native_contexts_list();
    1726     3877710 :   while (!maybe_context->IsUndefined(isolate())) {
    1727     1706918 :     Context context = Context::cast(maybe_context);
    1728             :     Object array_prot = context->get(Context::INITIAL_ARRAY_PROTOTYPE_INDEX);
    1729             :     Object object_prot = context->get(Context::INITIAL_OBJECT_PROTOTYPE_INDEX);
    1730     3413833 :     array_and_object_prototypes_.emplace(JSObject::cast(array_prot), isolate());
    1731     3413831 :     array_and_object_prototypes_.emplace(JSObject::cast(object_prot),
    1732     3413831 :                                          isolate());
    1733     1706917 :     maybe_context = context->next_context_link();
    1734             :   }
    1735             : 
    1736      463875 :   CHECK(!array_and_object_prototypes_.empty());
    1737      463875 : }
    1738             : 
    1739       65414 : bool JSHeapBroker::IsArrayOrObjectPrototype(const JSObjectRef& object) const {
    1740       65414 :   if (mode() == kDisabled) {
    1741      130812 :     return isolate()->IsInAnyContext(*object.object(),
    1742      127555 :                                      Context::INITIAL_ARRAY_PROTOTYPE_INDEX) ||
    1743       62149 :            isolate()->IsInAnyContext(*object.object(),
    1744             :                                      Context::INITIAL_OBJECT_PROTOTYPE_INDEX);
    1745             :   }
    1746           8 :   CHECK(!array_and_object_prototypes_.empty());
    1747          16 :   return array_and_object_prototypes_.find(object.object()) !=
    1748             :          array_and_object_prototypes_.end();
    1749             : }
    1750             : 
    1751      463877 : void JSHeapBroker::SerializeStandardObjects() {
    1752      463901 :   if (mode() == kDisabled) return;
    1753      463853 :   CHECK_EQ(mode(), kSerializing);
    1754             : 
    1755      463853 :   SerializeShareableObjects();
    1756             : 
    1757             :   TraceScope tracer(this, "JSHeapBroker::SerializeStandardObjects");
    1758             : 
    1759      463877 :   CollectArrayAndObjectPrototypes();
    1760             : 
    1761      463875 :   SetNativeContextRef();
    1762      463867 :   native_context().Serialize();
    1763             : 
    1764             :   Factory* const f = isolate()->factory();
    1765             : 
    1766             :   // Maps, strings, oddballs
    1767      463878 :   GetOrCreateData(f->arguments_marker_map());
    1768      463877 :   GetOrCreateData(f->bigint_string());
    1769      463877 :   GetOrCreateData(f->block_context_map());
    1770      463876 :   GetOrCreateData(f->boolean_map());
    1771      463877 :   GetOrCreateData(f->boolean_string());
    1772      463876 :   GetOrCreateData(f->catch_context_map());
    1773      463877 :   GetOrCreateData(f->empty_fixed_array());
    1774      463877 :   GetOrCreateData(f->empty_string());
    1775      463878 :   GetOrCreateData(f->eval_context_map());
    1776      463877 :   GetOrCreateData(f->false_string());
    1777      463878 :   GetOrCreateData(f->false_value());
    1778      463878 :   GetOrCreateData(f->fixed_array_map());
    1779      463878 :   GetOrCreateData(f->fixed_cow_array_map());
    1780      463877 :   GetOrCreateData(f->fixed_double_array_map());
    1781      463878 :   GetOrCreateData(f->function_context_map());
    1782      463877 :   GetOrCreateData(f->function_string());
    1783      463878 :   GetOrCreateData(f->heap_number_map());
    1784      463878 :   GetOrCreateData(f->length_string());
    1785      463878 :   GetOrCreateData(f->many_closures_cell_map());
    1786      463877 :   GetOrCreateData(f->minus_zero_value());
    1787      463877 :   GetOrCreateData(f->mutable_heap_number_map());
    1788      463878 :   GetOrCreateData(f->name_dictionary_map());
    1789      463878 :   GetOrCreateData(f->NaN_string());
    1790      463877 :   GetOrCreateData(f->null_map());
    1791      463874 :   GetOrCreateData(f->null_string());
    1792      463878 :   GetOrCreateData(f->null_value());
    1793      463878 :   GetOrCreateData(f->number_string());
    1794      463878 :   GetOrCreateData(f->object_string());
    1795      463878 :   GetOrCreateData(f->one_pointer_filler_map());
    1796      463874 :   GetOrCreateData(f->optimized_out());
    1797      463876 :   GetOrCreateData(f->optimized_out_map());
    1798      463877 :   GetOrCreateData(f->property_array_map());
    1799      463878 :   GetOrCreateData(f->sloppy_arguments_elements_map());
    1800      463877 :   GetOrCreateData(f->stale_register());
    1801      463878 :   GetOrCreateData(f->stale_register_map());
    1802      463877 :   GetOrCreateData(f->string_string());
    1803      463878 :   GetOrCreateData(f->symbol_string());
    1804      463877 :   GetOrCreateData(f->termination_exception_map());
    1805      463878 :   GetOrCreateData(f->the_hole_map());
    1806      463878 :   GetOrCreateData(f->the_hole_value());
    1807      463878 :   GetOrCreateData(f->true_string());
    1808      463878 :   GetOrCreateData(f->true_value());
    1809      463878 :   GetOrCreateData(f->undefined_map());
    1810      463878 :   GetOrCreateData(f->undefined_string());
    1811      463878 :   GetOrCreateData(f->undefined_value());
    1812      463878 :   GetOrCreateData(f->uninitialized_map());
    1813      463878 :   GetOrCreateData(f->with_context_map());
    1814      463878 :   GetOrCreateData(f->zero_string());
    1815             : 
    1816             :   // Protector cells
    1817             :   GetOrCreateData(f->array_buffer_detaching_protector())
    1818             :       ->AsPropertyCell()
    1819      463877 :       ->Serialize(this);
    1820      463878 :   GetOrCreateData(f->array_constructor_protector())->AsCell()->Serialize(this);
    1821             :   GetOrCreateData(f->array_iterator_protector())
    1822             :       ->AsPropertyCell()
    1823      463878 :       ->Serialize(this);
    1824             :   GetOrCreateData(f->array_species_protector())
    1825             :       ->AsPropertyCell()
    1826      463878 :       ->Serialize(this);
    1827             :   GetOrCreateData(f->no_elements_protector())
    1828             :       ->AsPropertyCell()
    1829      463878 :       ->Serialize(this);
    1830             :   GetOrCreateData(f->promise_hook_protector())
    1831             :       ->AsPropertyCell()
    1832      463878 :       ->Serialize(this);
    1833             :   GetOrCreateData(f->promise_species_protector())
    1834             :       ->AsPropertyCell()
    1835      463878 :       ->Serialize(this);
    1836             :   GetOrCreateData(f->promise_then_protector())
    1837             :       ->AsPropertyCell()
    1838      463878 :       ->Serialize(this);
    1839      463878 :   GetOrCreateData(f->string_length_protector())->AsCell()->Serialize(this);
    1840             : 
    1841             :   // CEntry stub
    1842      927754 :   GetOrCreateData(
    1843      463878 :       CodeFactory::CEntry(isolate(), 1, kDontSaveFPRegs, kArgvOnStack, true));
    1844             : 
    1845      463876 :   TRACE(this, "Finished serializing standard objects.");
    1846             : }
    1847             : 
    1848           0 : ObjectData* JSHeapBroker::GetData(Handle<Object> object) const {
    1849    51535580 :   RefsMap::Entry* entry = refs_->Lookup(object.address());
    1850    51535983 :   return entry ? entry->value : nullptr;
    1851             : }
    1852             : 
    1853             : // clang-format off
    1854   208342400 : ObjectData* JSHeapBroker::GetOrCreateData(Handle<Object> object) {
    1855   208342400 :   CHECK(SerializingAllowed());
    1856   208342400 :   RefsMap::Entry* entry = refs_->LookupOrInsert(object.address(), zone());
    1857   208347486 :   ObjectData** data_storage = &(entry->value);
    1858   208347486 :   if (*data_storage == nullptr) {
    1859             :     // TODO(neis): Remove these Allow* once we serialize everything upfront.
    1860             :     AllowHandleAllocation handle_allocation;
    1861             :     AllowHandleDereference handle_dereference;
    1862    92078448 :     if (object->IsSmi()) {
    1863     1070478 :       new (zone()) ObjectData(this, data_storage, object, kSmi);
    1864             : #define CREATE_DATA_IF_MATCH(name)                                             \
    1865             :     } else if (object->Is##name()) {                                           \
    1866             :       new (zone()) name##Data(this, data_storage, Handle<name>::cast(object));
    1867  2189199098 :     HEAP_BROKER_OBJECT_LIST(CREATE_DATA_IF_MATCH)
    1868             : #undef CREATE_DATA_IF_MATCH
    1869             :     } else {
    1870           0 :       UNREACHABLE();
    1871             :     }
    1872             :   }
    1873   208346140 :   CHECK_NOT_NULL(*data_storage);
    1874   208346140 :   return (*data_storage);
    1875             : }
    1876             : // clang-format on
    1877             : 
    1878   165001083 : ObjectData* JSHeapBroker::GetOrCreateData(Object object) {
    1879   164999640 :   return GetOrCreateData(handle(object, isolate()));
    1880             : }
    1881             : 
    1882             : #define DEFINE_IS_AND_AS(Name)                                    \
    1883             :   bool ObjectRef::Is##Name() const { return data()->Is##Name(); } \
    1884             :   Name##Ref ObjectRef::As##Name() const {                         \
    1885             :     DCHECK(Is##Name());                                           \
    1886             :     return Name##Ref(broker(), data());                           \
    1887             :   }
    1888    79692633 : HEAP_BROKER_OBJECT_LIST(DEFINE_IS_AND_AS)
    1889             : #undef DEFINE_IS_AND_AS
    1890             : 
    1891    24209932 : bool ObjectRef::IsSmi() const { return data()->is_smi(); }
    1892             : 
    1893      652396 : int ObjectRef::AsSmi() const {
    1894             :   DCHECK(IsSmi());
    1895             :   // Handle-dereference is always allowed for Handle<Smi>.
    1896      652396 :   return Handle<Smi>::cast(object())->value();
    1897             : }
    1898             : 
    1899          16 : base::Optional<MapRef> JSObjectRef::GetObjectCreateMap() const {
    1900          16 :   if (broker()->mode() == JSHeapBroker::kDisabled) {
    1901             :     AllowHandleAllocation handle_allocation;
    1902             :     AllowHandleDereference allow_handle_dereference;
    1903             :     AllowHeapAllocation heap_allocation;
    1904             :     Handle<Map> instance_map;
    1905           0 :     if (Map::TryGetObjectCreateMap(broker()->isolate(), object())
    1906             :             .ToHandle(&instance_map)) {
    1907           0 :       return MapRef(broker(), instance_map);
    1908             :     } else {
    1909           0 :       return base::Optional<MapRef>();
    1910             :     }
    1911             :   }
    1912          16 :   MapData* map_data = data()->AsJSObject()->object_create_map();
    1913             :   return map_data != nullptr ? MapRef(broker(), map_data)
    1914          24 :                              : base::Optional<MapRef>();
    1915             : }
    1916             : 
    1917             : #define DEF_TESTER(Type, ...)                              \
    1918             :   bool MapRef::Is##Type##Map() const {                     \
    1919             :     return InstanceTypeChecker::Is##Type(instance_type()); \
    1920             :   }
    1921      685564 : INSTANCE_TYPE_CHECKERS(DEF_TESTER)
    1922             : #undef DEF_TESTER
    1923             : 
    1924        1994 : base::Optional<MapRef> MapRef::AsElementsKind(ElementsKind kind) const {
    1925        1994 :   if (broker()->mode() == JSHeapBroker::kDisabled) {
    1926             :     AllowHandleAllocation handle_allocation;
    1927             :     AllowHeapAllocation heap_allocation;
    1928             :     AllowHandleDereference allow_handle_dereference;
    1929             :     return MapRef(broker(),
    1930           0 :                   Map::AsElementsKind(broker()->isolate(), object(), kind));
    1931             :   }
    1932        1994 :   if (kind == elements_kind()) return *this;
    1933             :   const ZoneVector<MapData*>& elements_kind_generalizations =
    1934         846 :       data()->AsMap()->elements_kind_generalizations();
    1935        1469 :   for (auto data : elements_kind_generalizations) {
    1936             :     MapRef map(broker(), data);
    1937        2315 :     if (map.elements_kind() == kind) return map;
    1938             :   }
    1939           0 :   return base::Optional<MapRef>();
    1940             : }
    1941             : 
    1942           0 : void MapRef::SerializeForElementLoad() {
    1943           0 :   CHECK_EQ(broker()->mode(), JSHeapBroker::kSerializing);
    1944           0 :   data()->AsMap()->SerializeForElementLoad(broker());
    1945           0 : }
    1946             : 
    1947           0 : void MapRef::SerializeForElementStore() {
    1948           0 :   CHECK_EQ(broker()->mode(), JSHeapBroker::kSerializing);
    1949           0 :   data()->AsMap()->SerializeForElementStore(broker());
    1950           0 : }
    1951             : 
    1952             : namespace {
    1953             : // This helper function has two modes. If {prototype_maps} is nullptr, the
    1954             : // prototype chain is serialized as necessary to determine the result.
    1955             : // Otherwise, the heap is untouched and the encountered prototypes are pushed
    1956             : // onto {prototype_maps}.
    1957           0 : bool HasOnlyStablePrototypesWithFastElementsHelper(
    1958             :     JSHeapBroker* broker, MapRef const& map,
    1959             :     ZoneVector<MapRef>* prototype_maps) {
    1960           0 :   for (MapRef prototype_map = map;;) {
    1961           0 :     if (prototype_maps == nullptr) prototype_map.SerializePrototype();
    1962           0 :     prototype_map = prototype_map.prototype().AsHeapObject().map();
    1963           0 :     if (prototype_map.oddball_type() == OddballType::kNull) return true;
    1964           0 :     if (!map.prototype().IsJSObject() || !prototype_map.is_stable() ||
    1965           0 :         !IsFastElementsKind(prototype_map.elements_kind())) {
    1966             :       return false;
    1967             :     }
    1968           0 :     if (prototype_maps != nullptr) prototype_maps->push_back(prototype_map);
    1969             :   }
    1970             : }
    1971             : }  // namespace
    1972             : 
    1973           0 : void MapData::SerializeForElementLoad(JSHeapBroker* broker) {
    1974           0 :   if (serialized_for_element_load_) return;
    1975           0 :   serialized_for_element_load_ = true;
    1976             : 
    1977           0 :   TraceScope tracer(broker, this, "MapData::SerializeForElementLoad");
    1978           0 :   SerializePrototype(broker);
    1979             : }
    1980             : 
    1981           0 : void MapData::SerializeForElementStore(JSHeapBroker* broker) {
    1982           0 :   if (serialized_for_element_store_) return;
    1983           0 :   serialized_for_element_store_ = true;
    1984             : 
    1985           0 :   TraceScope tracer(broker, this, "MapData::SerializeForElementStore");
    1986           0 :   HasOnlyStablePrototypesWithFastElementsHelper(broker, MapRef(broker, this),
    1987           0 :                                                 nullptr);
    1988             : }
    1989             : 
    1990        1957 : bool MapRef::HasOnlyStablePrototypesWithFastElements(
    1991             :     ZoneVector<MapRef>* prototype_maps) {
    1992        1957 :   for (MapRef prototype_map = *this;;) {
    1993        5766 :     if (prototype_maps == nullptr) prototype_map.SerializePrototype();
    1994        5766 :     prototype_map = prototype_map.prototype().AsHeapObject().map();
    1995        5766 :     if (prototype_map.oddball_type() == OddballType::kNull) return true;
    1996       11441 :     if (!prototype().IsJSObject() || !prototype_map.is_stable() ||
    1997        3809 :         !IsFastElementsKind(prototype_map.elements_kind())) {
    1998             :       return false;
    1999             :     }
    2000        3809 :     if (prototype_maps != nullptr) prototype_maps->push_back(prototype_map);
    2001             :   }
    2002             : }
    2003             : 
    2004        3805 : bool MapRef::supports_fast_array_iteration() const {
    2005        3805 :   if (broker()->mode() == JSHeapBroker::kDisabled) {
    2006             :     AllowHandleDereference allow_handle_dereference;
    2007             :     AllowHandleAllocation handle_allocation;
    2008        3805 :     return SupportsFastArrayIteration(broker()->isolate(), object());
    2009             :   }
    2010           0 :   return data()->AsMap()->supports_fast_array_iteration();
    2011             : }
    2012             : 
    2013        3388 : bool MapRef::supports_fast_array_resize() const {
    2014        3388 :   if (broker()->mode() == JSHeapBroker::kDisabled) {
    2015             :     AllowHandleDereference allow_handle_dereference;
    2016             :     AllowHandleAllocation handle_allocation;
    2017        3388 :     return SupportsFastArrayResize(broker()->isolate(), object());
    2018             :   }
    2019           0 :   return data()->AsMap()->supports_fast_array_resize();
    2020             : }
    2021             : 
    2022        5058 : int JSFunctionRef::InitialMapInstanceSizeWithMinSlack() const {
    2023        5058 :   if (broker()->mode() == JSHeapBroker::kDisabled) {
    2024             :     AllowHandleDereference allow_handle_dereference;
    2025             :     AllowHandleAllocation handle_allocation;
    2026           1 :     return object()->ComputeInstanceSizeWithMinSlack(broker()->isolate());
    2027             :   }
    2028       10114 :   return data()->AsJSFunction()->initial_map_instance_size_with_min_slack();
    2029             : }
    2030             : 
    2031             : // Not needed for TypedLowering.
    2032             : base::Optional<ScriptContextTableRef::LookupResult>
    2033           0 : ScriptContextTableRef::lookup(const NameRef& name) const {
    2034             :   AllowHandleAllocation handle_allocation;
    2035             :   AllowHandleDereference handle_dereference;
    2036           0 :   if (!name.IsString()) return {};
    2037             :   ScriptContextTable::LookupResult lookup_result;
    2038             :   auto table = object();
    2039           0 :   if (!ScriptContextTable::Lookup(broker()->isolate(), *table,
    2040           0 :                                   *name.AsString().object(), &lookup_result)) {
    2041           0 :     return {};
    2042             :   }
    2043             :   Handle<Context> script_context = ScriptContextTable::GetContext(
    2044           0 :       broker()->isolate(), table, lookup_result.context_index);
    2045             :   LookupResult result{ContextRef(broker(), script_context),
    2046           0 :                       lookup_result.mode == VariableMode::kConst,
    2047           0 :                       lookup_result.slot_index};
    2048             :   return result;
    2049             : }
    2050             : 
    2051    16896402 : OddballType MapRef::oddball_type() const {
    2052    16896402 :   if (instance_type() != ODDBALL_TYPE) {
    2053             :     return OddballType::kNone;
    2054             :   }
    2055             :   Factory* f = broker()->isolate()->factory();
    2056    10281767 :   if (equals(MapRef(broker(), f->undefined_map()))) {
    2057             :     return OddballType::kUndefined;
    2058             :   }
    2059     9350619 :   if (equals(MapRef(broker(), f->null_map()))) {
    2060             :     return OddballType::kNull;
    2061             :   }
    2062     9315781 :   if (equals(MapRef(broker(), f->boolean_map()))) {
    2063             :     return OddballType::kBoolean;
    2064             :   }
    2065     2519115 :   if (equals(MapRef(broker(), f->the_hole_map()))) {
    2066             :     return OddballType::kHole;
    2067             :   }
    2068      930806 :   if (equals(MapRef(broker(), f->uninitialized_map()))) {
    2069             :     return OddballType::kUninitialized;
    2070             :   }
    2071             :   DCHECK(equals(MapRef(broker(), f->termination_exception_map())) ||
    2072             :          equals(MapRef(broker(), f->arguments_marker_map())) ||
    2073             :          equals(MapRef(broker(), f->optimized_out_map())) ||
    2074             :          equals(MapRef(broker(), f->stale_register_map())));
    2075      928935 :   return OddballType::kOther;
    2076             : }
    2077             : 
    2078       52305 : ObjectRef FeedbackVectorRef::get(FeedbackSlot slot) const {
    2079       52305 :   if (broker()->mode() == JSHeapBroker::kDisabled) {
    2080             :     AllowHandleAllocation handle_allocation;
    2081             :     AllowHandleDereference handle_dereference;
    2082             :     Handle<Object> value(object()->Get(slot)->cast<Object>(),
    2083             :                          broker()->isolate());
    2084           0 :     return ObjectRef(broker(), value);
    2085             :   }
    2086             :   int i = FeedbackVector::GetIndex(slot);
    2087      156915 :   return ObjectRef(broker(), data()->AsFeedbackVector()->feedback().at(i));
    2088             : }
    2089             : 
    2090           0 : double JSObjectRef::RawFastDoublePropertyAt(FieldIndex index) const {
    2091           0 :   if (broker()->mode() == JSHeapBroker::kDisabled) {
    2092             :     AllowHandleDereference handle_dereference;
    2093             :     return object()->RawFastDoublePropertyAt(index);
    2094             :   }
    2095           0 :   JSObjectData* object_data = data()->AsJSObject();
    2096           0 :   CHECK(index.is_inobject());
    2097           0 :   return object_data->GetInobjectField(index.property_index()).AsDouble();
    2098             : }
    2099             : 
    2100        3274 : ObjectRef JSObjectRef::RawFastPropertyAt(FieldIndex index) const {
    2101        3274 :   if (broker()->mode() == JSHeapBroker::kDisabled) {
    2102             :     AllowHandleAllocation handle_allocation;
    2103             :     AllowHandleDereference handle_dereference;
    2104             :     return ObjectRef(broker(), handle(object()->RawFastPropertyAt(index),
    2105           0 :                                       broker()->isolate()));
    2106             :   }
    2107        3274 :   JSObjectData* object_data = data()->AsJSObject();
    2108        3274 :   CHECK(index.is_inobject());
    2109             :   return ObjectRef(
    2110             :       broker(),
    2111        6548 :       object_data->GetInobjectField(index.property_index()).AsObject());
    2112             : }
    2113             : 
    2114        5993 : bool AllocationSiteRef::IsFastLiteral() const {
    2115        5993 :   if (broker()->mode() == JSHeapBroker::kDisabled) {
    2116             :     AllowHeapAllocation allow_heap_allocation;  // For TryMigrateInstance.
    2117             :     AllowHandleAllocation allow_handle_allocation;
    2118             :     AllowHandleDereference allow_handle_dereference;
    2119             :     return IsInlinableFastLiteral(
    2120             :         handle(object()->boilerplate(), broker()->isolate()));
    2121             :   }
    2122        5993 :   return data()->AsAllocationSite()->IsFastLiteral();
    2123             : }
    2124             : 
    2125          40 : void JSObjectRef::EnsureElementsTenured() {
    2126          40 :   if (broker()->mode() == JSHeapBroker::kDisabled) {
    2127             :     AllowHandleAllocation allow_handle_allocation;
    2128             :     AllowHandleDereference allow_handle_dereference;
    2129             :     AllowHeapAllocation allow_heap_allocation;
    2130             : 
    2131           0 :     Handle<FixedArrayBase> object_elements = elements().object();
    2132           0 :     if (ObjectInYoungGeneration(*object_elements)) {
    2133             :       // If we would like to pretenure a fixed cow array, we must ensure that
    2134             :       // the array is already in old space, otherwise we'll create too many
    2135             :       // old-to-new-space pointers (overflowing the store buffer).
    2136             :       object_elements =
    2137             :           broker()->isolate()->factory()->CopyAndTenureFixedCOWArray(
    2138           0 :               Handle<FixedArray>::cast(object_elements));
    2139           0 :       object()->set_elements(*object_elements);
    2140             :     }
    2141             :     return;
    2142             :   }
    2143          80 :   CHECK(data()->AsJSObject()->cow_or_empty_elements_tenured());
    2144             : }
    2145             : 
    2146        3274 : FieldIndex MapRef::GetFieldIndexFor(int descriptor_index) const {
    2147        3274 :   if (broker()->mode() == JSHeapBroker::kDisabled) {
    2148             :     AllowHandleDereference allow_handle_dereference;
    2149           0 :     return FieldIndex::ForDescriptor(*object(), descriptor_index);
    2150             :   }
    2151        3274 :   DescriptorArrayData* descriptors = data()->AsMap()->instance_descriptors();
    2152        6548 :   return descriptors->contents().at(descriptor_index).field_index;
    2153             : }
    2154             : 
    2155       32800 : int MapRef::GetInObjectPropertyOffset(int i) const {
    2156       32800 :   if (broker()->mode() == JSHeapBroker::kDisabled) {
    2157             :     AllowHandleDereference allow_handle_dereference;
    2158             :     return object()->GetInObjectPropertyOffset(i);
    2159             :   }
    2160       32796 :   return (GetInObjectPropertiesStartInWords() + i) * kTaggedSize;
    2161             : }
    2162             : 
    2163       76207 : PropertyDetails MapRef::GetPropertyDetails(int descriptor_index) const {
    2164       76207 :   if (broker()->mode() == JSHeapBroker::kDisabled) {
    2165             :     AllowHandleDereference allow_handle_dereference;
    2166       68914 :     return object()->instance_descriptors()->GetDetails(descriptor_index);
    2167             :   }
    2168        7293 :   DescriptorArrayData* descriptors = data()->AsMap()->instance_descriptors();
    2169       14586 :   return descriptors->contents().at(descriptor_index).details;
    2170             : }
    2171             : 
    2172        3274 : NameRef MapRef::GetPropertyKey(int descriptor_index) const {
    2173        3274 :   if (broker()->mode() == JSHeapBroker::kDisabled) {
    2174             :     AllowHandleAllocation handle_allocation;
    2175             :     AllowHandleDereference allow_handle_dereference;
    2176             :     return NameRef(
    2177             :         broker(),
    2178           0 :         handle(object()->instance_descriptors()->GetKey(descriptor_index),
    2179           0 :                broker()->isolate()));
    2180             :   }
    2181        3274 :   DescriptorArrayData* descriptors = data()->AsMap()->instance_descriptors();
    2182        9822 :   return NameRef(broker(), descriptors->contents().at(descriptor_index).key);
    2183             : }
    2184             : 
    2185        4095 : bool MapRef::IsFixedCowArrayMap() const {
    2186             :   Handle<Map> fixed_cow_array_map =
    2187             :       ReadOnlyRoots(broker()->isolate()).fixed_cow_array_map_handle();
    2188        4095 :   return equals(MapRef(broker(), fixed_cow_array_map));
    2189             : }
    2190             : 
    2191      109567 : bool MapRef::IsPrimitiveMap() const {
    2192      117449 :   return instance_type() <= LAST_PRIMITIVE_TYPE;
    2193             : }
    2194             : 
    2195       73409 : MapRef MapRef::FindFieldOwner(int descriptor_index) const {
    2196       73409 :   if (broker()->mode() == JSHeapBroker::kDisabled) {
    2197             :     AllowHandleAllocation handle_allocation;
    2198             :     AllowHandleDereference allow_handle_dereference;
    2199             :     Handle<Map> owner(
    2200             :         object()->FindFieldOwner(broker()->isolate(), descriptor_index),
    2201      146786 :         broker()->isolate());
    2202       73393 :     return MapRef(broker(), owner);
    2203             :   }
    2204          16 :   DescriptorArrayData* descriptors = data()->AsMap()->instance_descriptors();
    2205             :   return MapRef(broker(),
    2206          48 :                 descriptors->contents().at(descriptor_index).field_owner);
    2207             : }
    2208             : 
    2209        4495 : ObjectRef MapRef::GetFieldType(int descriptor_index) const {
    2210        4495 :   if (broker()->mode() == JSHeapBroker::kDisabled) {
    2211             :     AllowHandleAllocation handle_allocation;
    2212             :     AllowHandleDereference allow_handle_dereference;
    2213             :     Handle<FieldType> field_type(
    2214        8958 :         object()->instance_descriptors()->GetFieldType(descriptor_index),
    2215             :         broker()->isolate());
    2216        4479 :     return ObjectRef(broker(), field_type);
    2217             :   }
    2218          16 :   DescriptorArrayData* descriptors = data()->AsMap()->instance_descriptors();
    2219             :   return ObjectRef(broker(),
    2220          48 :                    descriptors->contents().at(descriptor_index).field_type);
    2221             : }
    2222             : 
    2223        3274 : bool MapRef::IsUnboxedDoubleField(int descriptor_index) const {
    2224        3274 :   if (broker()->mode() == JSHeapBroker::kDisabled) {
    2225             :     AllowHandleDereference allow_handle_dereference;
    2226           0 :     return object()->IsUnboxedDoubleField(
    2227             :         FieldIndex::ForDescriptor(*object(), descriptor_index));
    2228             :   }
    2229        3274 :   DescriptorArrayData* descriptors = data()->AsMap()->instance_descriptors();
    2230        6548 :   return descriptors->contents().at(descriptor_index).is_unboxed_double_field;
    2231             : }
    2232             : 
    2233         108 : uint16_t StringRef::GetFirstChar() {
    2234         108 :   if (broker()->mode() == JSHeapBroker::kDisabled) {
    2235             :     AllowHandleDereference allow_handle_dereference;
    2236             :     return object()->Get(0);
    2237             :   }
    2238         108 :   return data()->AsString()->first_char();
    2239             : }
    2240             : 
    2241         841 : base::Optional<double> StringRef::ToNumber() {
    2242         841 :   if (broker()->mode() == JSHeapBroker::kDisabled) {
    2243             :     AllowHandleDereference allow_handle_dereference;
    2244             :     AllowHandleAllocation allow_handle_allocation;
    2245             :     AllowHeapAllocation allow_heap_allocation;
    2246             :     int flags = ALLOW_HEX | ALLOW_OCTAL | ALLOW_BINARY;
    2247           0 :     return StringToDouble(broker()->isolate(), object(), flags);
    2248             :   }
    2249         841 :   return data()->AsString()->to_number();
    2250             : }
    2251             : 
    2252         449 : uint32_t InternalizedStringRef::array_index() const {
    2253         449 :   if (broker()->mode() == JSHeapBroker::kDisabled) {
    2254             :     AllowHandleDereference allow_handle_dereference;
    2255             :     AllowHandleAllocation allow_handle_allocation;
    2256             :     uint32_t result;
    2257         449 :     if (!object()->AsArrayIndex(&result)) {
    2258         449 :       result = kNotAnArrayIndex;
    2259             :     }
    2260         449 :     return result;
    2261             :   }
    2262           0 :   return data()->AsInternalizedString()->array_index();
    2263             : }
    2264             : 
    2265        6779 : ObjectRef FixedArrayRef::get(int i) const {
    2266        6779 :   if (broker()->mode() == JSHeapBroker::kDisabled) {
    2267             :     AllowHandleAllocation handle_allocation;
    2268             :     AllowHandleDereference allow_handle_dereference;
    2269         208 :     return ObjectRef(broker(), handle(object()->get(i), broker()->isolate()));
    2270             :   }
    2271       13142 :   return ObjectRef(broker(), data()->AsFixedArray()->Get(i));
    2272             : }
    2273             : 
    2274        7195 : bool FixedDoubleArrayRef::is_the_hole(int i) const {
    2275        7195 :   if (broker()->mode() == JSHeapBroker::kDisabled) {
    2276             :     AllowHandleDereference allow_handle_dereference;
    2277             :     return object()->is_the_hole(i);
    2278             :   }
    2279       14390 :   return data()->AsFixedDoubleArray()->Get(i).is_hole_nan();
    2280             : }
    2281             : 
    2282        7096 : double FixedDoubleArrayRef::get_scalar(int i) const {
    2283        7096 :   if (broker()->mode() == JSHeapBroker::kDisabled) {
    2284             :     AllowHandleDereference allow_handle_dereference;
    2285             :     return object()->get_scalar(i);
    2286             :   }
    2287       14192 :   CHECK(!data()->AsFixedDoubleArray()->Get(i).is_hole_nan());
    2288        7096 :   return data()->AsFixedDoubleArray()->Get(i).get_scalar();
    2289             : }
    2290             : 
    2291             : #define IF_BROKER_DISABLED_ACCESS_HANDLE_C(holder, name) \
    2292             :   if (broker()->mode() == JSHeapBroker::kDisabled) {     \
    2293             :     AllowHandleAllocation handle_allocation;             \
    2294             :     AllowHandleDereference allow_handle_dereference;     \
    2295             :     return object()->name();                             \
    2296             :   }
    2297             : 
    2298             : #define IF_BROKER_DISABLED_ACCESS_HANDLE(holder, result, name)         \
    2299             :   if (broker()->mode() == JSHeapBroker::kDisabled) {                   \
    2300             :     AllowHandleAllocation handle_allocation;                           \
    2301             :     AllowHandleDereference allow_handle_dereference;                   \
    2302             :     return result##Ref(broker(),                                       \
    2303             :                        handle(object()->name(), broker()->isolate())); \
    2304             :   }
    2305             : 
    2306             : // Macros for definining a const getter that, depending on the broker mode,
    2307             : // either looks into the handle or into the serialized data.
    2308             : #define BIMODAL_ACCESSOR(holder, result, name)                             \
    2309             :   result##Ref holder##Ref::name() const {                                  \
    2310             :     IF_BROKER_DISABLED_ACCESS_HANDLE(holder, result, name);                \
    2311             :     return result##Ref(broker(), ObjectRef::data()->As##holder()->name()); \
    2312             :   }
    2313             : 
    2314             : // Like above except that the result type is not an XYZRef.
    2315             : #define BIMODAL_ACCESSOR_C(holder, result, name)      \
    2316             :   result holder##Ref::name() const {                  \
    2317             :     IF_BROKER_DISABLED_ACCESS_HANDLE_C(holder, name); \
    2318             :     return ObjectRef::data()->As##holder()->name();   \
    2319             :   }
    2320             : 
    2321             : // Like above but for BitFields.
    2322             : #define BIMODAL_ACCESSOR_B(holder, field, name, BitField)              \
    2323             :   typename BitField::FieldType holder##Ref::name() const {             \
    2324             :     IF_BROKER_DISABLED_ACCESS_HANDLE_C(holder, name);                  \
    2325             :     return BitField::decode(ObjectRef::data()->As##holder()->field()); \
    2326             :   }
    2327             : 
    2328       36132 : BIMODAL_ACCESSOR(AllocationSite, Object, nested_site)
    2329        1524 : BIMODAL_ACCESSOR_C(AllocationSite, bool, CanInlineCall)
    2330       22494 : BIMODAL_ACCESSOR_C(AllocationSite, bool, PointsToLiteral)
    2331        8856 : BIMODAL_ACCESSOR_C(AllocationSite, ElementsKind, GetElementsKind)
    2332       14500 : BIMODAL_ACCESSOR_C(AllocationSite, AllocationType, GetAllocationType)
    2333             : 
    2334        1545 : BIMODAL_ACCESSOR_C(BytecodeArray, int, register_count)
    2335             : 
    2336       75027 : BIMODAL_ACCESSOR(Cell, Object, value)
    2337             : 
    2338   203423382 : BIMODAL_ACCESSOR(HeapObject, Map, map)
    2339             : 
    2340       12057 : BIMODAL_ACCESSOR(JSArray, Object, length)
    2341             : 
    2342         666 : BIMODAL_ACCESSOR(JSBoundFunction, Object, bound_target_function)
    2343         501 : BIMODAL_ACCESSOR(JSBoundFunction, Object, bound_this)
    2344         666 : BIMODAL_ACCESSOR(JSBoundFunction, FixedArray, bound_arguments)
    2345             : 
    2346         848 : BIMODAL_ACCESSOR_C(JSDataView, size_t, byte_length)
    2347         424 : BIMODAL_ACCESSOR_C(JSDataView, size_t, byte_offset)
    2348             : 
    2349           0 : BIMODAL_ACCESSOR_C(JSFunction, bool, has_feedback_vector)
    2350       21044 : BIMODAL_ACCESSOR_C(JSFunction, bool, has_initial_map)
    2351        4758 : BIMODAL_ACCESSOR_C(JSFunction, bool, has_prototype)
    2352        4368 : BIMODAL_ACCESSOR_C(JSFunction, bool, PrototypeRequiresRuntimeLookup)
    2353        4788 : BIMODAL_ACCESSOR(JSFunction, Context, context)
    2354     1001846 : BIMODAL_ACCESSOR(JSFunction, NativeContext, native_context)
    2355       86463 : BIMODAL_ACCESSOR(JSFunction, Map, initial_map)
    2356        5276 : BIMODAL_ACCESSOR(JSFunction, Object, prototype)
    2357      911751 : BIMODAL_ACCESSOR(JSFunction, SharedFunctionInfo, shared)
    2358         177 : BIMODAL_ACCESSOR(JSFunction, FeedbackVector, feedback_vector)
    2359             : 
    2360       12516 : BIMODAL_ACCESSOR_C(JSTypedArray, bool, is_on_heap)
    2361        2654 : BIMODAL_ACCESSOR_C(JSTypedArray, size_t, length_value)
    2362        3981 : BIMODAL_ACCESSOR(JSTypedArray, HeapObject, buffer)
    2363             : 
    2364     2152279 : BIMODAL_ACCESSOR_B(Map, bit_field2, elements_kind, Map::ElementsKindBits)
    2365           0 : BIMODAL_ACCESSOR_B(Map, bit_field2, is_extensible, Map::IsExtensibleBit)
    2366           0 : BIMODAL_ACCESSOR_B(Map, bit_field3, is_deprecated, Map::IsDeprecatedBit)
    2367         400 : BIMODAL_ACCESSOR_B(Map, bit_field3, is_dictionary_map, Map::IsDictionaryMapBit)
    2368       25936 : BIMODAL_ACCESSOR_B(Map, bit_field3, NumberOfOwnDescriptors,
    2369             :                    Map::NumberOfOwnDescriptorsBits)
    2370         296 : BIMODAL_ACCESSOR_B(Map, bit_field3, has_hidden_prototype,
    2371             :                    Map::HasHiddenPrototypeBit)
    2372      184984 : BIMODAL_ACCESSOR_B(Map, bit_field3, is_migration_target,
    2373             :                    Map::IsMigrationTargetBit)
    2374      155776 : BIMODAL_ACCESSOR_B(Map, bit_field, has_prototype_slot, Map::HasPrototypeSlotBit)
    2375      104618 : BIMODAL_ACCESSOR_B(Map, bit_field, is_access_check_needed,
    2376             :                    Map::IsAccessCheckNeededBit)
    2377    66788634 : BIMODAL_ACCESSOR_B(Map, bit_field, is_callable, Map::IsCallableBit)
    2378      101354 : BIMODAL_ACCESSOR_B(Map, bit_field, has_indexed_interceptor,
    2379             :                    Map::HasIndexedInterceptorBit)
    2380       42050 : BIMODAL_ACCESSOR_B(Map, bit_field, is_constructor, Map::IsConstructorBit)
    2381    66760268 : BIMODAL_ACCESSOR_B(Map, bit_field, is_undetectable, Map::IsUndetectableBit)
    2382      141032 : BIMODAL_ACCESSOR_C(Map, int, instance_size)
    2383        6894 : BIMODAL_ACCESSOR_C(Map, int, NextFreePropertyIndex)
    2384           0 : BIMODAL_ACCESSOR_C(Map, int, UnusedPropertyFields)
    2385      299673 : BIMODAL_ACCESSOR(Map, Object, prototype)
    2386   101990174 : BIMODAL_ACCESSOR_C(Map, InstanceType, instance_type)
    2387       27522 : BIMODAL_ACCESSOR(Map, Object, GetConstructor)
    2388             : 
    2389             : #define DEF_NATIVE_CONTEXT_ACCESSOR(type, name) \
    2390             :   BIMODAL_ACCESSOR(NativeContext, type, name)
    2391      204666 : BROKER_NATIVE_CONTEXT_FIELDS(DEF_NATIVE_CONTEXT_ACCESSOR)
    2392             : #undef DEF_NATIVE_CONTEXT_ACCESSOR
    2393             : 
    2394      640428 : BIMODAL_ACCESSOR(PropertyCell, Object, value)
    2395     1122750 : BIMODAL_ACCESSOR_C(PropertyCell, PropertyDetails, property_details)
    2396             : 
    2397      257152 : BIMODAL_ACCESSOR_C(SharedFunctionInfo, int, builtin_id)
    2398        1545 : BIMODAL_ACCESSOR(SharedFunctionInfo, BytecodeArray, GetBytecodeArray)
    2399             : #define DEF_SFI_ACCESSOR(type, name) \
    2400             :   BIMODAL_ACCESSOR_C(SharedFunctionInfo, type, name)
    2401     2826059 : BROKER_SFI_FIELDS(DEF_SFI_ACCESSOR)
    2402             : #undef DEF_SFI_ACCESSOR
    2403             : 
    2404      163716 : BIMODAL_ACCESSOR_C(String, int, length)
    2405             : 
    2406        1327 : void* JSTypedArrayRef::elements_external_pointer() const {
    2407        1327 :   if (broker()->mode() == JSHeapBroker::kDisabled) {
    2408             :     AllowHandleDereference allow_handle_dereference;
    2409             :     return FixedTypedArrayBase::cast(object()->elements())->external_pointer();
    2410             :   }
    2411           0 :   return data()->AsJSTypedArray()->elements_external_pointer();
    2412             : }
    2413             : 
    2414          32 : bool MapRef::IsInobjectSlackTrackingInProgress() const {
    2415          32 :   IF_BROKER_DISABLED_ACCESS_HANDLE_C(Map, IsInobjectSlackTrackingInProgress);
    2416          32 :   return Map::ConstructionCounterBits::decode(data()->AsMap()->bit_field3()) !=
    2417          32 :          Map::kNoSlackTracking;
    2418             : }
    2419             : 
    2420        7882 : int MapRef::constructor_function_index() const {
    2421        7882 :   IF_BROKER_DISABLED_ACCESS_HANDLE_C(Map, GetConstructorFunctionIndex);
    2422           0 :   CHECK(IsPrimitiveMap());
    2423           0 :   return data()->AsMap()->constructor_function_index();
    2424             : }
    2425             : 
    2426      225391 : bool MapRef::is_stable() const {
    2427      225391 :   IF_BROKER_DISABLED_ACCESS_HANDLE_C(Map, is_stable);
    2428       27808 :   return !Map::IsUnstableBit::decode(data()->AsMap()->bit_field3());
    2429             : }
    2430             : 
    2431       21490 : bool MapRef::CanBeDeprecated() const {
    2432       42980 :   IF_BROKER_DISABLED_ACCESS_HANDLE_C(Map, CanBeDeprecated);
    2433           0 :   CHECK_GT(NumberOfOwnDescriptors(), 0);
    2434           0 :   return data()->AsMap()->can_be_deprecated();
    2435             : }
    2436             : 
    2437      160811 : bool MapRef::CanTransition() const {
    2438      160811 :   IF_BROKER_DISABLED_ACCESS_HANDLE_C(Map, CanTransition);
    2439          37 :   return data()->AsMap()->can_transition();
    2440             : }
    2441             : 
    2442       38822 : int MapRef::GetInObjectPropertiesStartInWords() const {
    2443       38822 :   IF_BROKER_DISABLED_ACCESS_HANDLE_C(Map, GetInObjectPropertiesStartInWords);
    2444       77642 :   return data()->AsMap()->in_object_properties_start_in_words();
    2445             : }
    2446             : 
    2447       77326 : int MapRef::GetInObjectProperties() const {
    2448       79760 :   IF_BROKER_DISABLED_ACCESS_HANDLE_C(Map, GetInObjectProperties);
    2449      149784 :   return data()->AsMap()->in_object_properties();
    2450             : }
    2451             : 
    2452        9296 : int ScopeInfoRef::ContextLength() const {
    2453        9296 :   IF_BROKER_DISABLED_ACCESS_HANDLE_C(ScopeInfo, ContextLength);
    2454        9296 :   return data()->AsScopeInfo()->context_length();
    2455             : }
    2456             : 
    2457           0 : bool StringRef::IsExternalString() const {
    2458           0 :   IF_BROKER_DISABLED_ACCESS_HANDLE_C(String, IsExternalString);
    2459           0 :   return data()->AsString()->is_external_string();
    2460             : }
    2461             : 
    2462           0 : bool StringRef::IsSeqString() const {
    2463           0 :   IF_BROKER_DISABLED_ACCESS_HANDLE_C(String, IsSeqString);
    2464           0 :   return data()->AsString()->is_seq_string();
    2465             : }
    2466             : 
    2467       31995 : MapRef NativeContextRef::GetFunctionMapFromIndex(int index) const {
    2468             :   DCHECK_GE(index, Context::FIRST_FUNCTION_MAP_INDEX);
    2469             :   DCHECK_LE(index, Context::LAST_FUNCTION_MAP_INDEX);
    2470       31995 :   if (broker()->mode() == JSHeapBroker::kDisabled) {
    2471           0 :     return get(index).AsMap();
    2472             :   }
    2473       31995 :   return MapRef(broker(), data()->AsNativeContext()->function_maps().at(
    2474       95985 :                               index - Context::FIRST_FUNCTION_MAP_INDEX));
    2475             : }
    2476             : 
    2477        2094 : MapRef NativeContextRef::GetInitialJSArrayMap(ElementsKind kind) const {
    2478        2094 :   switch (kind) {
    2479             :     case PACKED_SMI_ELEMENTS:
    2480         904 :       return js_array_packed_smi_elements_map();
    2481             :     case HOLEY_SMI_ELEMENTS:
    2482          40 :       return js_array_holey_smi_elements_map();
    2483             :     case PACKED_DOUBLE_ELEMENTS:
    2484          42 :       return js_array_packed_double_elements_map();
    2485             :     case HOLEY_DOUBLE_ELEMENTS:
    2486         348 :       return js_array_holey_double_elements_map();
    2487             :     case PACKED_ELEMENTS:
    2488         430 :       return js_array_packed_elements_map();
    2489             :     case HOLEY_ELEMENTS:
    2490         330 :       return js_array_holey_elements_map();
    2491             :     default:
    2492           0 :       UNREACHABLE();
    2493             :   }
    2494             : }
    2495             : 
    2496        7882 : base::Optional<JSFunctionRef> NativeContextRef::GetConstructorFunction(
    2497             :     const MapRef& map) const {
    2498        7882 :   CHECK(map.IsPrimitiveMap());
    2499        7882 :   switch (map.constructor_function_index()) {
    2500             :     case Map::kNoConstructorFunctionIndex:
    2501             :       return base::nullopt;
    2502             :     case Context::BIGINT_FUNCTION_INDEX:
    2503           0 :       return bigint_function();
    2504             :     case Context::BOOLEAN_FUNCTION_INDEX:
    2505        1050 :       return boolean_function();
    2506             :     case Context::NUMBER_FUNCTION_INDEX:
    2507        2766 :       return number_function();
    2508             :     case Context::STRING_FUNCTION_INDEX:
    2509       11878 :       return string_function();
    2510             :     case Context::SYMBOL_FUNCTION_INDEX:
    2511          70 :       return symbol_function();
    2512             :     default:
    2513           0 :       UNREACHABLE();
    2514             :   }
    2515             : }
    2516             : 
    2517         167 : bool ObjectRef::IsNullOrUndefined() const {
    2518         167 :   if (IsSmi()) return false;
    2519         167 :   OddballType type = AsHeapObject().map().oddball_type();
    2520         167 :   return type == OddballType::kNull || type == OddballType::kUndefined;
    2521             : }
    2522             : 
    2523      121946 : bool ObjectRef::BooleanValue() const {
    2524      121946 :   if (broker()->mode() == JSHeapBroker::kDisabled) {
    2525             :     AllowHandleDereference allow_handle_dereference;
    2526        9576 :     return object()->BooleanValue(broker()->isolate());
    2527             :   }
    2528      112370 :   return IsSmi() ? (AsSmi() != 0) : data()->AsHeapObject()->boolean_value();
    2529             : }
    2530             : 
    2531        1085 : Maybe<double> ObjectRef::OddballToNumber() const {
    2532        1085 :   OddballType type = AsHeapObject().map().oddball_type();
    2533             : 
    2534        1085 :   switch (type) {
    2535             :     case OddballType::kBoolean: {
    2536             :       ObjectRef true_ref(broker(),
    2537         493 :                          broker()->isolate()->factory()->true_value());
    2538         493 :       return this->equals(true_ref) ? Just(1.0) : Just(0.0);
    2539             :       break;
    2540             :     }
    2541             :     case OddballType::kUndefined: {
    2542             :       return Just(std::numeric_limits<double>::quiet_NaN());
    2543             :       break;
    2544             :     }
    2545             :     case OddballType::kNull: {
    2546             :       return Just(0.0);
    2547             :       break;
    2548             :     }
    2549             :     default: {
    2550             :       return Nothing<double>();
    2551             :       break;
    2552             :     }
    2553             :   }
    2554             : }
    2555             : 
    2556     2448507 : double HeapNumberRef::value() const {
    2557     2448507 :   IF_BROKER_DISABLED_ACCESS_HANDLE_C(HeapNumber, value);
    2558         146 :   return data()->AsHeapNumber()->value();
    2559             : }
    2560             : 
    2561         128 : double MutableHeapNumberRef::value() const {
    2562         128 :   IF_BROKER_DISABLED_ACCESS_HANDLE_C(MutableHeapNumber, value);
    2563         128 :   return data()->AsMutableHeapNumber()->value();
    2564             : }
    2565             : 
    2566         138 : CellRef ModuleRef::GetCell(int cell_index) const {
    2567         138 :   if (broker()->mode() == JSHeapBroker::kDisabled) {
    2568             :     AllowHandleAllocation handle_allocation;
    2569             :     AllowHandleDereference allow_handle_dereference;
    2570             :     return CellRef(broker(),
    2571           0 :                    handle(object()->GetCell(cell_index), broker()->isolate()));
    2572             :   }
    2573         276 :   return CellRef(broker(), data()->AsModule()->GetCell(cell_index));
    2574             : }
    2575             : 
    2576    69730634 : ObjectRef::ObjectRef(JSHeapBroker* broker, Handle<Object> object)
    2577    69730634 :     : broker_(broker) {
    2578    69730634 :   switch (broker->mode()) {
    2579             :     case JSHeapBroker::kSerialized:
    2580    51535983 :       data_ = broker->GetData(object);
    2581    51535983 :       break;
    2582             :     case JSHeapBroker::kSerializing:
    2583     8869464 :       data_ = broker->GetOrCreateData(object);
    2584     8869466 :       break;
    2585             :     case JSHeapBroker::kDisabled: {
    2586             :       RefsMap::Entry* entry =
    2587     9325878 :           broker->refs_->LookupOrInsert(object.address(), broker->zone());
    2588     9325885 :       ObjectData** storage = &(entry->value);
    2589     9325885 :       if (*storage == nullptr) {
    2590             :         AllowHandleDereference handle_dereference;
    2591             :         entry->value = new (broker->zone())
    2592             :             ObjectData(broker, storage, object,
    2593     4183110 :                        object->IsSmi() ? kSmi : kUnserializedHeapObject);
    2594             :       }
    2595     9325885 :       data_ = *storage;
    2596     9325885 :       break;
    2597             :     }
    2598             :     case JSHeapBroker::kRetired:
    2599           0 :       UNREACHABLE();
    2600             :   }
    2601    69731046 :   CHECK_WITH_MSG(data_ != nullptr, "Object is not known to the heap broker");
    2602    69731046 : }
    2603             : 
    2604             : namespace {
    2605     2480704 : OddballType GetOddballType(Isolate* isolate, Map map) {
    2606     2480704 :   if (map->instance_type() != ODDBALL_TYPE) {
    2607             :     return OddballType::kNone;
    2608             :   }
    2609             :   ReadOnlyRoots roots(isolate);
    2610      541145 :   if (map == roots.undefined_map()) {
    2611             :     return OddballType::kUndefined;
    2612             :   }
    2613      503267 :   if (map == roots.null_map()) {
    2614             :     return OddballType::kNull;
    2615             :   }
    2616      503082 :   if (map == roots.boolean_map()) {
    2617             :     return OddballType::kBoolean;
    2618             :   }
    2619      489214 :   if (map == roots.the_hole_map()) {
    2620             :     return OddballType::kHole;
    2621             :   }
    2622      488535 :   if (map == roots.uninitialized_map()) {
    2623             :     return OddballType::kUninitialized;
    2624             :   }
    2625             :   DCHECK(map == roots.termination_exception_map() ||
    2626             :          map == roots.arguments_marker_map() ||
    2627             :          map == roots.optimized_out_map() || map == roots.stale_register_map());
    2628           0 :   return OddballType::kOther;
    2629             : }
    2630             : }  // namespace
    2631             : 
    2632    19167794 : HeapObjectType HeapObjectRef::GetHeapObjectType() const {
    2633    19167794 :   if (broker()->mode() == JSHeapBroker::kDisabled) {
    2634             :     AllowHandleDereference handle_dereference;
    2635             :     Map map = Handle<HeapObject>::cast(object())->map();
    2636             :     HeapObjectType::Flags flags(0);
    2637     2480704 :     if (map->is_undetectable()) flags |= HeapObjectType::kUndetectable;
    2638     2480704 :     if (map->is_callable()) flags |= HeapObjectType::kCallable;
    2639             :     return HeapObjectType(map->instance_type(), flags,
    2640     4961408 :                           GetOddballType(broker()->isolate(), map));
    2641             :   }
    2642             :   HeapObjectType::Flags flags(0);
    2643    16687090 :   if (map().is_undetectable()) flags |= HeapObjectType::kUndetectable;
    2644    16687063 :   if (map().is_callable()) flags |= HeapObjectType::kCallable;
    2645    16687058 :   return HeapObjectType(map().instance_type(), flags, map().oddball_type());
    2646             : }
    2647       11796 : base::Optional<JSObjectRef> AllocationSiteRef::boilerplate() const {
    2648       11796 :   if (broker()->mode() == JSHeapBroker::kDisabled) {
    2649             :     AllowHandleAllocation handle_allocation;
    2650             :     AllowHandleDereference allow_handle_dereference;
    2651             :     return JSObjectRef(broker(),
    2652           0 :                        handle(object()->boilerplate(), broker()->isolate()));
    2653             :   }
    2654       11796 :   JSObjectData* boilerplate = data()->AsAllocationSite()->boilerplate();
    2655       11796 :   if (boilerplate) {
    2656             :     return JSObjectRef(broker(), boilerplate);
    2657             :   } else {
    2658             :     return base::nullopt;
    2659             :   }
    2660             : }
    2661             : 
    2662       10041 : ElementsKind JSObjectRef::GetElementsKind() const {
    2663       10041 :   return map().elements_kind();
    2664             : }
    2665             : 
    2666        7106 : FixedArrayBaseRef JSObjectRef::elements() const {
    2667        7106 :   if (broker()->mode() == JSHeapBroker::kDisabled) {
    2668             :     AllowHandleAllocation handle_allocation;
    2669             :     AllowHandleDereference allow_handle_dereference;
    2670             :     return FixedArrayBaseRef(broker(),
    2671           0 :                              handle(object()->elements(), broker()->isolate()));
    2672             :   }
    2673       14212 :   return FixedArrayBaseRef(broker(), data()->AsJSObject()->elements());
    2674             : }
    2675             : 
    2676       13398 : int FixedArrayBaseRef::length() const {
    2677       13398 :   IF_BROKER_DISABLED_ACCESS_HANDLE_C(FixedArrayBase, length);
    2678       12968 :   return data()->AsFixedArrayBase()->length();
    2679             : }
    2680             : 
    2681        6571 : ObjectData* FixedArrayData::Get(int i) const {
    2682        6571 :   CHECK_LT(i, static_cast<int>(contents_.size()));
    2683       13142 :   CHECK_NOT_NULL(contents_[i]);
    2684        6571 :   return contents_[i];
    2685             : }
    2686             : 
    2687       21387 : Float64 FixedDoubleArrayData::Get(int i) const {
    2688       21387 :   CHECK_LT(i, static_cast<int>(contents_.size()));
    2689       42774 :   return contents_[i];
    2690             : }
    2691             : 
    2692       52495 : void FeedbackVectorRef::SerializeSlots() {
    2693       52495 :   data()->AsFeedbackVector()->SerializeSlots(broker());
    2694       52496 : }
    2695             : 
    2696         582 : ObjectRef JSRegExpRef::data() const {
    2697         582 :   IF_BROKER_DISABLED_ACCESS_HANDLE(JSRegExp, Object, data);
    2698        1164 :   return ObjectRef(broker(), ObjectRef::data()->AsJSRegExp()->data());
    2699             : }
    2700             : 
    2701         582 : ObjectRef JSRegExpRef::flags() const {
    2702         582 :   IF_BROKER_DISABLED_ACCESS_HANDLE(JSRegExp, Object, flags);
    2703        1164 :   return ObjectRef(broker(), ObjectRef::data()->AsJSRegExp()->flags());
    2704             : }
    2705             : 
    2706         582 : ObjectRef JSRegExpRef::last_index() const {
    2707         582 :   IF_BROKER_DISABLED_ACCESS_HANDLE(JSRegExp, Object, last_index);
    2708        1164 :   return ObjectRef(broker(), ObjectRef::data()->AsJSRegExp()->last_index());
    2709             : }
    2710             : 
    2711         582 : ObjectRef JSRegExpRef::raw_properties_or_hash() const {
    2712         582 :   IF_BROKER_DISABLED_ACCESS_HANDLE(JSRegExp, Object, raw_properties_or_hash);
    2713             :   return ObjectRef(broker(),
    2714        1164 :                    ObjectRef::data()->AsJSRegExp()->raw_properties_or_hash());
    2715             : }
    2716             : 
    2717         582 : ObjectRef JSRegExpRef::source() const {
    2718         582 :   IF_BROKER_DISABLED_ACCESS_HANDLE(JSRegExp, Object, source);
    2719        1164 :   return ObjectRef(broker(), ObjectRef::data()->AsJSRegExp()->source());
    2720             : }
    2721             : 
    2722      859051 : Handle<Object> ObjectRef::object() const { return data_->object(); }
    2723             : 
    2724             : #define DEF_OBJECT_GETTER(T)                                                 \
    2725             :   Handle<T> T##Ref::object() const {                                         \
    2726             :     return Handle<T>(reinterpret_cast<Address*>(data_->object().address())); \
    2727             :   }
    2728    38030213 : HEAP_BROKER_OBJECT_LIST(DEF_OBJECT_GETTER)
    2729             : #undef DEF_OBJECT_GETTER
    2730             : 
    2731   435118207 : JSHeapBroker* ObjectRef::broker() const { return broker_; }
    2732             : 
    2733   214152239 : ObjectData* ObjectRef::data() const {
    2734   214152239 :   switch (broker()->mode()) {
    2735             :     case JSHeapBroker::kDisabled:
    2736    20276292 :       CHECK_NE(data_->kind(), kSerializedHeapObject);
    2737             :       return data_;
    2738             :     case JSHeapBroker::kSerializing:
    2739             :     case JSHeapBroker::kSerialized:
    2740   193875947 :       CHECK_NE(data_->kind(), kUnserializedHeapObject);
    2741             :       return data_;
    2742             :     case JSHeapBroker::kRetired:
    2743           0 :       UNREACHABLE();
    2744             :   }
    2745           0 : }
    2746             : 
    2747           0 : Reduction NoChangeBecauseOfMissingData(JSHeapBroker* broker,
    2748             :                                        const char* function, int line) {
    2749           0 :   if (FLAG_trace_heap_broker) {
    2750             :     PrintF("[%p] Skipping optimization in %s at line %d due to missing data\n",
    2751           0 :            broker, function, line);
    2752             :   }
    2753           0 :   return AdvancedReducer::NoChange();
    2754             : }
    2755             : 
    2756      463875 : NativeContextData::NativeContextData(JSHeapBroker* broker, ObjectData** storage,
    2757             :                                      Handle<NativeContext> object)
    2758      927760 :     : ContextData(broker, storage, object), function_maps_(broker->zone()) {}
    2759             : 
    2760      463856 : void NativeContextData::Serialize(JSHeapBroker* broker) {
    2761      463856 :   if (serialized_) return;
    2762      463856 :   serialized_ = true;
    2763             : 
    2764      463856 :   TraceScope tracer(broker, this, "NativeContextData::Serialize");
    2765             :   Handle<NativeContext> context = Handle<NativeContext>::cast(object());
    2766             : 
    2767             : #define SERIALIZE_MEMBER(type, name)                                       \
    2768             :   DCHECK_NULL(name##_);                                                    \
    2769             :   name##_ = broker->GetOrCreateData(context->name())->As##type();          \
    2770             :   if (name##_->IsJSFunction()) name##_->AsJSFunction()->Serialize(broker); \
    2771             :   if (name##_->IsMap()) name##_->AsMap()->SerializeConstructor(broker);
    2772    14380173 :   BROKER_COMPULSORY_NATIVE_CONTEXT_FIELDS(SERIALIZE_MEMBER)
    2773      463878 :   if (!broker->isolate()->bootstrapper()->IsActive()) {
    2774     2779242 :     BROKER_OPTIONAL_NATIVE_CONTEXT_FIELDS(SERIALIZE_MEMBER)
    2775             :   }
    2776             : #undef SERIALIZE_MEMBER
    2777             : 
    2778      463878 :   bound_function_with_constructor_map_->SerializePrototype(broker);
    2779      463878 :   bound_function_without_constructor_map_->SerializePrototype(broker);
    2780             : 
    2781             :   DCHECK(function_maps_.empty());
    2782             :   int const first = Context::FIRST_FUNCTION_MAP_INDEX;
    2783             :   int const last = Context::LAST_FUNCTION_MAP_INDEX;
    2784      463878 :   function_maps_.reserve(last + 1 - first);
    2785    22729749 :   for (int i = first; i <= last; ++i) {
    2786    33398808 :     function_maps_.push_back(broker->GetOrCreateData(context->get(i))->AsMap());
    2787             :   }
    2788             : }
    2789             : 
    2790     1255077 : void JSFunctionRef::Serialize() {
    2791     1255077 :   if (broker()->mode() == JSHeapBroker::kDisabled) return;
    2792     1029279 :   CHECK_EQ(broker()->mode(), JSHeapBroker::kSerializing);
    2793     1029279 :   data()->AsJSFunction()->Serialize(broker());
    2794             : }
    2795             : 
    2796          59 : bool JSFunctionRef::IsSerializedForCompilation() const {
    2797          59 :   return shared().IsSerializedForCompilation(feedback_vector());
    2798             : }
    2799             : 
    2800         147 : void SharedFunctionInfoRef::SetSerializedForCompilation(
    2801             :     FeedbackVectorRef feedback) {
    2802         147 :   CHECK_EQ(broker()->mode(), JSHeapBroker::kSerializing);
    2803         147 :   data()->AsSharedFunctionInfo()->SetSerializedForCompilation(broker(),
    2804         147 :                                                               feedback);
    2805         147 : }
    2806             : 
    2807         324 : bool SharedFunctionInfoRef::IsSerializedForCompilation(
    2808             :     FeedbackVectorRef feedback) const {
    2809         324 :   CHECK_NE(broker()->mode(), JSHeapBroker::kDisabled);
    2810         648 :   return data()->AsSharedFunctionInfo()->IsSerializedForCompilation(feedback);
    2811             : }
    2812             : 
    2813     1138292 : void JSObjectRef::SerializeObjectCreateMap() {
    2814     1138292 :   if (broker()->mode() == JSHeapBroker::kDisabled) return;
    2815     1138299 :   CHECK_EQ(broker()->mode(), JSHeapBroker::kSerializing);
    2816     1138299 :   data()->AsJSObject()->SerializeObjectCreateMap(broker());
    2817             : }
    2818             : 
    2819       73345 : void MapRef::SerializeOwnDescriptors() {
    2820       73345 :   if (broker()->mode() == JSHeapBroker::kDisabled) return;
    2821          16 :   CHECK_EQ(broker()->mode(), JSHeapBroker::kSerializing);
    2822          16 :   data()->AsMap()->SerializeOwnDescriptors(broker());
    2823             : }
    2824             : 
    2825       90179 : void MapRef::SerializePrototype() {
    2826       90179 :   if (broker()->mode() == JSHeapBroker::kDisabled) return;
    2827           0 :   CHECK_EQ(broker()->mode(), JSHeapBroker::kSerializing);
    2828           0 :   data()->AsMap()->SerializePrototype(broker());
    2829             : }
    2830             : 
    2831         170 : void ModuleRef::Serialize() {
    2832         170 :   if (broker()->mode() == JSHeapBroker::kDisabled) return;
    2833         170 :   CHECK_EQ(broker()->mode(), JSHeapBroker::kSerializing);
    2834         170 :   data()->AsModule()->Serialize(broker());
    2835             : }
    2836             : 
    2837     1352688 : void ContextRef::SerializeContextChain() {
    2838     1352688 :   if (broker()->mode() == JSHeapBroker::kDisabled) return;
    2839     1081546 :   CHECK_EQ(broker()->mode(), JSHeapBroker::kSerializing);
    2840     1081546 :   data()->AsContext()->SerializeContextChain(broker());
    2841             : }
    2842             : 
    2843       26500 : void ContextRef::SerializeSlot(int index) {
    2844       26500 :   if (broker()->mode() == JSHeapBroker::kDisabled) return;
    2845          16 :   CHECK_EQ(broker()->mode(), JSHeapBroker::kSerializing);
    2846          16 :   data()->AsContext()->SerializeSlot(broker(), index);
    2847             : }
    2848             : 
    2849      463855 : void NativeContextRef::Serialize() {
    2850      463855 :   if (broker()->mode() == JSHeapBroker::kDisabled) return;
    2851      463863 :   CHECK_EQ(broker()->mode(), JSHeapBroker::kSerializing);
    2852      463863 :   data()->AsNativeContext()->Serialize(broker());
    2853             : }
    2854             : 
    2855        1327 : void JSTypedArrayRef::Serialize() {
    2856        1327 :   if (broker()->mode() == JSHeapBroker::kDisabled) return;
    2857           0 :   CHECK_EQ(broker()->mode(), JSHeapBroker::kSerializing);
    2858           0 :   data()->AsJSTypedArray()->Serialize(broker());
    2859             : }
    2860             : 
    2861           0 : bool JSTypedArrayRef::serialized() const {
    2862           0 :   CHECK_NE(broker()->mode(), JSHeapBroker::kDisabled);
    2863           0 :   return data()->AsJSTypedArray()->serialized();
    2864             : }
    2865             : 
    2866         222 : void JSBoundFunctionRef::Serialize() {
    2867         222 :   if (broker()->mode() == JSHeapBroker::kDisabled) return;
    2868           0 :   CHECK_EQ(broker()->mode(), JSHeapBroker::kSerializing);
    2869           0 :   data()->AsJSBoundFunction()->Serialize(broker());
    2870             : }
    2871             : 
    2872      192987 : void PropertyCellRef::Serialize() {
    2873      192987 :   if (broker()->mode() == JSHeapBroker::kDisabled) return;
    2874           0 :   CHECK_EQ(broker()->mode(), JSHeapBroker::kSerializing);
    2875           0 :   data()->AsPropertyCell()->Serialize(broker());
    2876             : }
    2877             : 
    2878       52316 : bool CanInlineElementAccess(MapRef const& map) {
    2879       52316 :   if (!map.IsJSObjectMap()) return false;
    2880       50677 :   if (map.is_access_check_needed()) return false;
    2881       50677 :   if (map.has_indexed_interceptor()) return false;
    2882       50669 :   ElementsKind const elements_kind = map.elements_kind();
    2883       50669 :   if (IsFastElementsKind(elements_kind)) return true;
    2884       15629 :   if (IsFixedTypedArrayElementsKind(elements_kind) &&
    2885       15629 :       elements_kind != BIGUINT64_ELEMENTS &&
    2886             :       elements_kind != BIGINT64_ELEMENTS) {
    2887             :     return true;
    2888             :   }
    2889        1633 :   return false;
    2890             : }
    2891             : 
    2892           0 : GlobalAccessFeedback::GlobalAccessFeedback(PropertyCellRef cell)
    2893             :     : ProcessedFeedback(kGlobalAccess),
    2894             :       cell_or_context_(cell),
    2895      192736 :       index_and_immutable_(0 /* doesn't matter */) {}
    2896             : 
    2897           0 : GlobalAccessFeedback::GlobalAccessFeedback(ContextRef script_context,
    2898             :                                            int slot_index, bool immutable)
    2899             :     : ProcessedFeedback(kGlobalAccess),
    2900             :       cell_or_context_(script_context),
    2901         114 :       index_and_immutable_(FeedbackNexus::SlotIndexBits::encode(slot_index) |
    2902         228 :                            FeedbackNexus::ImmutabilityBit::encode(immutable)) {
    2903             :   DCHECK_EQ(this->slot_index(), slot_index);
    2904             :   DCHECK_EQ(this->immutable(), immutable);
    2905           0 : }
    2906             : 
    2907      385586 : bool GlobalAccessFeedback::IsPropertyCell() const {
    2908      771400 :   return cell_or_context_.IsPropertyCell();
    2909             : }
    2910      192736 : PropertyCellRef GlobalAccessFeedback::property_cell() const {
    2911             :   DCHECK(IsPropertyCell());
    2912      192736 :   return cell_or_context_.AsPropertyCell();
    2913             : }
    2914             : 
    2915         114 : ContextRef GlobalAccessFeedback::script_context() const {
    2916             :   DCHECK(IsScriptContextSlot());
    2917         114 :   return cell_or_context_.AsContext();
    2918             : }
    2919         114 : int GlobalAccessFeedback::slot_index() const {
    2920         114 :   CHECK(IsScriptContextSlot());
    2921         228 :   return FeedbackNexus::SlotIndexBits::decode(index_and_immutable_);
    2922             : }
    2923         114 : bool GlobalAccessFeedback::immutable() const {
    2924         114 :   CHECK(IsScriptContextSlot());
    2925         228 :   return FeedbackNexus::ImmutabilityBit::decode(index_and_immutable_);
    2926             : }
    2927             : 
    2928           0 : base::Optional<ObjectRef> GlobalAccessFeedback::GetConstantValue() const {
    2929           0 :   if (IsScriptContextSlot() && immutable()) {
    2930             :     // Return the value of this global variable if it's guaranteed to be
    2931             :     // constant.
    2932           0 :     return script_context().get(slot_index());
    2933             :   }
    2934           0 :   return {};
    2935             : }
    2936             : 
    2937           0 : ElementAccessFeedback::ElementAccessFeedback(Zone* zone)
    2938             :     : ProcessedFeedback(kElementAccess),
    2939             :       receiver_maps(zone),
    2940           0 :       transitions(zone) {}
    2941             : 
    2942       14552 : ElementAccessFeedback::MapIterator::MapIterator(
    2943             :     ElementAccessFeedback const& processed, JSHeapBroker* broker)
    2944       14552 :     : processed_(processed), broker_(broker) {
    2945       29104 :   CHECK_LT(processed.receiver_maps.size(),
    2946             :            std::numeric_limits<size_t>::max() - processed.transitions.size());
    2947       14552 : }
    2948             : 
    2949       29403 : bool ElementAccessFeedback::MapIterator::done() const {
    2950       60055 :   return index_ >=
    2951      120110 :          processed_.receiver_maps.size() + processed_.transitions.size();
    2952             : }
    2953             : 
    2954       14851 : void ElementAccessFeedback::MapIterator::advance() { index_++; }
    2955             : 
    2956       30652 : MapRef ElementAccessFeedback::MapIterator::current() const {
    2957       30652 :   CHECK(!done());
    2958             :   size_t receiver_maps_size = processed_.receiver_maps.size();
    2959             :   Handle<Map> map;
    2960       30652 :   if (index_ < receiver_maps_size) {
    2961       29533 :     map = processed_.receiver_maps[index_];
    2962             :   } else {
    2963        2238 :     map = processed_.transitions[index_ - receiver_maps_size].first;
    2964             :   }
    2965       61304 :   return MapRef(broker_, map);
    2966             : }
    2967             : 
    2968       14552 : ElementAccessFeedback::MapIterator ElementAccessFeedback::all_maps(
    2969             :     JSHeapBroker* broker) const {
    2970       14552 :   return MapIterator(*this, broker);
    2971             : }
    2972             : 
    2973          24 : FeedbackSource::FeedbackSource(FeedbackNexus const& nexus)
    2974          24 :     : vector(nexus.vector_handle()), slot(nexus.slot()) {}
    2975             : 
    2976     1219417 : FeedbackSource::FeedbackSource(VectorSlotPair const& pair)
    2977     1219417 :     : vector(pair.vector()), slot(pair.slot()) {}
    2978             : 
    2979          63 : void JSHeapBroker::SetFeedback(FeedbackSource const& source,
    2980             :                                ProcessedFeedback const* feedback) {
    2981          63 :   auto insertion = feedback_.insert({source, feedback});
    2982          63 :   CHECK(insertion.second);
    2983          63 : }
    2984             : 
    2985          67 : bool JSHeapBroker::HasFeedback(FeedbackSource const& source) const {
    2986          67 :   return feedback_.find(source) != feedback_.end();
    2987             : }
    2988             : 
    2989          59 : ProcessedFeedback const* JSHeapBroker::GetFeedback(
    2990             :     FeedbackSource const& source) const {
    2991             :   auto it = feedback_.find(source);
    2992          59 :   CHECK_NE(it, feedback_.end());
    2993          59 :   return it->second;
    2994             : }
    2995             : 
    2996           8 : ElementAccessFeedback const* JSHeapBroker::GetElementAccessFeedback(
    2997             :     FeedbackSource const& source) const {
    2998           8 :   ProcessedFeedback const* feedback = GetFeedback(source);
    2999           8 :   if (feedback == nullptr) return nullptr;
    3000           0 :   CHECK_EQ(feedback->kind(), ProcessedFeedback::kElementAccess);
    3001             :   return static_cast<ElementAccessFeedback const*>(feedback);
    3002             : }
    3003             : 
    3004          51 : GlobalAccessFeedback const* JSHeapBroker::GetGlobalAccessFeedback(
    3005             :     FeedbackSource const& source) const {
    3006          51 :   ProcessedFeedback const* feedback = GetFeedback(source);
    3007          51 :   if (feedback == nullptr) return nullptr;
    3008           0 :   CHECK_EQ(feedback->kind(), ProcessedFeedback::kGlobalAccess);
    3009             :   return static_cast<GlobalAccessFeedback const*>(feedback);
    3010             : }
    3011             : 
    3012       23155 : ElementAccessFeedback const* JSHeapBroker::ProcessFeedbackMapsForElementAccess(
    3013             :     MapHandles const& maps) {
    3014             :   // Collect possible transition targets.
    3015             :   MapHandles possible_transition_targets;
    3016       23155 :   possible_transition_targets.reserve(maps.size());
    3017       49038 :   for (Handle<Map> map : maps) {
    3018       76356 :     if (CanInlineElementAccess(MapRef(this, map)) &&
    3019       43569 :         IsFastElementsKind(map->elements_kind()) &&
    3020             :         GetInitialFastElementsKind() != map->elements_kind()) {
    3021       13172 :       possible_transition_targets.push_back(map);
    3022             :     }
    3023             :   }
    3024             : 
    3025       23155 :   if (maps.empty()) return nullptr;
    3026             : 
    3027             :   ElementAccessFeedback* result = new (zone()) ElementAccessFeedback(zone());
    3028             : 
    3029             :   // Separate the actual receiver maps and the possible transition sources.
    3030       49022 :   for (Handle<Map> map : maps) {
    3031             :     // Don't generate elements kind transitions from stable maps.
    3032             :     Map transition_target = map->is_stable()
    3033             :                                 ? Map()
    3034             :                                 : map->FindElementsKindTransitionedMap(
    3035       41207 :                                       isolate(), possible_transition_targets);
    3036       25883 :     if (transition_target.is_null()) {
    3037       24238 :       result->receiver_maps.push_back(map);
    3038             :     } else {
    3039        1645 :       result->transitions.emplace_back(map,
    3040        3290 :                                        handle(transition_target, isolate()));
    3041             :     }
    3042             :   }
    3043             : 
    3044             : #ifdef ENABLE_SLOW_DCHECKS
    3045             :   // No transition sources appear in {receiver_maps}.
    3046             :   // All transition targets appear in {receiver_maps}.
    3047             :   for (auto& transition : result->transitions) {
    3048             :     CHECK(std::none_of(
    3049             :         result->receiver_maps.cbegin(), result->receiver_maps.cend(),
    3050             :         [&](Handle<Map> map) { return map.equals(transition.first); }));
    3051             :     CHECK(std::any_of(
    3052             :         result->receiver_maps.cbegin(), result->receiver_maps.cend(),
    3053             :         [&](Handle<Map> map) { return map.equals(transition.second); }));
    3054             :   }
    3055             : #endif
    3056       23139 :   CHECK(!result->receiver_maps.empty());
    3057             : 
    3058             :   return result;
    3059             : }
    3060             : 
    3061     1219413 : GlobalAccessFeedback const* JSHeapBroker::ProcessFeedbackForGlobalAccess(
    3062             :     FeedbackSource const& source) {
    3063             :   FeedbackNexus nexus(source.vector, source.slot);
    3064             :   DCHECK(nexus.kind() == FeedbackSlotKind::kLoadGlobalInsideTypeof ||
    3065             :          nexus.kind() == FeedbackSlotKind::kLoadGlobalNotInsideTypeof ||
    3066             :          nexus.kind() == FeedbackSlotKind::kStoreGlobalSloppy ||
    3067             :          nexus.kind() == FeedbackSlotKind::kStoreGlobalStrict);
    3068     1412386 :   if (nexus.ic_state() != MONOMORPHIC || nexus.GetFeedback()->IsCleared()) {
    3069             :     return nullptr;
    3070             :   }
    3071             : 
    3072      385700 :   Handle<Object> feedback_value(nexus.GetFeedback()->GetHeapObjectOrSmi(),
    3073             :                                 isolate());
    3074             : 
    3075      192850 :   if (feedback_value->IsSmi()) {
    3076             :     // The wanted name belongs to a script-scope variable and the feedback tells
    3077             :     // us where to find its value.
    3078         114 :     int number = feedback_value->Number();
    3079             :     int const script_context_index =
    3080         228 :         FeedbackNexus::ContextIndexBits::decode(number);
    3081         114 :     int const context_slot_index = FeedbackNexus::SlotIndexBits::decode(number);
    3082             :     bool const immutable = FeedbackNexus::ImmutabilityBit::decode(number);
    3083             :     Handle<Context> context = ScriptContextTable::GetContext(
    3084         228 :         isolate(), native_context().script_context_table().object(),
    3085         114 :         script_context_index);
    3086             :     {
    3087             :       ObjectRef contents(this,
    3088         114 :                          handle(context->get(context_slot_index), isolate()));
    3089         228 :       CHECK(!contents.equals(
    3090             :           ObjectRef(this, isolate()->factory()->the_hole_value())));
    3091             :     }
    3092             :     ContextRef context_ref(this, context);
    3093         114 :     if (immutable) {
    3094          37 :       context_ref.SerializeSlot(context_slot_index);
    3095             :     }
    3096             :     return new (zone())
    3097         114 :         GlobalAccessFeedback(context_ref, context_slot_index, immutable);
    3098             :   }
    3099             : 
    3100      192736 :   CHECK(feedback_value->IsPropertyCell());
    3101             :   // The wanted name belongs (or did belong) to a property on the global
    3102             :   // object and the feedback is the cell holding its value.
    3103             :   PropertyCellRef cell(this, Handle<PropertyCell>::cast(feedback_value));
    3104      192736 :   cell.Serialize();
    3105      192736 :   return new (zone()) GlobalAccessFeedback(cell);
    3106             : }
    3107             : 
    3108             : #undef BIMODAL_ACCESSOR
    3109             : #undef BIMODAL_ACCESSOR_B
    3110             : #undef BIMODAL_ACCESSOR_C
    3111             : #undef IF_BROKER_DISABLED_ACCESS_HANDLE
    3112             : #undef IF_BROKER_DISABLED_ACCESS_HANDLE_C
    3113             : #undef TRACE
    3114             : 
    3115             : }  // namespace compiler
    3116             : }  // namespace internal
    3117      120216 : }  // namespace v8

Generated by: LCOV version 1.10