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