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