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