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