V8 API Reference, 7.2.502.16 (for Deno 0.2.4)
js-heap-broker.cc
1 // Copyright 2018 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "src/compiler/js-heap-broker.h"
6 
7 #include "src/ast/modules.h"
8 #include "src/bootstrapper.h"
9 #include "src/boxed-float.h"
10 #include "src/code-factory.h"
11 #include "src/compiler/graph-reducer.h"
12 #include "src/compiler/per-isolate-compiler-cache.h"
13 #include "src/objects-inl.h"
14 #include "src/objects/instance-type-inl.h"
15 #include "src/objects/js-array-buffer-inl.h"
16 #include "src/objects/js-array-inl.h"
17 #include "src/objects/js-regexp-inl.h"
18 #include "src/objects/module-inl.h"
19 #include "src/utils.h"
20 
21 namespace v8 {
22 namespace internal {
23 namespace compiler {
24 
25 #define FORWARD_DECL(Name) class Name##Data;
26 HEAP_BROKER_OBJECT_LIST(FORWARD_DECL)
27 #undef FORWARD_DECL
28 
29 // There are three kinds of ObjectData values.
30 //
31 // kSmi: The underlying V8 object is a Smi and the data is an instance of the
32 // base class (ObjectData), i.e. it's basically just the handle. Because the
33 // object is a Smi, it's safe to access the handle in order to extract the
34 // number value, and AsSmi() does exactly that.
35 //
36 // kSerializedHeapObject: The underlying V8 object is a HeapObject and the
37 // data is an instance of the corresponding (most-specific) subclass, e.g.
38 // JSFunctionData, which provides serialized information about the object.
39 //
40 // kUnserializedHeapObject: The underlying V8 object is a HeapObject and the
41 // data is an instance of the base class (ObjectData), i.e. it basically
42 // carries no information other than the handle.
43 //
44 enum ObjectDataKind { kSmi, kSerializedHeapObject, kUnserializedHeapObject };
45 
46 class ObjectData : public ZoneObject {
47  public:
48  ObjectData(JSHeapBroker* broker, ObjectData** storage, Handle<Object> object,
49  ObjectDataKind kind)
50  : object_(object), kind_(kind) {
51  // This assignment ensures we don't end up inserting the same object
52  // in an endless recursion.
53  *storage = this;
54 
55  broker->Trace("Creating data %p for handle %" V8PRIuPTR " (", this,
56  object.address());
57  if (FLAG_trace_heap_broker) {
58  object->ShortPrint();
59  PrintF(")\n");
60  }
61  CHECK_NOT_NULL(broker->isolate()->handle_scope_data()->canonical_scope);
62  }
63 
64 #define DECLARE_IS_AND_AS(Name) \
65  bool Is##Name() const; \
66  Name##Data* As##Name();
67  HEAP_BROKER_OBJECT_LIST(DECLARE_IS_AND_AS)
68 #undef DECLARE_IS_AND_AS
69 
70  Handle<Object> object() const { return object_; }
71  ObjectDataKind kind() const { return kind_; }
72  bool is_smi() const { return kind_ == kSmi; }
73 
74  private:
75  Handle<Object> const object_;
76  ObjectDataKind const kind_;
77 };
78 
79 class HeapObjectData : public ObjectData {
80  public:
81  HeapObjectData(JSHeapBroker* broker, ObjectData** storage,
82  Handle<HeapObject> object);
83 
84  bool boolean_value() const { return boolean_value_; }
85  MapData* map() const { return map_; }
86 
87  static HeapObjectData* Serialize(JSHeapBroker* broker,
88  Handle<HeapObject> object);
89 
90  private:
91  bool const boolean_value_;
92  MapData* const map_;
93 };
94 
96  public:
97  PropertyCellData(JSHeapBroker* broker, ObjectData** storage,
98  Handle<PropertyCell> object);
99 
100  PropertyDetails property_details() const { return property_details_; }
101 
102  void Serialize(JSHeapBroker* broker);
103  ObjectData* value() { return value_; }
104 
105  private:
106  PropertyDetails const property_details_;
107 
108  bool serialized_ = false;
109  ObjectData* value_ = nullptr;
110 };
111 
112 void JSHeapBroker::IncrementTracingIndentation() { ++tracing_indentation_; }
113 
114 void JSHeapBroker::DecrementTracingIndentation() { --tracing_indentation_; }
115 
116 class TraceScope {
117  public:
118  TraceScope(JSHeapBroker* broker, const char* label)
119  : TraceScope(broker, static_cast<void*>(broker), label) {}
120 
121  TraceScope(JSHeapBroker* broker, ObjectData* data, const char* label)
122  : TraceScope(broker, static_cast<void*>(data), label) {}
123 
124  ~TraceScope() { broker_->DecrementTracingIndentation(); }
125 
126  private:
127  JSHeapBroker* const broker_;
128 
129  TraceScope(JSHeapBroker* broker, void* self, const char* label)
130  : broker_(broker) {
131  broker_->Trace("Running %s on %p.\n", label, self);
132  broker_->IncrementTracingIndentation();
133  }
134 };
135 
136 PropertyCellData::PropertyCellData(JSHeapBroker* broker, ObjectData** storage,
137  Handle<PropertyCell> object)
138  : HeapObjectData(broker, storage, object),
139  property_details_(object->property_details()) {}
140 
141 void PropertyCellData::Serialize(JSHeapBroker* broker) {
142  if (serialized_) return;
143  serialized_ = true;
144 
145  TraceScope tracer(broker, this, "PropertyCellData::Serialize");
146  auto cell = Handle<PropertyCell>::cast(object());
147  DCHECK_NULL(value_);
148  value_ = broker->GetOrCreateData(cell->value());
149 }
150 
152  public:
153  bool IsDouble() const { return object_ == nullptr; }
154  double AsDouble() const {
155  CHECK(IsDouble());
156  return number_;
157  }
158 
159  bool IsObject() const { return object_ != nullptr; }
160  ObjectData* AsObject() const {
161  CHECK(IsObject());
162  return object_;
163  }
164 
165  explicit JSObjectField(double value) : number_(value) {}
166  explicit JSObjectField(ObjectData* value) : object_(value) {}
167 
168  private:
169  ObjectData* object_ = nullptr;
170  double number_ = 0;
171 };
172 
173 class JSObjectData : public HeapObjectData {
174  public:
175  JSObjectData(JSHeapBroker* broker, ObjectData** storage,
176  Handle<JSObject> object);
177 
178  // Recursively serializes all reachable JSObjects.
179  void SerializeAsBoilerplate(JSHeapBroker* broker);
180  // Shallow serialization of {elements}.
181  void SerializeElements(JSHeapBroker* broker);
182 
183  const JSObjectField& GetInobjectField(int property_index) const;
184  FixedArrayBaseData* elements() const;
185 
186  // This method is only used to assert our invariants.
187  bool cow_or_empty_elements_tenured() const;
188 
189  void SerializeObjectCreateMap(JSHeapBroker* broker);
190  MapData* object_create_map() const { // Can be nullptr.
191  CHECK(serialized_object_create_map_);
192  return object_create_map_;
193  }
194 
195  private:
196  void SerializeRecursive(JSHeapBroker* broker, int max_depths);
197 
198  FixedArrayBaseData* elements_ = nullptr;
199  bool cow_or_empty_elements_tenured_ = false;
200  // The {serialized_as_boilerplate} flag is set when all recursively
201  // reachable JSObjects are serialized.
202  bool serialized_as_boilerplate_ = false;
203  bool serialized_elements_ = false;
204 
205  ZoneVector<JSObjectField> inobject_fields_;
206 
207  bool serialized_object_create_map_ = false;
208  MapData* object_create_map_ = nullptr;
209 };
210 
211 void JSObjectData::SerializeObjectCreateMap(JSHeapBroker* broker) {
212  if (serialized_object_create_map_) return;
213  serialized_object_create_map_ = true;
214 
215  TraceScope tracer(broker, this, "JSObjectData::SerializeObjectCreateMap");
216  Handle<JSObject> jsobject = Handle<JSObject>::cast(object());
217 
218  if (jsobject->map()->is_prototype_map()) {
219  Handle<Object> maybe_proto_info(jsobject->map()->prototype_info(),
220  broker->isolate());
221  if (maybe_proto_info->IsPrototypeInfo()) {
222  auto proto_info = Handle<PrototypeInfo>::cast(maybe_proto_info);
223  if (proto_info->HasObjectCreateMap()) {
224  DCHECK_NULL(object_create_map_);
225  object_create_map_ =
226  broker->GetOrCreateData(proto_info->ObjectCreateMap())->AsMap();
227  }
228  }
229  }
230 }
231 
233  public:
234  JSTypedArrayData(JSHeapBroker* broker, ObjectData** storage,
235  Handle<JSTypedArray> object);
236 
237  bool is_on_heap() const { return is_on_heap_; }
238  size_t length_value() const { return length_value_; }
239  void* elements_external_pointer() const { return elements_external_pointer_; }
240 
241  void Serialize(JSHeapBroker* broker);
242 
243  HeapObjectData* buffer() const { return buffer_; }
244 
245  private:
246  bool const is_on_heap_;
247  size_t const length_value_;
248  void* const elements_external_pointer_;
249 
250  bool serialized_ = false;
251  HeapObjectData* buffer_ = nullptr;
252 };
253 
254 JSTypedArrayData::JSTypedArrayData(JSHeapBroker* broker, ObjectData** storage,
255  Handle<JSTypedArray> object)
256  : JSObjectData(broker, storage, object),
257  is_on_heap_(object->is_on_heap()),
258  length_value_(object->length_value()),
259  elements_external_pointer_(
260  FixedTypedArrayBase::cast(object->elements())->external_pointer()) {}
261 
262 void JSTypedArrayData::Serialize(JSHeapBroker* broker) {
263  if (serialized_) return;
264  serialized_ = true;
265 
266  TraceScope tracer(broker, this, "JSTypedArrayData::Serialize");
267  Handle<JSTypedArray> typed_array = Handle<JSTypedArray>::cast(object());
268 
269  if (!is_on_heap()) {
270  DCHECK_NULL(buffer_);
271  buffer_ = broker->GetOrCreateData(typed_array->buffer())->AsHeapObject();
272  }
273 }
274 
275 class JSDataViewData : public JSObjectData {
276  public:
277  JSDataViewData(JSHeapBroker* broker, ObjectData** storage,
278  Handle<JSDataView> object);
279 
280  size_t byte_length() const { return byte_length_; }
281  size_t byte_offset() const { return byte_offset_; }
282 
283  private:
284  size_t const byte_length_;
285  size_t const byte_offset_;
286 };
287 
289  public:
290  JSBoundFunctionData(JSHeapBroker* broker, ObjectData** storage,
291  Handle<JSBoundFunction> object);
292 
293  void Serialize(JSHeapBroker* broker);
294 
295  ObjectData* bound_target_function() const { return bound_target_function_; }
296  ObjectData* bound_this() const { return bound_this_; }
297  FixedArrayData* bound_arguments() const { return bound_arguments_; }
298 
299  private:
300  bool serialized_ = false;
301 
302  ObjectData* bound_target_function_ = nullptr;
303  ObjectData* bound_this_ = nullptr;
304  FixedArrayData* bound_arguments_ = nullptr;
305 };
306 
307 class JSFunctionData : public JSObjectData {
308  public:
309  JSFunctionData(JSHeapBroker* broker, ObjectData** storage,
310  Handle<JSFunction> object);
311 
312  bool has_initial_map() const { return has_initial_map_; }
313  bool has_prototype() const { return has_prototype_; }
314  bool PrototypeRequiresRuntimeLookup() const {
315  return PrototypeRequiresRuntimeLookup_;
316  }
317 
318  void Serialize(JSHeapBroker* broker);
319 
320  ContextData* context() const { return context_; }
321  NativeContextData* native_context() const { return native_context_; }
322  MapData* initial_map() const { return initial_map_; }
323  ObjectData* prototype() const { return prototype_; }
324  SharedFunctionInfoData* shared() const { return shared_; }
325  int initial_map_instance_size_with_min_slack() const {
326  CHECK(serialized_);
327  return initial_map_instance_size_with_min_slack_;
328  }
329 
330  private:
331  bool has_initial_map_;
332  bool has_prototype_;
333  bool PrototypeRequiresRuntimeLookup_;
334 
335  bool serialized_ = false;
336 
337  ContextData* context_ = nullptr;
338  NativeContextData* native_context_ = nullptr;
339  MapData* initial_map_ = nullptr;
340  ObjectData* prototype_ = nullptr;
341  SharedFunctionInfoData* shared_ = nullptr;
342  int initial_map_instance_size_with_min_slack_;
343 };
344 
345 class JSRegExpData : public JSObjectData {
346  public:
347  JSRegExpData(JSHeapBroker* broker, ObjectData** storage,
348  Handle<JSRegExp> object)
349  : JSObjectData(broker, storage, object) {}
350 
351  void SerializeAsRegExpBoilerplate(JSHeapBroker* broker);
352 
353  ObjectData* raw_properties_or_hash() const { return raw_properties_or_hash_; }
354  ObjectData* data() const { return data_; }
355  ObjectData* source() const { return source_; }
356  ObjectData* flags() const { return flags_; }
357  ObjectData* last_index() const { return last_index_; }
358 
359  private:
360  bool serialized_as_reg_exp_boilerplate_ = false;
361 
362  ObjectData* raw_properties_or_hash_ = nullptr;
363  ObjectData* data_ = nullptr;
364  ObjectData* source_ = nullptr;
365  ObjectData* flags_ = nullptr;
366  ObjectData* last_index_ = nullptr;
367 };
368 
370  public:
371  HeapNumberData(JSHeapBroker* broker, ObjectData** storage,
372  Handle<HeapNumber> object)
373  : HeapObjectData(broker, storage, object), value_(object->value()) {}
374 
375  double value() const { return value_; }
376 
377  private:
378  double const value_;
379 };
380 
382  public:
383  MutableHeapNumberData(JSHeapBroker* broker, ObjectData** storage,
385  : 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 ContextData : public HeapObjectData {
394  public:
395  ContextData(JSHeapBroker* broker, ObjectData** storage,
396  Handle<Context> object);
397  void Serialize(JSHeapBroker* broker);
398 
399  ContextData* previous() const {
400  CHECK(serialized_);
401  return previous_;
402  }
403 
404  private:
405  bool serialized_ = false;
406  ContextData* previous_ = nullptr;
407 };
408 
409 ContextData::ContextData(JSHeapBroker* broker, ObjectData** storage,
410  Handle<Context> object)
411  : HeapObjectData(broker, storage, object) {}
412 
413 void ContextData::Serialize(JSHeapBroker* broker) {
414  if (serialized_) return;
415  serialized_ = true;
416 
417  TraceScope tracer(broker, this, "ContextData::Serialize");
418  Handle<Context> context = Handle<Context>::cast(object());
419 
420  DCHECK_NULL(previous_);
421  // Context::previous DCHECK-fails when called on the native context.
422  if (!context->IsNativeContext()) {
423  previous_ = broker->GetOrCreateData(context->previous())->AsContext();
424  previous_->Serialize(broker);
425  }
426 }
427 
429  public:
430 #define DECL_ACCESSOR(type, name) \
431  type##Data* name() const { return name##_; }
432  BROKER_NATIVE_CONTEXT_FIELDS(DECL_ACCESSOR)
433 #undef DECL_ACCESSOR
434 
435  const ZoneVector<MapData*>& function_maps() const {
436  CHECK(serialized_);
437  return function_maps_;
438  }
439 
440  NativeContextData(JSHeapBroker* broker, ObjectData** storage,
441  Handle<NativeContext> object);
442  void Serialize(JSHeapBroker* broker);
443 
444  private:
445  bool serialized_ = false;
446 #define DECL_MEMBER(type, name) type##Data* name##_ = nullptr;
447  BROKER_NATIVE_CONTEXT_FIELDS(DECL_MEMBER)
448 #undef DECL_MEMBER
449  ZoneVector<MapData*> function_maps_;
450 };
451 
452 class NameData : public HeapObjectData {
453  public:
454  NameData(JSHeapBroker* broker, ObjectData** storage, Handle<Name> object)
455  : HeapObjectData(broker, storage, object) {}
456 };
457 
458 class StringData : public NameData {
459  public:
460  StringData(JSHeapBroker* broker, ObjectData** storage, Handle<String> object);
461 
462  int length() const { return length_; }
463  uint16_t first_char() const { return first_char_; }
464  base::Optional<double> to_number() const { return to_number_; }
465  bool is_external_string() const { return is_external_string_; }
466  bool is_seq_string() const { return is_seq_string_; }
467 
468  private:
469  int const length_;
470  uint16_t const first_char_;
471  base::Optional<double> to_number_;
472  bool const is_external_string_;
473  bool const is_seq_string_;
474 
475  static constexpr int kMaxLengthForDoubleConversion = 23;
476 };
477 
478 StringData::StringData(JSHeapBroker* broker, ObjectData** storage,
479  Handle<String> object)
480  : NameData(broker, storage, object),
481  length_(object->length()),
482  first_char_(length_ > 0 ? object->Get(0) : 0),
483  is_external_string_(object->IsExternalString()),
484  is_seq_string_(object->IsSeqString()) {
485  int flags = ALLOW_HEX | ALLOW_OCTAL | ALLOW_BINARY;
486  if (length_ <= kMaxLengthForDoubleConversion) {
487  to_number_ = StringToDouble(broker->isolate(), object, flags);
488  }
489 }
490 
492  public:
495  : StringData(broker, storage, object) {}
496 };
497 
498 namespace {
499 
500 bool IsFastLiteralHelper(Handle<JSObject> boilerplate, int max_depth,
501  int* max_properties) {
502  DCHECK_GE(max_depth, 0);
503  DCHECK_GE(*max_properties, 0);
504 
505  // Make sure the boilerplate map is not deprecated.
506  if (!JSObject::TryMigrateInstance(boilerplate)) return false;
507 
508  // Check for too deep nesting.
509  if (max_depth == 0) return false;
510 
511  // Check the elements.
512  Isolate* const isolate = boilerplate->GetIsolate();
513  Handle<FixedArrayBase> elements(boilerplate->elements(), isolate);
514  if (elements->length() > 0 &&
515  elements->map() != ReadOnlyRoots(isolate).fixed_cow_array_map()) {
516  if (boilerplate->HasSmiOrObjectElements()) {
517  Handle<FixedArray> fast_elements = Handle<FixedArray>::cast(elements);
518  int length = elements->length();
519  for (int i = 0; i < length; i++) {
520  if ((*max_properties)-- == 0) return false;
521  Handle<Object> value(fast_elements->get(i), isolate);
522  if (value->IsJSObject()) {
523  Handle<JSObject> value_object = Handle<JSObject>::cast(value);
524  if (!IsFastLiteralHelper(value_object, max_depth - 1,
525  max_properties)) {
526  return false;
527  }
528  }
529  }
530  } else if (boilerplate->HasDoubleElements()) {
531  if (elements->Size() > kMaxRegularHeapObjectSize) return false;
532  } else {
533  return false;
534  }
535  }
536 
537  // TODO(turbofan): Do we want to support out-of-object properties?
538  if (!(boilerplate->HasFastProperties() &&
539  boilerplate->property_array()->length() == 0)) {
540  return false;
541  }
542 
543  // Check the in-object properties.
544  Handle<DescriptorArray> descriptors(
545  boilerplate->map()->instance_descriptors(), isolate);
546  int limit = boilerplate->map()->NumberOfOwnDescriptors();
547  for (int i = 0; i < limit; i++) {
548  PropertyDetails details = descriptors->GetDetails(i);
549  if (details.location() != kField) continue;
550  DCHECK_EQ(kData, details.kind());
551  if ((*max_properties)-- == 0) return false;
552  FieldIndex field_index = FieldIndex::ForDescriptor(boilerplate->map(), i);
553  if (boilerplate->IsUnboxedDoubleField(field_index)) continue;
554  Handle<Object> value(boilerplate->RawFastPropertyAt(field_index), isolate);
555  if (value->IsJSObject()) {
556  Handle<JSObject> value_object = Handle<JSObject>::cast(value);
557  if (!IsFastLiteralHelper(value_object, max_depth - 1, max_properties)) {
558  return false;
559  }
560  }
561  }
562  return true;
563 }
564 
565 // Maximum depth and total number of elements and properties for literal
566 // graphs to be considered for fast deep-copying. The limit is chosen to
567 // match the maximum number of inobject properties, to ensure that the
568 // performance of using object literals is not worse than using constructor
569 // functions, see crbug.com/v8/6211 for details.
570 const int kMaxFastLiteralDepth = 3;
571 const int kMaxFastLiteralProperties = JSObject::kMaxInObjectProperties;
572 
573 // Determines whether the given array or object literal boilerplate satisfies
574 // all limits to be considered for fast deep-copying and computes the total
575 // size of all objects that are part of the graph.
576 bool IsInlinableFastLiteral(Handle<JSObject> boilerplate) {
577  int max_properties = kMaxFastLiteralProperties;
578  return IsFastLiteralHelper(boilerplate, kMaxFastLiteralDepth,
579  &max_properties);
580 }
581 
582 } // namespace
583 
585  public:
586  AllocationSiteData(JSHeapBroker* broker, ObjectData** storage,
587  Handle<AllocationSite> object);
588  void SerializeBoilerplate(JSHeapBroker* broker);
589 
590  bool PointsToLiteral() const { return PointsToLiteral_; }
591  PretenureFlag GetPretenureMode() const { return GetPretenureMode_; }
592  ObjectData* nested_site() const { return nested_site_; }
593  bool IsFastLiteral() const { return IsFastLiteral_; }
594  JSObjectData* boilerplate() const { return boilerplate_; }
595 
596  // These are only valid if PointsToLiteral is false.
597  ElementsKind GetElementsKind() const { return GetElementsKind_; }
598  bool CanInlineCall() const { return CanInlineCall_; }
599 
600  private:
601  bool const PointsToLiteral_;
602  PretenureFlag const GetPretenureMode_;
603  ObjectData* nested_site_ = nullptr;
604  bool IsFastLiteral_ = false;
605  JSObjectData* boilerplate_ = nullptr;
606  ElementsKind GetElementsKind_ = NO_ELEMENTS;
607  bool CanInlineCall_ = false;
608  bool serialized_boilerplate_ = false;
609 };
610 
611 // Only used in JSNativeContextSpecialization.
613  public:
616  : HeapObjectData(broker, storage, object) {}
617 };
618 
620  NameData* key = nullptr;
621  PropertyDetails details = PropertyDetails::Empty();
622  FieldIndex field_index;
623  MapData* field_owner = nullptr;
624  ObjectData* field_type = nullptr;
625  bool is_unboxed_double_field = false;
626 };
627 
628 class MapData : public HeapObjectData {
629  public:
630  MapData(JSHeapBroker* broker, ObjectData** storage, Handle<Map> object);
631 
632  InstanceType instance_type() const { return instance_type_; }
633  int instance_size() const { return instance_size_; }
634  byte bit_field() const { return bit_field_; }
635  byte bit_field2() const { return bit_field2_; }
636  uint32_t bit_field3() const { return bit_field3_; }
637  bool can_be_deprecated() const { return can_be_deprecated_; }
638  bool can_transition() const { return can_transition_; }
639  int in_object_properties_start_in_words() const {
640  CHECK(InstanceTypeChecker::IsJSObject(instance_type()));
641  return in_object_properties_start_in_words_;
642  }
643  int in_object_properties() const {
644  CHECK(InstanceTypeChecker::IsJSObject(instance_type()));
645  return in_object_properties_;
646  }
647  int constructor_function_index() const { return constructor_function_index_; }
648 
649  // Extra information.
650 
651  void SerializeElementsKindGeneralizations(JSHeapBroker* broker);
652  const ZoneVector<MapData*>& elements_kind_generalizations() const {
653  CHECK(serialized_elements_kind_generalizations_);
654  return elements_kind_generalizations_;
655  }
656 
657  // Serialize the own part of the descriptor array and, recursively, that of
658  // any field owner.
659  void SerializeOwnDescriptors(JSHeapBroker* broker);
660  DescriptorArrayData* instance_descriptors() const {
661  CHECK(serialized_own_descriptors_);
662  return instance_descriptors_;
663  }
664 
665  void SerializeConstructor(JSHeapBroker* broker);
666  ObjectData* GetConstructor() const {
667  CHECK(serialized_constructor_);
668  return constructor_;
669  }
670 
671  void SerializePrototype(JSHeapBroker* broker);
672  ObjectData* prototype() const {
673  CHECK(serialized_prototype_);
674  return prototype_;
675  }
676 
677  private:
678  InstanceType const instance_type_;
679  int const instance_size_;
680  byte const bit_field_;
681  byte const bit_field2_;
682  uint32_t const bit_field3_;
683  bool const can_be_deprecated_;
684  bool const can_transition_;
685  int const in_object_properties_start_in_words_;
686  int const in_object_properties_;
687  int const constructor_function_index_;
688 
689  bool serialized_elements_kind_generalizations_ = false;
690  ZoneVector<MapData*> elements_kind_generalizations_;
691 
692  bool serialized_own_descriptors_ = false;
693  DescriptorArrayData* instance_descriptors_ = nullptr;
694 
695  bool serialized_constructor_ = false;
696  ObjectData* constructor_ = nullptr;
697 
698  bool serialized_prototype_ = false;
699  ObjectData* prototype_ = nullptr;
700 };
701 
702 AllocationSiteData::AllocationSiteData(JSHeapBroker* broker,
703  ObjectData** storage,
704  Handle<AllocationSite> object)
705  : HeapObjectData(broker, storage, object),
706  PointsToLiteral_(object->PointsToLiteral()),
707  GetPretenureMode_(object->GetPretenureMode()) {
708  if (PointsToLiteral_) {
709  IsFastLiteral_ = IsInlinableFastLiteral(
710  handle(object->boilerplate(), broker->isolate()));
711  } else {
712  GetElementsKind_ = object->GetElementsKind();
713  CanInlineCall_ = object->CanInlineCall();
714  }
715 }
716 
717 void AllocationSiteData::SerializeBoilerplate(JSHeapBroker* broker) {
718  if (serialized_boilerplate_) return;
719  serialized_boilerplate_ = true;
720 
721  TraceScope tracer(broker, this, "AllocationSiteData::SerializeBoilerplate");
722  Handle<AllocationSite> site = Handle<AllocationSite>::cast(object());
723 
724  CHECK(IsFastLiteral_);
725  DCHECK_NULL(boilerplate_);
726  boilerplate_ = broker->GetOrCreateData(site->boilerplate())->AsJSObject();
727  boilerplate_->SerializeAsBoilerplate(broker);
728 
729  DCHECK_NULL(nested_site_);
730  nested_site_ = broker->GetOrCreateData(site->nested_site());
731  if (nested_site_->IsAllocationSite()) {
732  nested_site_->AsAllocationSite()->SerializeBoilerplate(broker);
733  }
734 }
735 
736 HeapObjectData::HeapObjectData(JSHeapBroker* broker, ObjectData** storage,
737  Handle<HeapObject> object)
738  : ObjectData(broker, storage, object, kSerializedHeapObject),
739  boolean_value_(object->BooleanValue(broker->isolate())),
740  // We have to use a raw cast below instead of AsMap() because of
741  // recursion. AsMap() would call IsMap(), which accesses the
742  // instance_type_ member. In the case of constructing the MapData for the
743  // meta map (whose map is itself), this member has not yet been
744  // initialized.
745  map_(static_cast<MapData*>(broker->GetOrCreateData(object->map()))) {
746  CHECK(broker->SerializingAllowed());
747 }
748 
749 MapData::MapData(JSHeapBroker* broker, ObjectData** storage, Handle<Map> object)
750  : HeapObjectData(broker, storage, object),
751  instance_type_(object->instance_type()),
752  instance_size_(object->instance_size()),
753  bit_field_(object->bit_field()),
754  bit_field2_(object->bit_field2()),
755  bit_field3_(object->bit_field3()),
756  can_be_deprecated_(object->NumberOfOwnDescriptors() > 0
757  ? object->CanBeDeprecated()
758  : false),
759  can_transition_(object->CanTransition()),
760  in_object_properties_start_in_words_(
761  object->IsJSObjectMap() ? object->GetInObjectPropertiesStartInWords()
762  : 0),
763  in_object_properties_(
764  object->IsJSObjectMap() ? object->GetInObjectProperties() : 0),
765  constructor_function_index_(object->IsPrimitiveMap()
766  ? object->GetConstructorFunctionIndex()
767  : Map::kNoConstructorFunctionIndex),
768  elements_kind_generalizations_(broker->zone()) {}
769 
770 JSFunctionData::JSFunctionData(JSHeapBroker* broker, ObjectData** storage,
771  Handle<JSFunction> object)
772  : JSObjectData(broker, storage, object),
773  has_initial_map_(object->has_prototype_slot() &&
774  object->has_initial_map()),
775  has_prototype_(object->has_prototype_slot() && object->has_prototype()),
776  PrototypeRequiresRuntimeLookup_(
777  object->PrototypeRequiresRuntimeLookup()) {}
778 
779 void JSFunctionData::Serialize(JSHeapBroker* broker) {
780  if (serialized_) return;
781  serialized_ = true;
782 
783  TraceScope tracer(broker, this, "JSFunctionData::Serialize");
784  Handle<JSFunction> function = Handle<JSFunction>::cast(object());
785 
786  DCHECK_NULL(context_);
787  DCHECK_NULL(native_context_);
788  DCHECK_NULL(initial_map_);
789  DCHECK_NULL(prototype_);
790  DCHECK_NULL(shared_);
791 
792  context_ = broker->GetOrCreateData(function->context())->AsContext();
793  native_context_ =
794  broker->GetOrCreateData(function->native_context())->AsNativeContext();
795  shared_ = broker->GetOrCreateData(function->shared())->AsSharedFunctionInfo();
796  initial_map_ = has_initial_map()
797  ? broker->GetOrCreateData(function->initial_map())->AsMap()
798  : nullptr;
799  prototype_ = has_prototype() ? broker->GetOrCreateData(function->prototype())
800  : nullptr;
801 
802  if (initial_map_ != nullptr) {
803  initial_map_instance_size_with_min_slack_ =
804  function->ComputeInstanceSizeWithMinSlack(broker->isolate());
805  if (initial_map_->instance_type() == JS_ARRAY_TYPE) {
806  initial_map_->SerializeElementsKindGeneralizations(broker);
807  }
808  initial_map_->SerializeConstructor(broker);
809  // TODO(neis): This is currently only needed for native_context's
810  // object_function, as used by GetObjectCreateMap. If no further use sites
811  // show up, we should move this into NativeContextData::Serialize.
812  initial_map_->SerializePrototype(broker);
813  }
814 }
815 
816 void MapData::SerializeElementsKindGeneralizations(JSHeapBroker* broker) {
817  if (serialized_elements_kind_generalizations_) return;
818  serialized_elements_kind_generalizations_ = true;
819 
820  TraceScope tracer(broker, this,
821  "MapData::SerializeElementsKindGeneralizations");
822  DCHECK_EQ(instance_type(), JS_ARRAY_TYPE);
823  MapRef self(broker, this);
824  ElementsKind from_kind = self.elements_kind();
825  DCHECK(elements_kind_generalizations_.empty());
826  for (int i = FIRST_FAST_ELEMENTS_KIND; i <= LAST_FAST_ELEMENTS_KIND; i++) {
827  ElementsKind to_kind = static_cast<ElementsKind>(i);
828  if (IsMoreGeneralElementsKindTransition(from_kind, to_kind)) {
829  Handle<Map> target =
830  Map::AsElementsKind(broker->isolate(), self.object(), to_kind);
831  elements_kind_generalizations_.push_back(
832  broker->GetOrCreateData(target)->AsMap());
833  }
834  }
835 }
836 
838  public:
839  DescriptorArrayData(JSHeapBroker* broker, ObjectData** storage,
841  : HeapObjectData(broker, storage, object), contents_(broker->zone()) {}
842 
843  ZoneVector<PropertyDescriptor>& contents() { return contents_; }
844 
845  private:
847 };
848 
850  public:
851  const ZoneVector<ObjectData*>& feedback() { return feedback_; }
852 
853  FeedbackVectorData(JSHeapBroker* broker, ObjectData** storage,
854  Handle<FeedbackVector> object);
855 
856  void SerializeSlots(JSHeapBroker* broker);
857 
858  private:
859  bool serialized_ = false;
860  ZoneVector<ObjectData*> feedback_;
861 };
862 
863 FeedbackVectorData::FeedbackVectorData(JSHeapBroker* broker,
864  ObjectData** storage,
865  Handle<FeedbackVector> object)
866  : HeapObjectData(broker, storage, object), feedback_(broker->zone()) {}
867 
868 void FeedbackVectorData::SerializeSlots(JSHeapBroker* broker) {
869  if (serialized_) return;
870  serialized_ = true;
871 
872  TraceScope tracer(broker, this, "FeedbackVectorData::SerializeSlots");
874  DCHECK(feedback_.empty());
875  feedback_.reserve(vector->length());
876  for (int i = 0; i < vector->length(); ++i) {
877  MaybeObject value = vector->get(i);
878  ObjectData* slot_value =
879  value->IsObject() ? broker->GetOrCreateData(value->cast<Object>())
880  : nullptr;
881  feedback_.push_back(slot_value);
882  if (slot_value == nullptr) continue;
883 
884  if (slot_value->IsAllocationSite() &&
885  slot_value->AsAllocationSite()->IsFastLiteral()) {
886  slot_value->AsAllocationSite()->SerializeBoilerplate(broker);
887  } else if (slot_value->IsJSRegExp()) {
888  slot_value->AsJSRegExp()->SerializeAsRegExpBoilerplate(broker);
889  }
890  }
891  DCHECK_EQ(vector->length(), feedback_.size());
892  broker->Trace("Copied %zu slots.\n", feedback_.size());
893 }
894 
896  public:
897  FixedArrayBaseData(JSHeapBroker* broker, ObjectData** storage,
898  Handle<FixedArrayBase> object)
899  // TODO(3770): Drop explicit cast after migrating HeapObject*.
900  : HeapObjectData(broker, storage, Handle<HeapObject>(object.location())),
901  length_(object->length()) {}
902 
903  int length() const { return length_; }
904 
905  private:
906  int const length_;
907 };
908 
910  public:
911  FixedArrayData(JSHeapBroker* broker, ObjectData** storage,
912  Handle<FixedArray> object);
913 
914  // Creates all elements of the fixed array.
915  void SerializeContents(JSHeapBroker* broker);
916 
917  ObjectData* Get(int i) const;
918 
919  private:
920  bool serialized_contents_ = false;
921  ZoneVector<ObjectData*> contents_;
922 };
923 
924 JSDataViewData::JSDataViewData(JSHeapBroker* broker, ObjectData** storage,
925  Handle<JSDataView> object)
926  : JSObjectData(broker, storage, object),
927  byte_length_(object->byte_length()),
928  byte_offset_(object->byte_offset()) {}
929 
930 JSBoundFunctionData::JSBoundFunctionData(JSHeapBroker* broker,
931  ObjectData** storage,
933  : JSObjectData(broker, storage, object) {}
934 
935 void JSBoundFunctionData::Serialize(JSHeapBroker* broker) {
936  if (serialized_) return;
937  serialized_ = true;
938 
939  TraceScope tracer(broker, this, "JSBoundFunctionData::Serialize");
941 
942  DCHECK_NULL(bound_target_function_);
943  DCHECK_NULL(bound_this_);
944  DCHECK_NULL(bound_arguments_);
945 
946  bound_target_function_ =
947  broker->GetOrCreateData(function->bound_target_function());
948  bound_this_ = broker->GetOrCreateData(function->bound_this());
949  bound_arguments_ =
950  broker->GetOrCreateData(function->bound_arguments())->AsFixedArray();
951 
952  bound_arguments_->SerializeContents(broker);
953 }
954 
955 JSObjectData::JSObjectData(JSHeapBroker* broker, ObjectData** storage,
956  Handle<JSObject> object)
957  : HeapObjectData(broker, storage, object),
958  inobject_fields_(broker->zone()) {}
959 
960 FixedArrayData::FixedArrayData(JSHeapBroker* broker, ObjectData** storage,
961  Handle<FixedArray> object)
962  : FixedArrayBaseData(broker, storage, object), contents_(broker->zone()) {}
963 
964 void FixedArrayData::SerializeContents(JSHeapBroker* broker) {
965  if (serialized_contents_) return;
966  serialized_contents_ = true;
967 
968  TraceScope tracer(broker, this, "FixedArrayData::SerializeContents");
969  Handle<FixedArray> array = Handle<FixedArray>::cast(object());
970  CHECK_EQ(array->length(), length());
971  CHECK(contents_.empty());
972  contents_.reserve(static_cast<size_t>(length()));
973 
974  for (int i = 0; i < length(); i++) {
975  Handle<Object> value(array->get(i), broker->isolate());
976  contents_.push_back(broker->GetOrCreateData(value));
977  }
978  broker->Trace("Copied %zu elements.\n", contents_.size());
979 }
980 
982  public:
983  FixedDoubleArrayData(JSHeapBroker* broker, ObjectData** storage,
984  Handle<FixedDoubleArray> object);
985 
986  // Serializes all elements of the fixed array.
987  void SerializeContents(JSHeapBroker* broker);
988 
989  Float64 Get(int i) const;
990 
991  private:
992  bool serialized_contents_ = false;
993  ZoneVector<Float64> contents_;
994 };
995 
996 FixedDoubleArrayData::FixedDoubleArrayData(JSHeapBroker* broker,
997  ObjectData** storage,
999  : FixedArrayBaseData(broker, storage, object), contents_(broker->zone()) {}
1000 
1001 void FixedDoubleArrayData::SerializeContents(JSHeapBroker* broker) {
1002  if (serialized_contents_) return;
1003  serialized_contents_ = true;
1004 
1005  TraceScope tracer(broker, this, "FixedDoubleArrayData::SerializeContents");
1007  CHECK_EQ(self->length(), length());
1008  CHECK(contents_.empty());
1009  contents_.reserve(static_cast<size_t>(length()));
1010 
1011  for (int i = 0; i < length(); i++) {
1012  contents_.push_back(Float64::FromBits(self->get_representation(i)));
1013  }
1014  broker->Trace("Copied %zu elements.\n", contents_.size());
1015 }
1016 
1018  public:
1019  int register_count() const { return register_count_; }
1020 
1021  BytecodeArrayData(JSHeapBroker* broker, ObjectData** storage,
1022  Handle<BytecodeArray> object)
1023  : FixedArrayBaseData(broker, storage, object),
1024  register_count_(object->register_count()) {}
1025 
1026  private:
1027  int const register_count_;
1028 };
1029 
1030 class JSArrayData : public JSObjectData {
1031  public:
1032  JSArrayData(JSHeapBroker* broker, ObjectData** storage,
1033  Handle<JSArray> object);
1034  void Serialize(JSHeapBroker* broker);
1035 
1036  ObjectData* length() const { return length_; }
1037 
1038  private:
1039  bool serialized_ = false;
1040  ObjectData* length_ = nullptr;
1041 };
1042 
1043 JSArrayData::JSArrayData(JSHeapBroker* broker, ObjectData** storage,
1044  Handle<JSArray> object)
1045  : JSObjectData(broker, storage, object) {}
1046 
1047 void JSArrayData::Serialize(JSHeapBroker* broker) {
1048  if (serialized_) return;
1049  serialized_ = true;
1050 
1051  TraceScope tracer(broker, this, "JSArrayData::Serialize");
1052  Handle<JSArray> jsarray = Handle<JSArray>::cast(object());
1053  DCHECK_NULL(length_);
1054  length_ = broker->GetOrCreateData(jsarray->length());
1055 }
1056 
1058  public:
1059  ScopeInfoData(JSHeapBroker* broker, ObjectData** storage,
1060  Handle<ScopeInfo> object);
1061 
1062  int context_length() const { return context_length_; }
1063 
1064  private:
1065  int const context_length_;
1066 };
1067 
1068 ScopeInfoData::ScopeInfoData(JSHeapBroker* broker, ObjectData** storage,
1069  Handle<ScopeInfo> object)
1070  : HeapObjectData(broker, storage, object),
1071  context_length_(object->ContextLength()) {}
1072 
1074  public:
1075  int builtin_id() const { return builtin_id_; }
1076  BytecodeArrayData* GetBytecodeArray() const { return GetBytecodeArray_; }
1077 #define DECL_ACCESSOR(type, name) \
1078  type name() const { return name##_; }
1079  BROKER_SFI_FIELDS(DECL_ACCESSOR)
1080 #undef DECL_ACCESSOR
1081 
1082  SharedFunctionInfoData(JSHeapBroker* broker, ObjectData** storage,
1084  : HeapObjectData(broker, storage, object),
1085  builtin_id_(object->HasBuiltinId() ? object->builtin_id()
1086  : Builtins::kNoBuiltinId),
1087  GetBytecodeArray_(
1088  object->HasBytecodeArray()
1089  ? broker->GetOrCreateData(object->GetBytecodeArray())
1090  ->AsBytecodeArray()
1091  : nullptr)
1092 #define INIT_MEMBER(type, name) , name##_(object->name())
1093  BROKER_SFI_FIELDS(INIT_MEMBER)
1094 #undef INIT_MEMBER
1095  {
1096  DCHECK_EQ(HasBuiltinId_, builtin_id_ != Builtins::kNoBuiltinId);
1097  DCHECK_EQ(HasBytecodeArray_, GetBytecodeArray_ != nullptr);
1098  }
1099 
1100  private:
1101  int const builtin_id_;
1102  BytecodeArrayData* const GetBytecodeArray_;
1103 #define DECL_MEMBER(type, name) type const name##_;
1104  BROKER_SFI_FIELDS(DECL_MEMBER)
1105 #undef DECL_MEMBER
1106 };
1107 
1108 class ModuleData : public HeapObjectData {
1109  public:
1110  ModuleData(JSHeapBroker* broker, ObjectData** storage, Handle<Module> object);
1111  void Serialize(JSHeapBroker* broker);
1112 
1113  CellData* GetCell(int cell_index) const;
1114 
1115  private:
1116  bool serialized_ = false;
1117  ZoneVector<CellData*> imports_;
1118  ZoneVector<CellData*> exports_;
1119 };
1120 
1121 ModuleData::ModuleData(JSHeapBroker* broker, ObjectData** storage,
1122  Handle<Module> object)
1123  : HeapObjectData(broker, storage, object),
1124  imports_(broker->zone()),
1125  exports_(broker->zone()) {}
1126 
1127 CellData* ModuleData::GetCell(int cell_index) const {
1128  CHECK(serialized_);
1129  CellData* cell;
1130  switch (ModuleDescriptor::GetCellIndexKind(cell_index)) {
1131  case ModuleDescriptor::kImport:
1132  cell = imports_.at(Module::ImportIndex(cell_index));
1133  break;
1134  case ModuleDescriptor::kExport:
1135  cell = exports_.at(Module::ExportIndex(cell_index));
1136  break;
1137  case ModuleDescriptor::kInvalid:
1138  UNREACHABLE();
1139  break;
1140  }
1141  CHECK_NOT_NULL(cell);
1142  return cell;
1143 }
1144 
1145 void ModuleData::Serialize(JSHeapBroker* broker) {
1146  if (serialized_) return;
1147  serialized_ = true;
1148 
1149  TraceScope tracer(broker, this, "ModuleData::Serialize");
1150  Handle<Module> module = Handle<Module>::cast(object());
1151 
1152  // TODO(neis): We could be smarter and only serialize the cells we care about.
1153  // TODO(neis): Define a helper for serializing a FixedArray into a ZoneVector.
1154 
1155  DCHECK(imports_.empty());
1156  Handle<FixedArray> imports(module->regular_imports(), broker->isolate());
1157  int const imports_length = imports->length();
1158  imports_.reserve(imports_length);
1159  for (int i = 0; i < imports_length; ++i) {
1160  imports_.push_back(broker->GetOrCreateData(imports->get(i))->AsCell());
1161  }
1162  broker->Trace("Copied %zu imports.\n", imports_.size());
1163 
1164  DCHECK(exports_.empty());
1165  Handle<FixedArray> exports(module->regular_exports(), broker->isolate());
1166  int const exports_length = exports->length();
1167  exports_.reserve(exports_length);
1168  for (int i = 0; i < exports_length; ++i) {
1169  exports_.push_back(broker->GetOrCreateData(exports->get(i))->AsCell());
1170  }
1171  broker->Trace("Copied %zu exports.\n", exports_.size());
1172 }
1173 
1174 class CellData : public HeapObjectData {
1175  public:
1176  CellData(JSHeapBroker* broker, ObjectData** storage, Handle<Cell> object);
1177 
1178  void Serialize(JSHeapBroker* broker);
1179  ObjectData* value() { return value_; }
1180 
1181  private:
1182  bool serialized_ = false;
1183  ObjectData* value_ = nullptr;
1184 };
1185 
1186 CellData::CellData(JSHeapBroker* broker, ObjectData** storage,
1187  Handle<Cell> object)
1188  : HeapObjectData(broker, storage, object) {}
1189 
1190 void CellData::Serialize(JSHeapBroker* broker) {
1191  if (serialized_) return;
1192  serialized_ = true;
1193 
1194  TraceScope tracer(broker, this, "CellData::Serialize");
1195  auto cell = Handle<Cell>::cast(object());
1196  DCHECK_NULL(value_);
1197  value_ = broker->GetOrCreateData(cell->value());
1198 }
1199 
1201  public:
1202  JSGlobalProxyData(JSHeapBroker* broker, ObjectData** storage,
1203  Handle<JSGlobalProxy> object)
1204  : JSObjectData(broker, storage, object) {}
1205 };
1206 
1207 class CodeData : public HeapObjectData {
1208  public:
1209  CodeData(JSHeapBroker* broker, ObjectData** storage, Handle<Code> object)
1210  : HeapObjectData(broker, storage, object) {}
1211 };
1212 
1213 #define DEFINE_IS_AND_AS(Name) \
1214  bool ObjectData::Is##Name() const { \
1215  if (kind() == kUnserializedHeapObject) { \
1216  AllowHandleDereference allow_handle_dereference; \
1217  return object()->Is##Name(); \
1218  } \
1219  if (is_smi()) return false; \
1220  InstanceType instance_type = \
1221  static_cast<const HeapObjectData*>(this)->map()->instance_type(); \
1222  return InstanceTypeChecker::Is##Name(instance_type); \
1223  } \
1224  Name##Data* ObjectData::As##Name() { \
1225  CHECK_EQ(kind(), kSerializedHeapObject); \
1226  CHECK(Is##Name()); \
1227  return static_cast<Name##Data*>(this); \
1228  }
1229 HEAP_BROKER_OBJECT_LIST(DEFINE_IS_AND_AS)
1230 #undef DEFINE_IS_AND_AS
1231 
1232 const JSObjectField& JSObjectData::GetInobjectField(int property_index) const {
1233  CHECK_LT(static_cast<size_t>(property_index), inobject_fields_.size());
1234  return inobject_fields_[property_index];
1235 }
1236 
1237 bool JSObjectData::cow_or_empty_elements_tenured() const {
1238  return cow_or_empty_elements_tenured_;
1239 }
1240 
1241 FixedArrayBaseData* JSObjectData::elements() const { return elements_; }
1242 
1243 void JSObjectData::SerializeAsBoilerplate(JSHeapBroker* broker) {
1244  SerializeRecursive(broker, kMaxFastLiteralDepth);
1245 }
1246 
1247 void JSObjectData::SerializeElements(JSHeapBroker* broker) {
1248  if (serialized_elements_) return;
1249  serialized_elements_ = true;
1250 
1251  TraceScope tracer(broker, this, "JSObjectData::SerializeElements");
1252  Handle<JSObject> boilerplate = Handle<JSObject>::cast(object());
1253  Handle<FixedArrayBase> elements_object(boilerplate->elements(),
1254  broker->isolate());
1255  DCHECK_NULL(elements_);
1256  elements_ = broker->GetOrCreateData(elements_object)->AsFixedArrayBase();
1257 }
1258 
1259 void MapData::SerializeConstructor(JSHeapBroker* broker) {
1260  if (serialized_constructor_) return;
1261  serialized_constructor_ = true;
1262 
1263  TraceScope tracer(broker, this, "MapData::SerializeConstructor");
1264  Handle<Map> map = Handle<Map>::cast(object());
1265  DCHECK_NULL(constructor_);
1266  constructor_ = broker->GetOrCreateData(map->GetConstructor());
1267 }
1268 
1269 void MapData::SerializePrototype(JSHeapBroker* broker) {
1270  if (serialized_prototype_) return;
1271  serialized_prototype_ = true;
1272 
1273  TraceScope tracer(broker, this, "MapData::SerializePrototype");
1274  Handle<Map> map = Handle<Map>::cast(object());
1275  DCHECK_NULL(prototype_);
1276  prototype_ = broker->GetOrCreateData(map->prototype());
1277 }
1278 
1279 void MapData::SerializeOwnDescriptors(JSHeapBroker* broker) {
1280  if (serialized_own_descriptors_) return;
1281  serialized_own_descriptors_ = true;
1282 
1283  TraceScope tracer(broker, this, "MapData::SerializeOwnDescriptors");
1284  Handle<Map> map = Handle<Map>::cast(object());
1285 
1286  DCHECK_NULL(instance_descriptors_);
1287  instance_descriptors_ =
1288  broker->GetOrCreateData(map->instance_descriptors())->AsDescriptorArray();
1289 
1290  int const number_of_own = map->NumberOfOwnDescriptors();
1291  ZoneVector<PropertyDescriptor>& contents = instance_descriptors_->contents();
1292  int const current_size = static_cast<int>(contents.size());
1293  if (number_of_own <= current_size) return;
1294 
1295  Isolate* const isolate = broker->isolate();
1296  auto descriptors =
1297  Handle<DescriptorArray>::cast(instance_descriptors_->object());
1298  CHECK_EQ(*descriptors, map->instance_descriptors());
1299  contents.reserve(number_of_own);
1300 
1301  // Copy the new descriptors.
1302  for (int i = current_size; i < number_of_own; ++i) {
1303  PropertyDescriptor d;
1304  d.key = broker->GetOrCreateData(descriptors->GetKey(i))->AsName();
1305  d.details = descriptors->GetDetails(i);
1306  if (d.details.location() == kField) {
1307  d.field_index = FieldIndex::ForDescriptor(*map, i);
1308  d.field_owner =
1309  broker->GetOrCreateData(map->FindFieldOwner(isolate, i))->AsMap();
1310  d.field_type = broker->GetOrCreateData(descriptors->GetFieldType(i));
1311  d.is_unboxed_double_field = map->IsUnboxedDoubleField(d.field_index);
1312  // Recurse.
1313  }
1314  contents.push_back(d);
1315  }
1316  CHECK_EQ(number_of_own, contents.size());
1317 
1318  // Recurse on the new owner maps.
1319  for (int i = current_size; i < number_of_own; ++i) {
1320  const PropertyDescriptor& d = contents[i];
1321  if (d.details.location() == kField) {
1322  CHECK_LE(
1323  Handle<Map>::cast(d.field_owner->object())->NumberOfOwnDescriptors(),
1324  number_of_own);
1325  d.field_owner->SerializeOwnDescriptors(broker);
1326  }
1327  }
1328 
1329  broker->Trace("Copied %zu descriptors into %p (%zu total).\n",
1330  number_of_own - current_size, instance_descriptors_,
1331  number_of_own);
1332 }
1333 
1334 void JSObjectData::SerializeRecursive(JSHeapBroker* broker, int depth) {
1335  if (serialized_as_boilerplate_) return;
1336  serialized_as_boilerplate_ = true;
1337 
1338  TraceScope tracer(broker, this, "JSObjectData::SerializeRecursive");
1339  Handle<JSObject> boilerplate = Handle<JSObject>::cast(object());
1340 
1341  // We only serialize boilerplates that pass the IsInlinableFastLiteral
1342  // check, so we only do a sanity check on the depth here.
1343  CHECK_GT(depth, 0);
1344  CHECK(!boilerplate->map()->is_deprecated());
1345 
1346  // Serialize the elements.
1347  Isolate* const isolate = broker->isolate();
1348  Handle<FixedArrayBase> elements_object(boilerplate->elements(), isolate);
1349 
1350  // Boilerplates need special serialization - we need to make sure COW arrays
1351  // are tenured. Boilerplate objects should only be reachable from their
1352  // allocation site, so it is safe to assume that the elements have not been
1353  // serialized yet.
1354 
1355  bool const empty_or_cow =
1356  elements_object->length() == 0 ||
1357  elements_object->map() == ReadOnlyRoots(isolate).fixed_cow_array_map();
1358  if (empty_or_cow) {
1359  // We need to make sure copy-on-write elements are tenured.
1360  if (Heap::InNewSpace(*elements_object)) {
1361  elements_object = isolate->factory()->CopyAndTenureFixedCOWArray(
1362  Handle<FixedArray>::cast(elements_object));
1363  boilerplate->set_elements(*elements_object);
1364  }
1365  cow_or_empty_elements_tenured_ = true;
1366  }
1367 
1368  DCHECK_NULL(elements_);
1369  elements_ = broker->GetOrCreateData(elements_object)->AsFixedArrayBase();
1370 
1371  if (empty_or_cow) {
1372  // No need to do anything here. Empty or copy-on-write elements
1373  // do not need to be serialized because we only need to store the elements
1374  // reference to the allocated object.
1375  } else if (boilerplate->HasSmiOrObjectElements()) {
1376  elements_->AsFixedArray()->SerializeContents(broker);
1377  Handle<FixedArray> fast_elements =
1378  Handle<FixedArray>::cast(elements_object);
1379  int length = elements_object->length();
1380  for (int i = 0; i < length; i++) {
1381  Handle<Object> value(fast_elements->get(i), isolate);
1382  if (value->IsJSObject()) {
1383  ObjectData* value_data = broker->GetOrCreateData(value);
1384  value_data->AsJSObject()->SerializeRecursive(broker, depth - 1);
1385  }
1386  }
1387  } else {
1388  CHECK(boilerplate->HasDoubleElements());
1389  CHECK_LE(elements_object->Size(), kMaxRegularHeapObjectSize);
1390  elements_->AsFixedDoubleArray()->SerializeContents(broker);
1391  }
1392 
1393  // TODO(turbofan): Do we want to support out-of-object properties?
1394  CHECK(boilerplate->HasFastProperties() &&
1395  boilerplate->property_array()->length() == 0);
1396  CHECK_EQ(inobject_fields_.size(), 0u);
1397 
1398  // Check the in-object properties.
1399  Handle<DescriptorArray> descriptors(
1400  boilerplate->map()->instance_descriptors(), isolate);
1401  int const limit = boilerplate->map()->NumberOfOwnDescriptors();
1402  for (int i = 0; i < limit; i++) {
1403  PropertyDetails details = descriptors->GetDetails(i);
1404  if (details.location() != kField) continue;
1405  DCHECK_EQ(kData, details.kind());
1406 
1407  FieldIndex field_index = FieldIndex::ForDescriptor(boilerplate->map(), i);
1408  // Make sure {field_index} agrees with {inobject_properties} on the index of
1409  // this field.
1410  DCHECK_EQ(field_index.property_index(),
1411  static_cast<int>(inobject_fields_.size()));
1412  if (boilerplate->IsUnboxedDoubleField(field_index)) {
1413  double value = boilerplate->RawFastDoublePropertyAt(field_index);
1414  inobject_fields_.push_back(JSObjectField{value});
1415  } else {
1416  Handle<Object> value(boilerplate->RawFastPropertyAt(field_index),
1417  isolate);
1418  ObjectData* value_data = broker->GetOrCreateData(value);
1419  if (value->IsJSObject()) {
1420  value_data->AsJSObject()->SerializeRecursive(broker, depth - 1);
1421  }
1422  inobject_fields_.push_back(JSObjectField{value_data});
1423  }
1424  }
1425  broker->Trace("Copied %zu in-object fields.\n", inobject_fields_.size());
1426 
1427  map()->SerializeOwnDescriptors(broker);
1428 
1429  if (IsJSArray()) AsJSArray()->Serialize(broker);
1430 }
1431 
1432 void JSRegExpData::SerializeAsRegExpBoilerplate(JSHeapBroker* broker) {
1433  if (serialized_as_reg_exp_boilerplate_) return;
1434  serialized_as_reg_exp_boilerplate_ = true;
1435 
1436  TraceScope tracer(broker, this, "JSRegExpData::SerializeAsRegExpBoilerplate");
1437  Handle<JSRegExp> boilerplate = Handle<JSRegExp>::cast(object());
1438 
1439  SerializeElements(broker);
1440 
1441  raw_properties_or_hash_ =
1442  broker->GetOrCreateData(boilerplate->raw_properties_or_hash());
1443  data_ = broker->GetOrCreateData(boilerplate->data());
1444  source_ = broker->GetOrCreateData(boilerplate->source());
1445  flags_ = broker->GetOrCreateData(boilerplate->flags());
1446  last_index_ = broker->GetOrCreateData(boilerplate->last_index());
1447 }
1448 
1449 bool ObjectRef::equals(const ObjectRef& other) const {
1450  return data_ == other.data_;
1451 }
1452 
1453 Isolate* ObjectRef::isolate() const { return broker()->isolate(); }
1454 
1455 ContextRef ContextRef::previous() const {
1456  if (broker()->mode() == JSHeapBroker::kDisabled) {
1457  AllowHandleAllocation handle_allocation;
1458  AllowHandleDereference handle_dereference;
1459  return ContextRef(broker(),
1460  handle(object()->previous(), broker()->isolate()));
1461  }
1462  return ContextRef(broker(), data()->AsContext()->previous());
1463 }
1464 
1465 // Not needed for TypedLowering.
1466 ObjectRef ContextRef::get(int index) const {
1467  AllowHandleAllocation handle_allocation;
1468  AllowHandleDereference handle_dereference;
1469  Handle<Object> value(object()->get(index), broker()->isolate());
1470  return ObjectRef(broker(), value);
1471 }
1472 
1473 JSHeapBroker::JSHeapBroker(Isolate* isolate, Zone* broker_zone)
1474  : isolate_(isolate),
1475  broker_zone_(broker_zone),
1476  current_zone_(broker_zone),
1477  refs_(new (zone())
1478  RefsMap(kMinimalRefsBucketCount, AddressMatcher(), zone())),
1479  array_and_object_prototypes_(zone()) {
1480  // Note that this initialization of the refs_ pointer with the minimal
1481  // initial capacity is redundant in the normal use case (concurrent
1482  // compilation enabled, standard objects to be serialized), as the map
1483  // is going to be replaced immediatelly with a larger capacity one.
1484  // It doesn't seem to affect the performance in a noticeable way though.
1485  Trace("Constructing heap broker.\n");
1486 }
1487 
1488 void JSHeapBroker::Trace(const char* format, ...) const {
1489  if (FLAG_trace_heap_broker) {
1490  PrintF("[%p] ", this);
1491  for (unsigned i = 0; i < tracing_indentation_; ++i) PrintF(" ");
1492  va_list arguments;
1493  va_start(arguments, format);
1494  base::OS::VPrint(format, arguments);
1495  va_end(arguments);
1496  }
1497 }
1498 
1499 void JSHeapBroker::StartSerializing() {
1500  CHECK_EQ(mode_, kDisabled);
1501  Trace("Starting serialization.\n");
1502  mode_ = kSerializing;
1503  refs_->Clear();
1504 }
1505 
1506 void JSHeapBroker::StopSerializing() {
1507  CHECK_EQ(mode_, kSerializing);
1508  Trace("Stopping serialization.\n");
1509  mode_ = kSerialized;
1510 }
1511 
1512 void JSHeapBroker::Retire() {
1513  CHECK_EQ(mode_, kSerialized);
1514  Trace("Retiring.\n");
1515  mode_ = kRetired;
1516 }
1517 
1518 bool JSHeapBroker::SerializingAllowed() const { return mode() == kSerializing; }
1519 
1520 void JSHeapBroker::SetNativeContextRef() {
1521  native_context_ = NativeContextRef(this, isolate()->native_context());
1522 }
1523 
1524 bool IsShareable(Handle<Object> object, Isolate* isolate) {
1525  Builtins* const b = isolate->builtins();
1526 
1527  int index;
1528  RootIndex root_index;
1529  return (object->IsHeapObject() &&
1530  b->IsBuiltinHandle(Handle<HeapObject>::cast(object), &index)) ||
1531  isolate->roots_table().IsRootHandle(object, &root_index);
1532 }
1533 
1534 void JSHeapBroker::SerializeShareableObjects() {
1535  PerIsolateCompilerCache::Setup(isolate());
1536  compiler_cache_ = isolate()->compiler_cache();
1537 
1538  if (compiler_cache_->HasSnapshot()) {
1539  RefsMap* snapshot = compiler_cache_->GetSnapshot();
1540 
1541  refs_ = new (zone()) RefsMap(snapshot, zone());
1542  return;
1543  }
1544 
1545  TraceScope tracer(
1546  this, "JSHeapBroker::SerializeShareableObjects (building snapshot)");
1547 
1548  refs_ =
1549  new (zone()) RefsMap(kInitialRefsBucketCount, AddressMatcher(), zone());
1550 
1551  current_zone_ = compiler_cache_->zone();
1552 
1553  Builtins* const b = isolate()->builtins();
1554  {
1555  Builtins::Name builtins[] = {
1556  Builtins::kAllocateInNewSpace,
1557  Builtins::kAllocateInOldSpace,
1558  Builtins::kArgumentsAdaptorTrampoline,
1559  Builtins::kArrayConstructorImpl,
1560  Builtins::kCallFunctionForwardVarargs,
1561  Builtins::kCallFunction_ReceiverIsAny,
1562  Builtins::kCallFunction_ReceiverIsNotNullOrUndefined,
1563  Builtins::kCallFunction_ReceiverIsNullOrUndefined,
1564  Builtins::kConstructFunctionForwardVarargs,
1565  Builtins::kForInFilter,
1566  Builtins::kJSBuiltinsConstructStub,
1567  Builtins::kJSConstructStubGeneric,
1568  Builtins::kStringAdd_CheckNone,
1569  Builtins::kStringAdd_ConvertLeft,
1570  Builtins::kStringAdd_ConvertRight,
1571  Builtins::kToNumber,
1572  Builtins::kToObject,
1573  };
1574  for (auto id : builtins) {
1575  GetOrCreateData(b->builtin_handle(id));
1576  }
1577  }
1578  for (int32_t id = 0; id < Builtins::builtin_count; ++id) {
1579  if (Builtins::KindOf(id) == Builtins::TFJ) {
1580  GetOrCreateData(b->builtin_handle(id));
1581  }
1582  }
1583 
1584  for (RefsMap::Entry* p = refs_->Start(); p != nullptr; p = refs_->Next(p)) {
1585  CHECK(IsShareable(p->value->object(), isolate()));
1586  }
1587 
1588  // TODO(mslekova):
1589  // Serialize root objects (from factory).
1590  compiler_cache()->SetSnapshot(refs_);
1591  current_zone_ = broker_zone_;
1592 }
1593 
1594 void JSHeapBroker::CollectArrayAndObjectPrototypes() {
1595  DisallowHeapAllocation no_gc;
1596  CHECK_EQ(mode(), kSerializing);
1597  CHECK(array_and_object_prototypes_.empty());
1598 
1599  Object* maybe_context = isolate()->heap()->native_contexts_list();
1600  while (!maybe_context->IsUndefined(isolate())) {
1601  Context context = Context::cast(maybe_context);
1602  Object* array_prot = context->get(Context::INITIAL_ARRAY_PROTOTYPE_INDEX);
1603  Object* object_prot = context->get(Context::INITIAL_OBJECT_PROTOTYPE_INDEX);
1604  array_and_object_prototypes_.emplace(JSObject::cast(array_prot), isolate());
1605  array_and_object_prototypes_.emplace(JSObject::cast(object_prot),
1606  isolate());
1607  maybe_context = context->next_context_link();
1608  }
1609 
1610  CHECK(!array_and_object_prototypes_.empty());
1611 }
1612 
1613 bool JSHeapBroker::IsArrayOrObjectPrototype(const JSObjectRef& object) const {
1614  if (mode() == kDisabled) {
1615  return isolate()->IsInAnyContext(*object.object(),
1616  Context::INITIAL_ARRAY_PROTOTYPE_INDEX) ||
1617  isolate()->IsInAnyContext(*object.object(),
1618  Context::INITIAL_OBJECT_PROTOTYPE_INDEX);
1619  }
1620  CHECK(!array_and_object_prototypes_.empty());
1621  return array_and_object_prototypes_.find(object.object()) !=
1622  array_and_object_prototypes_.end();
1623 }
1624 
1625 void JSHeapBroker::SerializeStandardObjects() {
1626  if (mode() == kDisabled) return;
1627  CHECK_EQ(mode(), kSerializing);
1628 
1629  SerializeShareableObjects();
1630 
1631  TraceScope tracer(this, "JSHeapBroker::SerializeStandardObjects");
1632 
1633  CollectArrayAndObjectPrototypes();
1634 
1635  SetNativeContextRef();
1636  native_context().Serialize();
1637 
1638  Factory* const f = isolate()->factory();
1639 
1640  // Maps, strings, oddballs
1641  GetOrCreateData(f->arguments_marker_map());
1642  GetOrCreateData(f->bigint_string());
1643  GetOrCreateData(f->block_context_map());
1644  GetOrCreateData(f->boolean_map());
1645  GetOrCreateData(f->boolean_string());
1646  GetOrCreateData(f->catch_context_map());
1647  GetOrCreateData(f->empty_fixed_array());
1648  GetOrCreateData(f->empty_string());
1649  GetOrCreateData(f->eval_context_map());
1650  GetOrCreateData(f->false_string());
1651  GetOrCreateData(f->false_value());
1652  GetOrCreateData(f->fixed_array_map());
1653  GetOrCreateData(f->fixed_cow_array_map());
1654  GetOrCreateData(f->fixed_double_array_map());
1655  GetOrCreateData(f->function_context_map());
1656  GetOrCreateData(f->function_string());
1657  GetOrCreateData(f->heap_number_map());
1658  GetOrCreateData(f->length_string());
1659  GetOrCreateData(f->many_closures_cell_map());
1660  GetOrCreateData(f->minus_zero_value());
1661  GetOrCreateData(f->mutable_heap_number_map());
1662  GetOrCreateData(f->name_dictionary_map());
1663  GetOrCreateData(f->NaN_string());
1664  GetOrCreateData(f->null_map());
1665  GetOrCreateData(f->null_string());
1666  GetOrCreateData(f->null_value());
1667  GetOrCreateData(f->number_string());
1668  GetOrCreateData(f->object_string());
1669  GetOrCreateData(f->one_pointer_filler_map());
1670  GetOrCreateData(f->optimized_out());
1671  GetOrCreateData(f->optimized_out_map());
1672  GetOrCreateData(f->property_array_map());
1673  GetOrCreateData(f->sloppy_arguments_elements_map());
1674  GetOrCreateData(f->stale_register());
1675  GetOrCreateData(f->stale_register_map());
1676  GetOrCreateData(f->string_string());
1677  GetOrCreateData(f->symbol_string());
1678  GetOrCreateData(f->termination_exception_map());
1679  GetOrCreateData(f->the_hole_map());
1680  GetOrCreateData(f->the_hole_value());
1681  GetOrCreateData(f->true_string());
1682  GetOrCreateData(f->true_value());
1683  GetOrCreateData(f->undefined_map());
1684  GetOrCreateData(f->undefined_string());
1685  GetOrCreateData(f->undefined_value());
1686  GetOrCreateData(f->uninitialized_map());
1687  GetOrCreateData(f->with_context_map());
1688  GetOrCreateData(f->zero_string());
1689 
1690  // Protector cells
1691  GetOrCreateData(f->array_buffer_neutering_protector())
1692  ->AsPropertyCell()
1693  ->Serialize(this);
1694  GetOrCreateData(f->array_constructor_protector())->AsCell()->Serialize(this);
1695  GetOrCreateData(f->array_iterator_protector())
1696  ->AsPropertyCell()
1697  ->Serialize(this);
1698  GetOrCreateData(f->array_species_protector())
1699  ->AsPropertyCell()
1700  ->Serialize(this);
1701  GetOrCreateData(f->no_elements_protector())
1702  ->AsPropertyCell()
1703  ->Serialize(this);
1704  GetOrCreateData(f->promise_hook_protector())
1705  ->AsPropertyCell()
1706  ->Serialize(this);
1707  GetOrCreateData(f->promise_species_protector())
1708  ->AsPropertyCell()
1709  ->Serialize(this);
1710  GetOrCreateData(f->promise_then_protector())
1711  ->AsPropertyCell()
1712  ->Serialize(this);
1713  GetOrCreateData(f->string_length_protector())->AsCell()->Serialize(this);
1714 
1715  // CEntry stub
1716  GetOrCreateData(
1717  CodeFactory::CEntry(isolate(), 1, kDontSaveFPRegs, kArgvOnStack, true));
1718 
1719  Trace("Finished serializing standard objects.\n");
1720 }
1721 
1722 ObjectData* JSHeapBroker::GetData(Handle<Object> object) const {
1723  RefsMap::Entry* entry = refs_->Lookup(object.address());
1724  return entry ? entry->value : nullptr;
1725 }
1726 
1727 // clang-format off
1728 ObjectData* JSHeapBroker::GetOrCreateData(Handle<Object> object) {
1729  CHECK(SerializingAllowed());
1730  RefsMap::Entry* entry = refs_->LookupOrInsert(object.address(), zone());
1731  ObjectData** data_storage = &(entry->value);
1732  if (*data_storage == nullptr) {
1733  // TODO(neis): Remove these Allow* once we serialize everything upfront.
1734  AllowHandleAllocation handle_allocation;
1735  AllowHandleDereference handle_dereference;
1736  if (object->IsSmi()) {
1737  new (zone()) ObjectData(this, data_storage, object, kSmi);
1738 #define CREATE_DATA_IF_MATCH(name) \
1739  } else if (object->Is##name()) { \
1740  new (zone()) name##Data(this, data_storage, Handle<name>::cast(object));
1741  HEAP_BROKER_OBJECT_LIST(CREATE_DATA_IF_MATCH)
1742 #undef CREATE_DATA_IF_MATCH
1743  } else {
1744  UNREACHABLE();
1745  }
1746  }
1747  CHECK_NOT_NULL(*data_storage);
1748  return (*data_storage);
1749 }
1750 // clang-format on
1751 
1752 ObjectData* JSHeapBroker::GetOrCreateData(Object* object) {
1753  return GetOrCreateData(handle(object, isolate()));
1754 }
1755 
1756 #define DEFINE_IS_AND_AS(Name) \
1757  bool ObjectRef::Is##Name() const { return data()->Is##Name(); } \
1758  Name##Ref ObjectRef::As##Name() const { \
1759  DCHECK(Is##Name()); \
1760  return Name##Ref(broker(), data()); \
1761  }
1762 HEAP_BROKER_OBJECT_LIST(DEFINE_IS_AND_AS)
1763 #undef DEFINE_IS_AND_AS
1764 
1765 bool ObjectRef::IsSmi() const { return data()->is_smi(); }
1766 
1767 int ObjectRef::AsSmi() const {
1768  DCHECK(IsSmi());
1769  // Handle-dereference is always allowed for Handle<Smi>.
1770  return Handle<Smi>::cast(object())->value();
1771 }
1772 
1773 base::Optional<MapRef> JSObjectRef::GetObjectCreateMap() const {
1774  if (broker()->mode() == JSHeapBroker::kDisabled) {
1775  AllowHandleAllocation handle_allocation;
1776  AllowHandleDereference allow_handle_dereference;
1777  AllowHeapAllocation heap_allocation;
1778  Handle<Map> instance_map;
1779  if (Map::TryGetObjectCreateMap(broker()->isolate(), object())
1780  .ToHandle(&instance_map)) {
1781  return MapRef(broker(), instance_map);
1782  } else {
1783  return base::Optional<MapRef>();
1784  }
1785  }
1786  MapData* map_data = data()->AsJSObject()->object_create_map();
1787  return map_data != nullptr ? MapRef(broker(), map_data)
1788  : base::Optional<MapRef>();
1789 }
1790 
1791 #define DEF_TESTER(Type, ...) \
1792  bool MapRef::Is##Type##Map() const { \
1793  return InstanceTypeChecker::Is##Type(instance_type()); \
1794  }
1795 INSTANCE_TYPE_CHECKERS(DEF_TESTER)
1796 #undef DEF_TESTER
1797 
1798 base::Optional<MapRef> MapRef::AsElementsKind(ElementsKind kind) const {
1799  if (broker()->mode() == JSHeapBroker::kDisabled) {
1800  AllowHandleAllocation handle_allocation;
1801  AllowHeapAllocation heap_allocation;
1802  AllowHandleDereference allow_handle_dereference;
1803  return MapRef(broker(),
1804  Map::AsElementsKind(broker()->isolate(), object(), kind));
1805  }
1806  if (kind == elements_kind()) return *this;
1807  const ZoneVector<MapData*>& elements_kind_generalizations =
1808  data()->AsMap()->elements_kind_generalizations();
1809  for (auto data : elements_kind_generalizations) {
1810  MapRef map(broker(), data);
1811  if (map.elements_kind() == kind) return map;
1812  }
1813  return base::Optional<MapRef>();
1814 }
1815 
1816 int JSFunctionRef::InitialMapInstanceSizeWithMinSlack() const {
1817  if (broker()->mode() == JSHeapBroker::kDisabled) {
1818  AllowHandleDereference allow_handle_dereference;
1819  AllowHandleAllocation handle_allocation;
1820  return object()->ComputeInstanceSizeWithMinSlack(broker()->isolate());
1821  }
1822  return data()->AsJSFunction()->initial_map_instance_size_with_min_slack();
1823 }
1824 
1825 // Not needed for TypedLowering.
1826 base::Optional<ScriptContextTableRef::LookupResult>
1827 ScriptContextTableRef::lookup(const NameRef& name) const {
1828  AllowHandleAllocation handle_allocation;
1829  AllowHandleDereference handle_dereference;
1830  if (!name.IsString()) return {};
1831  ScriptContextTable::LookupResult lookup_result;
1832  auto table = object();
1833  if (!ScriptContextTable::Lookup(broker()->isolate(), table,
1834  name.AsString().object(), &lookup_result)) {
1835  return {};
1836  }
1837  Handle<Context> script_context = ScriptContextTable::GetContext(
1838  broker()->isolate(), table, lookup_result.context_index);
1839  LookupResult result{ContextRef(broker(), script_context),
1840  lookup_result.mode == VariableMode::kConst,
1841  lookup_result.slot_index};
1842  return result;
1843 }
1844 
1845 OddballType MapRef::oddball_type() const {
1846  if (instance_type() != ODDBALL_TYPE) {
1847  return OddballType::kNone;
1848  }
1849  Factory* f = broker()->isolate()->factory();
1850  if (equals(MapRef(broker(), f->undefined_map()))) {
1851  return OddballType::kUndefined;
1852  }
1853  if (equals(MapRef(broker(), f->null_map()))) {
1854  return OddballType::kNull;
1855  }
1856  if (equals(MapRef(broker(), f->boolean_map()))) {
1857  return OddballType::kBoolean;
1858  }
1859  if (equals(MapRef(broker(), f->the_hole_map()))) {
1860  return OddballType::kHole;
1861  }
1862  if (equals(MapRef(broker(), f->uninitialized_map()))) {
1863  return OddballType::kUninitialized;
1864  }
1865  DCHECK(equals(MapRef(broker(), f->termination_exception_map())) ||
1866  equals(MapRef(broker(), f->arguments_marker_map())) ||
1867  equals(MapRef(broker(), f->optimized_out_map())) ||
1868  equals(MapRef(broker(), f->stale_register_map())));
1869  return OddballType::kOther;
1870 }
1871 
1872 ObjectRef FeedbackVectorRef::get(FeedbackSlot slot) const {
1873  if (broker()->mode() == JSHeapBroker::kDisabled) {
1874  AllowHandleAllocation handle_allocation;
1875  AllowHandleDereference handle_dereference;
1876  Handle<Object> value(object()->Get(slot)->cast<Object>(),
1877  broker()->isolate());
1878  return ObjectRef(broker(), value);
1879  }
1880  int i = FeedbackVector::GetIndex(slot);
1881  return ObjectRef(broker(), data()->AsFeedbackVector()->feedback().at(i));
1882 }
1883 
1884 double JSObjectRef::RawFastDoublePropertyAt(FieldIndex index) const {
1885  if (broker()->mode() == JSHeapBroker::kDisabled) {
1886  AllowHandleDereference handle_dereference;
1887  return object()->RawFastDoublePropertyAt(index);
1888  }
1889  JSObjectData* object_data = data()->AsJSObject();
1890  CHECK(index.is_inobject());
1891  return object_data->GetInobjectField(index.property_index()).AsDouble();
1892 }
1893 
1894 ObjectRef JSObjectRef::RawFastPropertyAt(FieldIndex index) const {
1895  if (broker()->mode() == JSHeapBroker::kDisabled) {
1896  AllowHandleAllocation handle_allocation;
1897  AllowHandleDereference handle_dereference;
1898  return ObjectRef(broker(), handle(object()->RawFastPropertyAt(index),
1899  broker()->isolate()));
1900  }
1901  JSObjectData* object_data = data()->AsJSObject();
1902  CHECK(index.is_inobject());
1903  return ObjectRef(
1904  broker(),
1905  object_data->GetInobjectField(index.property_index()).AsObject());
1906 }
1907 
1908 bool AllocationSiteRef::IsFastLiteral() const {
1909  if (broker()->mode() == JSHeapBroker::kDisabled) {
1910  AllowHeapAllocation allow_heap_allocation; // For TryMigrateInstance.
1911  AllowHandleAllocation allow_handle_allocation;
1912  AllowHandleDereference allow_handle_dereference;
1913  return IsInlinableFastLiteral(
1914  handle(object()->boilerplate(), broker()->isolate()));
1915  }
1916  return data()->AsAllocationSite()->IsFastLiteral();
1917 }
1918 
1919 void JSObjectRef::EnsureElementsTenured() {
1920  if (broker()->mode() == JSHeapBroker::kDisabled) {
1921  AllowHandleAllocation allow_handle_allocation;
1922  AllowHandleDereference allow_handle_dereference;
1923  AllowHeapAllocation allow_heap_allocation;
1924 
1925  Handle<FixedArrayBase> object_elements = elements().object();
1926  if (Heap::InNewSpace(*object_elements)) {
1927  // If we would like to pretenure a fixed cow array, we must ensure that
1928  // the array is already in old space, otherwise we'll create too many
1929  // old-to-new-space pointers (overflowing the store buffer).
1930  object_elements =
1931  broker()->isolate()->factory()->CopyAndTenureFixedCOWArray(
1932  Handle<FixedArray>::cast(object_elements));
1933  object()->set_elements(*object_elements);
1934  }
1935  return;
1936  }
1937  CHECK(data()->AsJSObject()->cow_or_empty_elements_tenured());
1938 }
1939 
1940 FieldIndex MapRef::GetFieldIndexFor(int descriptor_index) const {
1941  if (broker()->mode() == JSHeapBroker::kDisabled) {
1942  AllowHandleDereference allow_handle_dereference;
1943  return FieldIndex::ForDescriptor(*object(), descriptor_index);
1944  }
1945  DescriptorArrayData* descriptors = data()->AsMap()->instance_descriptors();
1946  return descriptors->contents().at(descriptor_index).field_index;
1947 }
1948 
1949 int MapRef::GetInObjectPropertyOffset(int i) const {
1950  if (broker()->mode() == JSHeapBroker::kDisabled) {
1951  AllowHandleDereference allow_handle_dereference;
1952  return object()->GetInObjectPropertyOffset(i);
1953  }
1954  return (GetInObjectPropertiesStartInWords() + i) * kPointerSize;
1955 }
1956 
1957 PropertyDetails MapRef::GetPropertyDetails(int descriptor_index) const {
1958  if (broker()->mode() == JSHeapBroker::kDisabled) {
1959  AllowHandleDereference allow_handle_dereference;
1960  return object()->instance_descriptors()->GetDetails(descriptor_index);
1961  }
1962  DescriptorArrayData* descriptors = data()->AsMap()->instance_descriptors();
1963  return descriptors->contents().at(descriptor_index).details;
1964 }
1965 
1966 NameRef MapRef::GetPropertyKey(int descriptor_index) const {
1967  if (broker()->mode() == JSHeapBroker::kDisabled) {
1968  AllowHandleAllocation handle_allocation;
1969  AllowHandleDereference allow_handle_dereference;
1970  return NameRef(
1971  broker(),
1972  handle(object()->instance_descriptors()->GetKey(descriptor_index),
1973  broker()->isolate()));
1974  }
1975  DescriptorArrayData* descriptors = data()->AsMap()->instance_descriptors();
1976  return NameRef(broker(), descriptors->contents().at(descriptor_index).key);
1977 }
1978 
1979 bool MapRef::IsFixedCowArrayMap() const {
1980  Handle<Map> fixed_cow_array_map =
1981  ReadOnlyRoots(broker()->isolate()).fixed_cow_array_map_handle();
1982  return equals(MapRef(broker(), fixed_cow_array_map));
1983 }
1984 
1985 bool MapRef::IsPrimitiveMap() const {
1986  return instance_type() <= LAST_PRIMITIVE_TYPE;
1987 }
1988 
1989 MapRef MapRef::FindFieldOwner(int descriptor_index) const {
1990  if (broker()->mode() == JSHeapBroker::kDisabled) {
1991  AllowHandleAllocation handle_allocation;
1992  AllowHandleDereference allow_handle_dereference;
1993  Handle<Map> owner(
1994  object()->FindFieldOwner(broker()->isolate(), descriptor_index),
1995  broker()->isolate());
1996  return MapRef(broker(), owner);
1997  }
1998  DescriptorArrayData* descriptors = data()->AsMap()->instance_descriptors();
1999  return MapRef(broker(),
2000  descriptors->contents().at(descriptor_index).field_owner);
2001 }
2002 
2003 ObjectRef MapRef::GetFieldType(int descriptor_index) const {
2004  if (broker()->mode() == JSHeapBroker::kDisabled) {
2005  AllowHandleAllocation handle_allocation;
2006  AllowHandleDereference allow_handle_dereference;
2007  Handle<FieldType> field_type(
2008  object()->instance_descriptors()->GetFieldType(descriptor_index),
2009  broker()->isolate());
2010  return ObjectRef(broker(), field_type);
2011  }
2012  DescriptorArrayData* descriptors = data()->AsMap()->instance_descriptors();
2013  return ObjectRef(broker(),
2014  descriptors->contents().at(descriptor_index).field_type);
2015 }
2016 
2017 bool MapRef::IsUnboxedDoubleField(int descriptor_index) const {
2018  if (broker()->mode() == JSHeapBroker::kDisabled) {
2019  AllowHandleDereference allow_handle_dereference;
2020  return object()->IsUnboxedDoubleField(
2021  FieldIndex::ForDescriptor(*object(), descriptor_index));
2022  }
2023  DescriptorArrayData* descriptors = data()->AsMap()->instance_descriptors();
2024  return descriptors->contents().at(descriptor_index).is_unboxed_double_field;
2025 }
2026 
2027 uint16_t StringRef::GetFirstChar() {
2028  if (broker()->mode() == JSHeapBroker::kDisabled) {
2029  AllowHandleDereference allow_handle_dereference;
2030  return object()->Get(0);
2031  }
2032  return data()->AsString()->first_char();
2033 }
2034 
2035 base::Optional<double> StringRef::ToNumber() {
2036  if (broker()->mode() == JSHeapBroker::kDisabled) {
2037  AllowHandleDereference allow_handle_dereference;
2038  AllowHandleAllocation allow_handle_allocation;
2039  AllowHeapAllocation allow_heap_allocation;
2040  int flags = ALLOW_HEX | ALLOW_OCTAL | ALLOW_BINARY;
2041  return StringToDouble(broker()->isolate(), object(), flags);
2042  }
2043  return data()->AsString()->to_number();
2044 }
2045 
2046 ObjectRef FixedArrayRef::get(int i) const {
2047  if (broker()->mode() == JSHeapBroker::kDisabled) {
2048  AllowHandleAllocation handle_allocation;
2049  AllowHandleDereference allow_handle_dereference;
2050  return ObjectRef(broker(), handle(object()->get(i), broker()->isolate()));
2051  }
2052  return ObjectRef(broker(), data()->AsFixedArray()->Get(i));
2053 }
2054 
2055 bool FixedDoubleArrayRef::is_the_hole(int i) const {
2056  if (broker()->mode() == JSHeapBroker::kDisabled) {
2057  AllowHandleDereference allow_handle_dereference;
2058  return object()->is_the_hole(i);
2059  }
2060  return data()->AsFixedDoubleArray()->Get(i).is_hole_nan();
2061 }
2062 
2063 double FixedDoubleArrayRef::get_scalar(int i) const {
2064  if (broker()->mode() == JSHeapBroker::kDisabled) {
2065  AllowHandleDereference allow_handle_dereference;
2066  return object()->get_scalar(i);
2067  }
2068  CHECK(!data()->AsFixedDoubleArray()->Get(i).is_hole_nan());
2069  return data()->AsFixedDoubleArray()->Get(i).get_scalar();
2070 }
2071 
2072 #define IF_BROKER_DISABLED_ACCESS_HANDLE_C(holder, name) \
2073  if (broker()->mode() == JSHeapBroker::kDisabled) { \
2074  AllowHandleAllocation handle_allocation; \
2075  AllowHandleDereference allow_handle_dereference; \
2076  return object()->name(); \
2077  }
2078 
2079 #define IF_BROKER_DISABLED_ACCESS_HANDLE(holder, result, name) \
2080  if (broker()->mode() == JSHeapBroker::kDisabled) { \
2081  AllowHandleAllocation handle_allocation; \
2082  AllowHandleDereference allow_handle_dereference; \
2083  return result##Ref(broker(), \
2084  handle(object()->name(), broker()->isolate())); \
2085  }
2086 
2087 // Macros for definining a const getter that, depending on the broker mode,
2088 // either looks into the handle or into the serialized data.
2089 #define BIMODAL_ACCESSOR(holder, result, name) \
2090  result##Ref holder##Ref::name() const { \
2091  IF_BROKER_DISABLED_ACCESS_HANDLE(holder, result, name); \
2092  return result##Ref(broker(), ObjectRef::data()->As##holder()->name()); \
2093  }
2094 
2095 // Like above except that the result type is not an XYZRef.
2096 #define BIMODAL_ACCESSOR_C(holder, result, name) \
2097  result holder##Ref::name() const { \
2098  IF_BROKER_DISABLED_ACCESS_HANDLE_C(holder, name); \
2099  return ObjectRef::data()->As##holder()->name(); \
2100  }
2101 
2102 // Like above but for BitFields.
2103 #define BIMODAL_ACCESSOR_B(holder, field, name, BitField) \
2104  typename BitField::FieldType holder##Ref::name() const { \
2105  IF_BROKER_DISABLED_ACCESS_HANDLE_C(holder, name); \
2106  return BitField::decode(ObjectRef::data()->As##holder()->field()); \
2107  }
2108 
2109 BIMODAL_ACCESSOR(AllocationSite, Object, nested_site)
2110 BIMODAL_ACCESSOR_C(AllocationSite, bool, CanInlineCall)
2111 BIMODAL_ACCESSOR_C(AllocationSite, bool, PointsToLiteral)
2112 BIMODAL_ACCESSOR_C(AllocationSite, ElementsKind, GetElementsKind)
2113 BIMODAL_ACCESSOR_C(AllocationSite, PretenureFlag, GetPretenureMode)
2114 
2115 BIMODAL_ACCESSOR_C(BytecodeArray, int, register_count)
2116 
2117 BIMODAL_ACCESSOR(Cell, Object, value)
2118 
2119 BIMODAL_ACCESSOR(HeapObject, Map, map)
2120 
2121 BIMODAL_ACCESSOR(JSArray, Object, length)
2122 
2123 BIMODAL_ACCESSOR(JSBoundFunction, Object, bound_target_function)
2124 BIMODAL_ACCESSOR(JSBoundFunction, Object, bound_this)
2125 BIMODAL_ACCESSOR(JSBoundFunction, FixedArray, bound_arguments)
2126 
2127 BIMODAL_ACCESSOR_C(JSDataView, size_t, byte_length)
2128 BIMODAL_ACCESSOR_C(JSDataView, size_t, byte_offset)
2129 
2130 BIMODAL_ACCESSOR_C(JSFunction, bool, has_prototype)
2131 BIMODAL_ACCESSOR_C(JSFunction, bool, has_initial_map)
2132 BIMODAL_ACCESSOR_C(JSFunction, bool, PrototypeRequiresRuntimeLookup)
2133 BIMODAL_ACCESSOR(JSFunction, Context, context)
2134 BIMODAL_ACCESSOR(JSFunction, NativeContext, native_context)
2135 BIMODAL_ACCESSOR(JSFunction, Map, initial_map)
2136 BIMODAL_ACCESSOR(JSFunction, Object, prototype)
2137 BIMODAL_ACCESSOR(JSFunction, SharedFunctionInfo, shared)
2138 
2139 BIMODAL_ACCESSOR_C(JSTypedArray, bool, is_on_heap)
2140 BIMODAL_ACCESSOR_C(JSTypedArray, size_t, length_value)
2141 BIMODAL_ACCESSOR(JSTypedArray, HeapObject, buffer)
2142 
2143 BIMODAL_ACCESSOR_B(Map, bit_field2, elements_kind, Map::ElementsKindBits)
2144 BIMODAL_ACCESSOR_B(Map, bit_field2, is_extensible, Map::IsExtensibleBit)
2145 BIMODAL_ACCESSOR_B(Map, bit_field3, is_deprecated, Map::IsDeprecatedBit)
2146 BIMODAL_ACCESSOR_B(Map, bit_field3, is_dictionary_map, Map::IsDictionaryMapBit)
2147 BIMODAL_ACCESSOR_B(Map, bit_field3, NumberOfOwnDescriptors,
2148  Map::NumberOfOwnDescriptorsBits)
2149 BIMODAL_ACCESSOR_B(Map, bit_field3, has_hidden_prototype,
2150  Map::HasHiddenPrototypeBit)
2151 BIMODAL_ACCESSOR_B(Map, bit_field, has_prototype_slot, Map::HasPrototypeSlotBit)
2152 BIMODAL_ACCESSOR_B(Map, bit_field, is_access_check_needed,
2153  Map::IsAccessCheckNeededBit)
2154 BIMODAL_ACCESSOR_B(Map, bit_field, is_callable, Map::IsCallableBit)
2155 BIMODAL_ACCESSOR_B(Map, bit_field, is_constructor, Map::IsConstructorBit)
2156 BIMODAL_ACCESSOR_B(Map, bit_field, is_undetectable, Map::IsUndetectableBit)
2157 BIMODAL_ACCESSOR_C(Map, int, instance_size)
2158 BIMODAL_ACCESSOR(Map, Object, prototype)
2159 BIMODAL_ACCESSOR_C(Map, InstanceType, instance_type)
2160 BIMODAL_ACCESSOR(Map, Object, GetConstructor)
2161 
2162 #define DEF_NATIVE_CONTEXT_ACCESSOR(type, name) \
2163  BIMODAL_ACCESSOR(NativeContext, type, name)
2164 BROKER_NATIVE_CONTEXT_FIELDS(DEF_NATIVE_CONTEXT_ACCESSOR)
2165 #undef DEF_NATIVE_CONTEXT_ACCESSOR
2166 
2167 BIMODAL_ACCESSOR(PropertyCell, Object, value)
2168 BIMODAL_ACCESSOR_C(PropertyCell, PropertyDetails, property_details)
2169 
2170 BIMODAL_ACCESSOR_C(SharedFunctionInfo, int, builtin_id)
2171 BIMODAL_ACCESSOR(SharedFunctionInfo, BytecodeArray, GetBytecodeArray)
2172 #define DEF_SFI_ACCESSOR(type, name) \
2173  BIMODAL_ACCESSOR_C(SharedFunctionInfo, type, name)
2174 BROKER_SFI_FIELDS(DEF_SFI_ACCESSOR)
2175 #undef DEF_SFI_ACCESSOR
2176 
2177 BIMODAL_ACCESSOR_C(String, int, length)
2178 
2179 void* JSTypedArrayRef::elements_external_pointer() const {
2180  if (broker()->mode() == JSHeapBroker::kDisabled) {
2181  AllowHandleDereference allow_handle_dereference;
2182  return FixedTypedArrayBase::cast(object()->elements())->external_pointer();
2183  }
2184  return data()->AsJSTypedArray()->elements_external_pointer();
2185 }
2186 
2187 bool MapRef::IsInobjectSlackTrackingInProgress() const {
2188  IF_BROKER_DISABLED_ACCESS_HANDLE_C(Map, IsInobjectSlackTrackingInProgress);
2189  return Map::ConstructionCounterBits::decode(data()->AsMap()->bit_field3()) !=
2190  Map::kNoSlackTracking;
2191 }
2192 
2193 int MapRef::constructor_function_index() const {
2194  IF_BROKER_DISABLED_ACCESS_HANDLE_C(Map, GetConstructorFunctionIndex);
2195  CHECK(IsPrimitiveMap());
2196  return data()->AsMap()->constructor_function_index();
2197 }
2198 
2199 bool MapRef::is_stable() const {
2200  IF_BROKER_DISABLED_ACCESS_HANDLE_C(Map, is_stable);
2201  return !Map::IsUnstableBit::decode(data()->AsMap()->bit_field3());
2202 }
2203 
2204 bool MapRef::CanBeDeprecated() const {
2205  IF_BROKER_DISABLED_ACCESS_HANDLE_C(Map, CanBeDeprecated);
2206  CHECK_GT(NumberOfOwnDescriptors(), 0);
2207  return data()->AsMap()->can_be_deprecated();
2208 }
2209 
2210 bool MapRef::CanTransition() const {
2211  IF_BROKER_DISABLED_ACCESS_HANDLE_C(Map, CanTransition);
2212  return data()->AsMap()->can_transition();
2213 }
2214 
2215 int MapRef::GetInObjectPropertiesStartInWords() const {
2216  IF_BROKER_DISABLED_ACCESS_HANDLE_C(Map, GetInObjectPropertiesStartInWords);
2217  return data()->AsMap()->in_object_properties_start_in_words();
2218 }
2219 
2220 int MapRef::GetInObjectProperties() const {
2221  IF_BROKER_DISABLED_ACCESS_HANDLE_C(Map, GetInObjectProperties);
2222  return data()->AsMap()->in_object_properties();
2223 }
2224 
2225 int ScopeInfoRef::ContextLength() const {
2226  IF_BROKER_DISABLED_ACCESS_HANDLE_C(ScopeInfo, ContextLength);
2227  return data()->AsScopeInfo()->context_length();
2228 }
2229 
2230 bool StringRef::IsExternalString() const {
2231  IF_BROKER_DISABLED_ACCESS_HANDLE_C(String, IsExternalString);
2232  return data()->AsString()->is_external_string();
2233 }
2234 
2235 bool StringRef::IsSeqString() const {
2236  IF_BROKER_DISABLED_ACCESS_HANDLE_C(String, IsSeqString);
2237  return data()->AsString()->is_seq_string();
2238 }
2239 
2240 MapRef NativeContextRef::GetFunctionMapFromIndex(int index) const {
2241  DCHECK_GE(index, Context::FIRST_FUNCTION_MAP_INDEX);
2242  DCHECK_LE(index, Context::LAST_FUNCTION_MAP_INDEX);
2243  if (broker()->mode() == JSHeapBroker::kDisabled) {
2244  return get(index).AsMap();
2245  }
2246  return MapRef(broker(), data()->AsNativeContext()->function_maps().at(
2247  index - Context::FIRST_FUNCTION_MAP_INDEX));
2248 }
2249 
2250 MapRef NativeContextRef::GetInitialJSArrayMap(ElementsKind kind) const {
2251  switch (kind) {
2252  case PACKED_SMI_ELEMENTS:
2253  return js_array_packed_smi_elements_map();
2254  case HOLEY_SMI_ELEMENTS:
2255  return js_array_holey_smi_elements_map();
2256  case PACKED_DOUBLE_ELEMENTS:
2257  return js_array_packed_double_elements_map();
2258  case HOLEY_DOUBLE_ELEMENTS:
2259  return js_array_holey_double_elements_map();
2260  case PACKED_ELEMENTS:
2261  return js_array_packed_elements_map();
2262  case HOLEY_ELEMENTS:
2263  return js_array_holey_elements_map();
2264  default:
2265  UNREACHABLE();
2266  }
2267 }
2268 
2269 base::Optional<JSFunctionRef> NativeContextRef::GetConstructorFunction(
2270  const MapRef& map) const {
2271  CHECK(map.IsPrimitiveMap());
2272  switch (map.constructor_function_index()) {
2273  case Map::kNoConstructorFunctionIndex:
2274  return base::nullopt;
2275  case Context::BIGINT_FUNCTION_INDEX:
2276  return bigint_function();
2277  case Context::BOOLEAN_FUNCTION_INDEX:
2278  return boolean_function();
2279  case Context::NUMBER_FUNCTION_INDEX:
2280  return number_function();
2281  case Context::STRING_FUNCTION_INDEX:
2282  return string_function();
2283  case Context::SYMBOL_FUNCTION_INDEX:
2284  return symbol_function();
2285  default:
2286  UNREACHABLE();
2287  }
2288 }
2289 
2290 bool ObjectRef::IsNullOrUndefined() const {
2291  if (IsSmi()) return false;
2292  OddballType type = AsHeapObject().map().oddball_type();
2293  return type == OddballType::kNull || type == OddballType::kUndefined;
2294 }
2295 
2296 bool ObjectRef::BooleanValue() const {
2297  if (broker()->mode() == JSHeapBroker::kDisabled) {
2298  AllowHandleDereference allow_handle_dereference;
2299  return object()->BooleanValue(broker()->isolate());
2300  }
2301  return IsSmi() ? (AsSmi() != 0) : data()->AsHeapObject()->boolean_value();
2302 }
2303 
2304 double ObjectRef::OddballToNumber() const {
2305  OddballType type = AsHeapObject().map().oddball_type();
2306 
2307  switch (type) {
2308  case OddballType::kBoolean: {
2309  ObjectRef true_ref(broker(),
2310  broker()->isolate()->factory()->true_value());
2311  return this->equals(true_ref) ? 1 : 0;
2312  break;
2313  }
2314  case OddballType::kUndefined: {
2315  return std::numeric_limits<double>::quiet_NaN();
2316  break;
2317  }
2318  case OddballType::kNull: {
2319  return 0;
2320  break;
2321  }
2322  default: {
2323  UNREACHABLE();
2324  break;
2325  }
2326  }
2327 }
2328 
2329 double HeapNumberRef::value() const {
2330  IF_BROKER_DISABLED_ACCESS_HANDLE_C(HeapNumber, value);
2331  return data()->AsHeapNumber()->value();
2332 }
2333 
2334 double MutableHeapNumberRef::value() const {
2335  IF_BROKER_DISABLED_ACCESS_HANDLE_C(MutableHeapNumber, value);
2336  return data()->AsMutableHeapNumber()->value();
2337 }
2338 
2339 CellRef ModuleRef::GetCell(int cell_index) const {
2340  if (broker()->mode() == JSHeapBroker::kDisabled) {
2341  AllowHandleAllocation handle_allocation;
2342  AllowHandleDereference allow_handle_dereference;
2343  return CellRef(broker(),
2344  handle(object()->GetCell(cell_index), broker()->isolate()));
2345  }
2346  return CellRef(broker(), data()->AsModule()->GetCell(cell_index));
2347 }
2348 
2349 ObjectRef::ObjectRef(JSHeapBroker* broker, Handle<Object> object)
2350  : broker_(broker) {
2351  switch (broker->mode()) {
2352  case JSHeapBroker::kSerialized:
2353  data_ = broker->GetData(object);
2354  break;
2355  case JSHeapBroker::kSerializing:
2356  data_ = broker->GetOrCreateData(object);
2357  break;
2358  case JSHeapBroker::kDisabled: {
2359  RefsMap::Entry* entry =
2360  broker->refs_->LookupOrInsert(object.address(), broker->zone());
2361  ObjectData** storage = &(entry->value);
2362  if (*storage == nullptr) {
2363  AllowHandleDereference handle_dereference;
2364  entry->value = new (broker->zone())
2365  ObjectData(broker, storage, object,
2366  object->IsSmi() ? kSmi : kUnserializedHeapObject);
2367  }
2368  data_ = *storage;
2369  break;
2370  }
2371  case JSHeapBroker::kRetired:
2372  UNREACHABLE();
2373  }
2374  CHECK_NOT_NULL(data_);
2375 }
2376 
2377 namespace {
2378 OddballType GetOddballType(Isolate* isolate, Map map) {
2379  if (map->instance_type() != ODDBALL_TYPE) {
2380  return OddballType::kNone;
2381  }
2382  ReadOnlyRoots roots(isolate);
2383  if (map == roots.undefined_map()) {
2384  return OddballType::kUndefined;
2385  }
2386  if (map == roots.null_map()) {
2387  return OddballType::kNull;
2388  }
2389  if (map == roots.boolean_map()) {
2390  return OddballType::kBoolean;
2391  }
2392  if (map == roots.the_hole_map()) {
2393  return OddballType::kHole;
2394  }
2395  if (map == roots.uninitialized_map()) {
2396  return OddballType::kUninitialized;
2397  }
2398  DCHECK(map == roots.termination_exception_map() ||
2399  map == roots.arguments_marker_map() ||
2400  map == roots.optimized_out_map() || map == roots.stale_register_map());
2401  return OddballType::kOther;
2402 }
2403 } // namespace
2404 
2405 HeapObjectType HeapObjectRef::GetHeapObjectType() const {
2406  if (broker()->mode() == JSHeapBroker::kDisabled) {
2407  AllowHandleDereference handle_dereference;
2408  Map map = Handle<HeapObject>::cast(object())->map();
2409  HeapObjectType::Flags flags(0);
2410  if (map->is_undetectable()) flags |= HeapObjectType::kUndetectable;
2411  if (map->is_callable()) flags |= HeapObjectType::kCallable;
2412  return HeapObjectType(map->instance_type(), flags,
2413  GetOddballType(broker()->isolate(), map));
2414  }
2415  HeapObjectType::Flags flags(0);
2416  if (map().is_undetectable()) flags |= HeapObjectType::kUndetectable;
2417  if (map().is_callable()) flags |= HeapObjectType::kCallable;
2418  return HeapObjectType(map().instance_type(), flags, map().oddball_type());
2419 }
2420 base::Optional<JSObjectRef> AllocationSiteRef::boilerplate() const {
2421  if (broker()->mode() == JSHeapBroker::kDisabled) {
2422  AllowHandleAllocation handle_allocation;
2423  AllowHandleDereference allow_handle_dereference;
2424  return JSObjectRef(broker(),
2425  handle(object()->boilerplate(), broker()->isolate()));
2426  }
2427  JSObjectData* boilerplate = data()->AsAllocationSite()->boilerplate();
2428  if (boilerplate) {
2429  return JSObjectRef(broker(), boilerplate);
2430  } else {
2431  return base::nullopt;
2432  }
2433 }
2434 
2435 ElementsKind JSObjectRef::GetElementsKind() const {
2436  return map().elements_kind();
2437 }
2438 
2439 FixedArrayBaseRef JSObjectRef::elements() const {
2440  if (broker()->mode() == JSHeapBroker::kDisabled) {
2441  AllowHandleAllocation handle_allocation;
2442  AllowHandleDereference allow_handle_dereference;
2443  return FixedArrayBaseRef(broker(),
2444  handle(object()->elements(), broker()->isolate()));
2445  }
2446  return FixedArrayBaseRef(broker(), data()->AsJSObject()->elements());
2447 }
2448 
2449 int FixedArrayBaseRef::length() const {
2450  IF_BROKER_DISABLED_ACCESS_HANDLE_C(FixedArrayBase, length);
2451  return data()->AsFixedArrayBase()->length();
2452 }
2453 
2454 ObjectData* FixedArrayData::Get(int i) const {
2455  CHECK_LT(i, static_cast<int>(contents_.size()));
2456  CHECK_NOT_NULL(contents_[i]);
2457  return contents_[i];
2458 }
2459 
2460 Float64 FixedDoubleArrayData::Get(int i) const {
2461  CHECK_LT(i, static_cast<int>(contents_.size()));
2462  return contents_[i];
2463 }
2464 
2465 void FeedbackVectorRef::SerializeSlots() {
2466  data()->AsFeedbackVector()->SerializeSlots(broker());
2467 }
2468 
2469 ObjectRef JSRegExpRef::data() const {
2470  IF_BROKER_DISABLED_ACCESS_HANDLE(JSRegExp, Object, data);
2471  return ObjectRef(broker(), ObjectRef::data()->AsJSRegExp()->data());
2472 }
2473 
2474 ObjectRef JSRegExpRef::flags() const {
2475  IF_BROKER_DISABLED_ACCESS_HANDLE(JSRegExp, Object, flags);
2476  return ObjectRef(broker(), ObjectRef::data()->AsJSRegExp()->flags());
2477 }
2478 
2479 ObjectRef JSRegExpRef::last_index() const {
2480  IF_BROKER_DISABLED_ACCESS_HANDLE(JSRegExp, Object, last_index);
2481  return ObjectRef(broker(), ObjectRef::data()->AsJSRegExp()->last_index());
2482 }
2483 
2484 ObjectRef JSRegExpRef::raw_properties_or_hash() const {
2485  IF_BROKER_DISABLED_ACCESS_HANDLE(JSRegExp, Object, raw_properties_or_hash);
2486  return ObjectRef(broker(),
2487  ObjectRef::data()->AsJSRegExp()->raw_properties_or_hash());
2488 }
2489 
2490 ObjectRef JSRegExpRef::source() const {
2491  IF_BROKER_DISABLED_ACCESS_HANDLE(JSRegExp, Object, source);
2492  return ObjectRef(broker(), ObjectRef::data()->AsJSRegExp()->source());
2493 }
2494 
2495 Handle<Object> ObjectRef::object() const { return data_->object(); }
2496 
2497 #define DEF_OBJECT_GETTER(T) \
2498  Handle<T> T##Ref::object() const { \
2499  return Handle<T>(reinterpret_cast<Address*>(data_->object().address())); \
2500  }
2501 HEAP_BROKER_OBJECT_LIST(DEF_OBJECT_GETTER)
2502 #undef DEF_OBJECT_GETTER
2503 
2504 JSHeapBroker* ObjectRef::broker() const { return broker_; }
2505 
2506 ObjectData* ObjectRef::data() const {
2507  switch (broker()->mode()) {
2508  case JSHeapBroker::kDisabled:
2509  CHECK_NE(data_->kind(), kSerializedHeapObject);
2510  return data_;
2511  case JSHeapBroker::kSerializing:
2512  case JSHeapBroker::kSerialized:
2513  CHECK_NE(data_->kind(), kUnserializedHeapObject);
2514  return data_;
2515  case JSHeapBroker::kRetired:
2516  UNREACHABLE();
2517  }
2518 }
2519 
2520 Reduction NoChangeBecauseOfMissingData(JSHeapBroker* broker,
2521  const char* function, int line) {
2522  if (FLAG_trace_heap_broker) {
2523  PrintF("[%p] Skipping optimization in %s at line %d due to missing data\n",
2524  broker, function, line);
2525  }
2526  return AdvancedReducer::NoChange();
2527 }
2528 
2529 NativeContextData::NativeContextData(JSHeapBroker* broker, ObjectData** storage,
2530  Handle<NativeContext> object)
2531  : ContextData(broker, storage, object), function_maps_(broker->zone()) {}
2532 
2533 void NativeContextData::Serialize(JSHeapBroker* broker) {
2534  if (serialized_) return;
2535  serialized_ = true;
2536 
2537  TraceScope tracer(broker, this, "NativeContextData::Serialize");
2538  Handle<NativeContext> context = Handle<NativeContext>::cast(object());
2539 
2540 #define SERIALIZE_MEMBER(type, name) \
2541  DCHECK_NULL(name##_); \
2542  name##_ = broker->GetOrCreateData(context->name())->As##type(); \
2543  if (name##_->IsJSFunction()) name##_->AsJSFunction()->Serialize(broker); \
2544  if (name##_->IsMap()) name##_->AsMap()->SerializeConstructor(broker);
2545  BROKER_COMPULSORY_NATIVE_CONTEXT_FIELDS(SERIALIZE_MEMBER)
2546  if (!broker->isolate()->bootstrapper()->IsActive()) {
2547  BROKER_OPTIONAL_NATIVE_CONTEXT_FIELDS(SERIALIZE_MEMBER)
2548  }
2549 #undef SERIALIZE_MEMBER
2550 
2551  bound_function_with_constructor_map_->SerializePrototype(broker);
2552  bound_function_without_constructor_map_->SerializePrototype(broker);
2553 
2554  DCHECK(function_maps_.empty());
2555  int const first = Context::FIRST_FUNCTION_MAP_INDEX;
2556  int const last = Context::LAST_FUNCTION_MAP_INDEX;
2557  function_maps_.reserve(last + 1 - first);
2558  for (int i = first; i <= last; ++i) {
2559  function_maps_.push_back(broker->GetOrCreateData(context->get(i))->AsMap());
2560  }
2561 }
2562 
2563 void JSFunctionRef::Serialize() {
2564  if (broker()->mode() == JSHeapBroker::kDisabled) return;
2565  CHECK_EQ(broker()->mode(), JSHeapBroker::kSerializing);
2566  data()->AsJSFunction()->Serialize(broker());
2567 }
2568 
2569 void JSObjectRef::SerializeObjectCreateMap() {
2570  if (broker()->mode() == JSHeapBroker::kDisabled) return;
2571  CHECK_EQ(broker()->mode(), JSHeapBroker::kSerializing);
2572  data()->AsJSObject()->SerializeObjectCreateMap(broker());
2573 }
2574 
2575 void MapRef::SerializeOwnDescriptors() {
2576  if (broker()->mode() == JSHeapBroker::kDisabled) return;
2577  CHECK_EQ(broker()->mode(), JSHeapBroker::kSerializing);
2578  data()->AsMap()->SerializeOwnDescriptors(broker());
2579 }
2580 
2581 void MapRef::SerializePrototype() {
2582  if (broker()->mode() == JSHeapBroker::kDisabled) return;
2583  CHECK_EQ(broker()->mode(), JSHeapBroker::kSerializing);
2584  data()->AsMap()->SerializePrototype(broker());
2585 }
2586 
2587 void ModuleRef::Serialize() {
2588  if (broker()->mode() == JSHeapBroker::kDisabled) return;
2589  CHECK_EQ(broker()->mode(), JSHeapBroker::kSerializing);
2590  data()->AsModule()->Serialize(broker());
2591 }
2592 
2593 void ContextRef::Serialize() {
2594  if (broker()->mode() == JSHeapBroker::kDisabled) return;
2595  CHECK_EQ(broker()->mode(), JSHeapBroker::kSerializing);
2596  data()->AsContext()->Serialize(broker());
2597 }
2598 
2599 void NativeContextRef::Serialize() {
2600  if (broker()->mode() == JSHeapBroker::kDisabled) return;
2601  CHECK_EQ(broker()->mode(), JSHeapBroker::kSerializing);
2602  data()->AsNativeContext()->Serialize(broker());
2603 }
2604 
2605 void JSTypedArrayRef::Serialize() {
2606  if (broker()->mode() == JSHeapBroker::kDisabled) return;
2607  CHECK_EQ(broker()->mode(), JSHeapBroker::kSerializing);
2608  data()->AsJSTypedArray()->Serialize(broker());
2609 }
2610 
2611 void JSBoundFunctionRef::Serialize() {
2612  if (broker()->mode() == JSHeapBroker::kDisabled) return;
2613  CHECK_EQ(broker()->mode(), JSHeapBroker::kSerializing);
2614  data()->AsJSBoundFunction()->Serialize(broker());
2615 }
2616 
2617 #undef BIMODAL_ACCESSOR
2618 #undef BIMODAL_ACCESSOR_B
2619 #undef BIMODAL_ACCESSOR_C
2620 #undef IF_BROKER_DISABLED_ACCESS_HANDLE
2621 #undef IF_BROKER_DISABLED_ACCESS_HANDLE_C
2622 
2623 } // namespace compiler
2624 } // namespace internal
2625 } // namespace v8
Definition: v8.h:85
Definition: libplatform.h:13