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 : #ifdef ENABLE_SLOW_DCHECKS
8 : #include <algorithm>
9 : #endif
10 :
11 : #include "src/api-inl.h"
12 : #include "src/ast/modules.h"
13 : #include "src/bootstrapper.h"
14 : #include "src/boxed-float.h"
15 : #include "src/code-factory.h"
16 : #include "src/compiler/graph-reducer.h"
17 : #include "src/compiler/per-isolate-compiler-cache.h"
18 : #include "src/objects-inl.h"
19 : #include "src/objects/allocation-site-inl.h"
20 : #include "src/objects/api-callbacks.h"
21 : #include "src/objects/cell-inl.h"
22 : #include "src/objects/heap-number-inl.h"
23 : #include "src/objects/instance-type-inl.h"
24 : #include "src/objects/js-array-buffer-inl.h"
25 : #include "src/objects/js-array-inl.h"
26 : #include "src/objects/js-regexp-inl.h"
27 : #include "src/objects/module-inl.h"
28 : #include "src/objects/templates.h"
29 : #include "src/utils.h"
30 : #include "src/vector-slot-pair.h"
31 :
32 : namespace v8 {
33 : namespace internal {
34 : namespace compiler {
35 :
36 : #define TRACE(broker, x) TRACE_BROKER(broker, x)
37 : #define TRACE_MISSING(broker, x) TRACE_BROKER_MISSING(broker, x)
38 :
39 : #define FORWARD_DECL(Name) class Name##Data;
40 : HEAP_BROKER_OBJECT_LIST(FORWARD_DECL)
41 : #undef FORWARD_DECL
42 :
43 : // There are three kinds of ObjectData values.
44 : //
45 : // kSmi: The underlying V8 object is a Smi and the data is an instance of the
46 : // base class (ObjectData), i.e. it's basically just the handle. Because the
47 : // object is a Smi, it's safe to access the handle in order to extract the
48 : // number value, and AsSmi() does exactly that.
49 : //
50 : // kSerializedHeapObject: The underlying V8 object is a HeapObject and the
51 : // data is an instance of the corresponding (most-specific) subclass, e.g.
52 : // JSFunctionData, which provides serialized information about the object.
53 : //
54 : // kUnserializedHeapObject: The underlying V8 object is a HeapObject and the
55 : // data is an instance of the base class (ObjectData), i.e. it basically
56 : // carries no information other than the handle.
57 : //
58 : enum ObjectDataKind { kSmi, kSerializedHeapObject, kUnserializedHeapObject };
59 :
60 : class ObjectData : public ZoneObject {
61 : public:
62 94250924 : ObjectData(JSHeapBroker* broker, ObjectData** storage, Handle<Object> object,
63 : ObjectDataKind kind)
64 94250924 : : object_(object), kind_(kind) {
65 : // This assignment ensures we don't end up inserting the same object
66 : // in an endless recursion.
67 94250924 : *storage = this;
68 :
69 94250924 : TRACE(broker, "Creating data " << this << " for handle " << object.address()
70 : << " (" << Brief(*object) << ")");
71 :
72 94250924 : CHECK_NOT_NULL(broker->isolate()->handle_scope_data()->canonical_scope);
73 94250924 : }
74 :
75 : #define DECLARE_IS_AND_AS(Name) \
76 : bool Is##Name() const; \
77 : Name##Data* As##Name();
78 : HEAP_BROKER_OBJECT_LIST(DECLARE_IS_AND_AS)
79 : #undef DECLARE_IS_AND_AS
80 :
81 : Handle<Object> object() const { return object_; }
82 : ObjectDataKind kind() const { return kind_; }
83 12631612 : bool is_smi() const { return kind_ == kSmi; }
84 :
85 : private:
86 : Handle<Object> const object_;
87 : ObjectDataKind const kind_;
88 : };
89 :
90 : class HeapObjectData : public ObjectData {
91 : public:
92 : HeapObjectData(JSHeapBroker* broker, ObjectData** storage,
93 : Handle<HeapObject> object);
94 :
95 : bool boolean_value() const { return boolean_value_; }
96 : MapData* map() const { return map_; }
97 :
98 : static HeapObjectData* Serialize(JSHeapBroker* broker,
99 : Handle<HeapObject> object);
100 :
101 : private:
102 : bool const boolean_value_;
103 : MapData* const map_;
104 : };
105 :
106 : class PropertyCellData : public HeapObjectData {
107 : public:
108 : PropertyCellData(JSHeapBroker* broker, ObjectData** storage,
109 : Handle<PropertyCell> object);
110 :
111 : PropertyDetails property_details() const { return property_details_; }
112 :
113 : void Serialize(JSHeapBroker* broker);
114 : ObjectData* value() const { return value_; }
115 :
116 : private:
117 : PropertyDetails const property_details_;
118 :
119 : bool serialized_ = false;
120 : ObjectData* value_ = nullptr;
121 : };
122 :
123 : class FunctionTemplateInfoData : public HeapObjectData {
124 : public:
125 : FunctionTemplateInfoData(JSHeapBroker* broker, ObjectData** storage,
126 : Handle<FunctionTemplateInfo> object);
127 :
128 : void Serialize(JSHeapBroker* broker);
129 : ObjectData* call_code() const { return call_code_; }
130 :
131 : private:
132 : bool serialized_ = false;
133 : ObjectData* call_code_ = nullptr;
134 : };
135 :
136 : class CallHandlerInfoData : public HeapObjectData {
137 : public:
138 : CallHandlerInfoData(JSHeapBroker* broker, ObjectData** storage,
139 : Handle<CallHandlerInfo> object);
140 :
141 : Address callback() const { return callback_; }
142 :
143 : void Serialize(JSHeapBroker* broker);
144 : ObjectData* data() const { return data_; }
145 :
146 : private:
147 : Address const callback_;
148 :
149 : bool serialized_ = false;
150 : ObjectData* data_ = nullptr;
151 : };
152 :
153 128 : FunctionTemplateInfoData::FunctionTemplateInfoData(
154 : JSHeapBroker* broker, ObjectData** storage,
155 : Handle<FunctionTemplateInfo> object)
156 128 : : HeapObjectData(broker, storage, object) {}
157 :
158 0 : CallHandlerInfoData::CallHandlerInfoData(JSHeapBroker* broker,
159 : ObjectData** storage,
160 : Handle<CallHandlerInfo> object)
161 : : HeapObjectData(broker, storage, object),
162 0 : callback_(v8::ToCData<Address>(object->callback())) {}
163 :
164 29200642 : void JSHeapBroker::IncrementTracingIndentation() { ++trace_indentation_; }
165 :
166 29200774 : void JSHeapBroker::DecrementTracingIndentation() { --trace_indentation_; }
167 :
168 : class TraceScope {
169 : public:
170 : TraceScope(JSHeapBroker* broker, const char* label)
171 479036 : : TraceScope(broker, static_cast<void*>(broker), label) {}
172 :
173 : TraceScope(JSHeapBroker* broker, ObjectData* data, const char* label)
174 28721742 : : TraceScope(broker, static_cast<void*>(data), label) {}
175 :
176 58400037 : ~TraceScope() { broker_->DecrementTracingIndentation(); }
177 :
178 : private:
179 : JSHeapBroker* const broker_;
180 :
181 29200642 : TraceScope(JSHeapBroker* broker, void* self, const char* label)
182 29200642 : : broker_(broker) {
183 29200642 : TRACE(broker_, "Running " << label << " on " << self);
184 29200642 : broker_->IncrementTracingIndentation();
185 29200642 : }
186 : };
187 :
188 3259151 : PropertyCellData::PropertyCellData(JSHeapBroker* broker, ObjectData** storage,
189 : Handle<PropertyCell> object)
190 : : HeapObjectData(broker, storage, object),
191 6518296 : property_details_(object->property_details()) {}
192 :
193 3248788 : void PropertyCellData::Serialize(JSHeapBroker* broker) {
194 3248788 : if (serialized_) return;
195 3248788 : serialized_ = true;
196 :
197 3248788 : TraceScope tracer(broker, this, "PropertyCellData::Serialize");
198 : auto cell = Handle<PropertyCell>::cast(object());
199 : DCHECK_NULL(value_);
200 3248789 : value_ = broker->GetOrCreateData(cell->value());
201 : }
202 :
203 0 : void FunctionTemplateInfoData::Serialize(JSHeapBroker* broker) {
204 0 : if (serialized_) return;
205 0 : serialized_ = true;
206 :
207 0 : TraceScope tracer(broker, this, "FunctionTemplateInfoData::Serialize");
208 : auto function_template_info = Handle<FunctionTemplateInfo>::cast(object());
209 : DCHECK_NULL(call_code_);
210 0 : call_code_ = broker->GetOrCreateData(function_template_info->call_code());
211 :
212 0 : if (call_code_->IsCallHandlerInfo()) {
213 0 : call_code_->AsCallHandlerInfo()->Serialize(broker);
214 : }
215 : }
216 :
217 0 : void CallHandlerInfoData::Serialize(JSHeapBroker* broker) {
218 0 : if (serialized_) return;
219 0 : serialized_ = true;
220 :
221 0 : TraceScope tracer(broker, this, "CallHandlerInfoData::Serialize");
222 : auto call_handler_info = Handle<CallHandlerInfo>::cast(object());
223 : DCHECK_NULL(data_);
224 0 : data_ = broker->GetOrCreateData(call_handler_info->data());
225 : }
226 :
227 : class JSObjectField {
228 : public:
229 : bool IsDouble() const { return object_ == nullptr; }
230 : double AsDouble() const {
231 128 : CHECK(IsDouble());
232 128 : return number_;
233 : }
234 :
235 : bool IsObject() const { return object_ != nullptr; }
236 : ObjectData* AsObject() const {
237 3202 : CHECK(IsObject());
238 : return object_;
239 : }
240 :
241 128 : explicit JSObjectField(double value) : number_(value) {}
242 2735 : explicit JSObjectField(ObjectData* value) : object_(value) {}
243 :
244 : private:
245 : ObjectData* object_ = nullptr;
246 : double number_ = 0;
247 : };
248 :
249 : class JSObjectData : public HeapObjectData {
250 : public:
251 : JSObjectData(JSHeapBroker* broker, ObjectData** storage,
252 : Handle<JSObject> object);
253 :
254 : // Recursive serialization of all reachable JSObjects.
255 : void SerializeAsBoilerplate(JSHeapBroker* broker);
256 : const JSObjectField& GetInobjectField(int property_index) const;
257 :
258 : // Shallow serialization of {elements}.
259 : void SerializeElements(JSHeapBroker* broker);
260 : bool serialized_elements() const { return serialized_elements_; }
261 : FixedArrayBaseData* elements() const;
262 :
263 : void SerializeObjectCreateMap(JSHeapBroker* broker);
264 : MapData* object_create_map() const { // Can be nullptr.
265 16 : CHECK(serialized_object_create_map_);
266 16 : return object_create_map_;
267 : }
268 :
269 : ObjectData* GetOwnConstantElement(JSHeapBroker* broker, uint32_t index,
270 : bool serialize);
271 :
272 : // This method is only used to assert our invariants.
273 : bool cow_or_empty_elements_tenured() const;
274 :
275 : private:
276 : void SerializeRecursive(JSHeapBroker* broker, int max_depths);
277 :
278 : FixedArrayBaseData* elements_ = nullptr;
279 : bool cow_or_empty_elements_tenured_ = false;
280 : // The {serialized_as_boilerplate} flag is set when all recursively
281 : // reachable JSObjects are serialized.
282 : bool serialized_as_boilerplate_ = false;
283 : bool serialized_elements_ = false;
284 :
285 : ZoneVector<JSObjectField> inobject_fields_;
286 :
287 : bool serialized_object_create_map_ = false;
288 : MapData* object_create_map_ = nullptr;
289 :
290 : // Elements (indexed properties) that either
291 : // (1) are known to exist directly on the object as non-writable and
292 : // non-configurable, or (2) are known not to (possibly they don't exist at
293 : // all). In case (2), the second pair component is nullptr.
294 : ZoneVector<std::pair<uint32_t, ObjectData*>> own_constant_elements_;
295 : };
296 :
297 1141482 : void JSObjectData::SerializeObjectCreateMap(JSHeapBroker* broker) {
298 1663039 : if (serialized_object_create_map_) return;
299 619925 : serialized_object_create_map_ = true;
300 :
301 619925 : TraceScope tracer(broker, this, "JSObjectData::SerializeObjectCreateMap");
302 : Handle<JSObject> jsobject = Handle<JSObject>::cast(object());
303 :
304 619925 : if (jsobject->map()->is_prototype_map()) {
305 : Handle<Object> maybe_proto_info(jsobject->map()->prototype_info(),
306 : broker->isolate());
307 10482 : if (maybe_proto_info->IsPrototypeInfo()) {
308 : auto proto_info = Handle<PrototypeInfo>::cast(maybe_proto_info);
309 3301 : if (proto_info->HasObjectCreateMap()) {
310 : DCHECK_NULL(object_create_map_);
311 : object_create_map_ =
312 30 : broker->GetOrCreateData(proto_info->ObjectCreateMap())->AsMap();
313 : }
314 : }
315 : }
316 : }
317 :
318 : namespace {
319 1642 : base::Optional<ObjectRef> GetOwnElementFromHeap(JSHeapBroker* broker,
320 : Handle<Object> receiver,
321 : uint32_t index,
322 : bool constant_only) {
323 1642 : LookupIterator it(broker->isolate(), receiver, index, LookupIterator::OWN);
324 3284 : if (it.state() == LookupIterator::DATA &&
325 1399 : (!constant_only || (it.IsReadOnly() && !it.IsConfigurable()))) {
326 254 : return ObjectRef(broker, it.GetDataValue());
327 : }
328 : return base::nullopt;
329 : }
330 : } // namespace
331 :
332 9 : ObjectData* JSObjectData::GetOwnConstantElement(JSHeapBroker* broker,
333 : uint32_t index,
334 : bool serialize) {
335 9 : for (auto const& p : own_constant_elements_) {
336 0 : if (p.first == index) return p.second;
337 : }
338 :
339 9 : if (!serialize) {
340 9 : TRACE_MISSING(broker, "knowledge about index " << index << " on " << this);
341 : return nullptr;
342 : }
343 :
344 : base::Optional<ObjectRef> element =
345 0 : GetOwnElementFromHeap(broker, object(), index, true);
346 0 : ObjectData* result = element.has_value() ? element->data() : nullptr;
347 0 : own_constant_elements_.push_back({index, result});
348 0 : return result;
349 : }
350 :
351 : class JSTypedArrayData : public JSObjectData {
352 : public:
353 : JSTypedArrayData(JSHeapBroker* broker, ObjectData** storage,
354 : Handle<JSTypedArray> object);
355 :
356 : bool is_on_heap() const { return is_on_heap_; }
357 : size_t length() const { return length_; }
358 : void* elements_external_pointer() const { return elements_external_pointer_; }
359 :
360 : void Serialize(JSHeapBroker* broker);
361 : bool serialized() const { return serialized_; }
362 :
363 : HeapObjectData* buffer() const { return buffer_; }
364 :
365 : private:
366 : bool const is_on_heap_;
367 : size_t const length_;
368 : void* const elements_external_pointer_;
369 :
370 : bool serialized_ = false;
371 : HeapObjectData* buffer_ = nullptr;
372 : };
373 :
374 807 : JSTypedArrayData::JSTypedArrayData(JSHeapBroker* broker, ObjectData** storage,
375 : Handle<JSTypedArray> object)
376 : : JSObjectData(broker, storage, object),
377 : is_on_heap_(object->is_on_heap()),
378 : length_(object->length()),
379 : elements_external_pointer_(
380 3228 : FixedTypedArrayBase::cast(object->elements())->external_pointer()) {}
381 :
382 0 : void JSTypedArrayData::Serialize(JSHeapBroker* broker) {
383 0 : if (serialized_) return;
384 0 : serialized_ = true;
385 :
386 0 : TraceScope tracer(broker, this, "JSTypedArrayData::Serialize");
387 : Handle<JSTypedArray> typed_array = Handle<JSTypedArray>::cast(object());
388 :
389 0 : if (!is_on_heap()) {
390 : DCHECK_NULL(buffer_);
391 0 : buffer_ = broker->GetOrCreateData(typed_array->buffer())->AsHeapObject();
392 : }
393 : }
394 :
395 : class JSDataViewData : public JSObjectData {
396 : public:
397 : JSDataViewData(JSHeapBroker* broker, ObjectData** storage,
398 : Handle<JSDataView> object);
399 :
400 : size_t byte_length() const { return byte_length_; }
401 : size_t byte_offset() const { return byte_offset_; }
402 :
403 : private:
404 : size_t const byte_length_;
405 : size_t const byte_offset_;
406 : };
407 :
408 : class JSBoundFunctionData : public JSObjectData {
409 : public:
410 : JSBoundFunctionData(JSHeapBroker* broker, ObjectData** storage,
411 : Handle<JSBoundFunction> object);
412 :
413 : void Serialize(JSHeapBroker* broker);
414 :
415 : ObjectData* bound_target_function() const { return bound_target_function_; }
416 : ObjectData* bound_this() const { return bound_this_; }
417 : FixedArrayData* bound_arguments() const { return bound_arguments_; }
418 :
419 : private:
420 : bool serialized_ = false;
421 :
422 : ObjectData* bound_target_function_ = nullptr;
423 : ObjectData* bound_this_ = nullptr;
424 : FixedArrayData* bound_arguments_ = nullptr;
425 : };
426 :
427 : class JSFunctionData : public JSObjectData {
428 : public:
429 : JSFunctionData(JSHeapBroker* broker, ObjectData** storage,
430 : Handle<JSFunction> object);
431 :
432 : bool has_feedback_vector() const { return has_feedback_vector_; }
433 : bool has_initial_map() const { return has_initial_map_; }
434 : bool has_prototype() const { return has_prototype_; }
435 : bool PrototypeRequiresRuntimeLookup() const {
436 : return PrototypeRequiresRuntimeLookup_;
437 : }
438 :
439 : void Serialize(JSHeapBroker* broker);
440 : bool serialized() const { return serialized_; }
441 :
442 : ContextData* context() const { return context_; }
443 : NativeContextData* native_context() const { return native_context_; }
444 : MapData* initial_map() const { return initial_map_; }
445 : ObjectData* prototype() const { return prototype_; }
446 : SharedFunctionInfoData* shared() const { return shared_; }
447 : FeedbackVectorData* feedback_vector() const { return feedback_vector_; }
448 : int initial_map_instance_size_with_min_slack() const {
449 5447 : CHECK(serialized_);
450 5447 : return initial_map_instance_size_with_min_slack_;
451 : }
452 :
453 : private:
454 : bool has_feedback_vector_;
455 : bool has_initial_map_;
456 : bool has_prototype_;
457 : bool PrototypeRequiresRuntimeLookup_;
458 :
459 : bool serialized_ = false;
460 :
461 : ContextData* context_ = nullptr;
462 : NativeContextData* native_context_ = nullptr;
463 : MapData* initial_map_ = nullptr;
464 : ObjectData* prototype_ = nullptr;
465 : SharedFunctionInfoData* shared_ = nullptr;
466 : FeedbackVectorData* feedback_vector_ = nullptr;
467 : int initial_map_instance_size_with_min_slack_;
468 : };
469 :
470 : class JSRegExpData : public JSObjectData {
471 : public:
472 640 : JSRegExpData(JSHeapBroker* broker, ObjectData** storage,
473 : Handle<JSRegExp> object)
474 640 : : JSObjectData(broker, storage, object) {}
475 :
476 : void SerializeAsRegExpBoilerplate(JSHeapBroker* broker);
477 :
478 : ObjectData* raw_properties_or_hash() const { return raw_properties_or_hash_; }
479 : ObjectData* data() const { return data_; }
480 : ObjectData* source() const { return source_; }
481 : ObjectData* flags() const { return flags_; }
482 : ObjectData* last_index() const { return last_index_; }
483 :
484 : private:
485 : bool serialized_as_reg_exp_boilerplate_ = false;
486 :
487 : ObjectData* raw_properties_or_hash_ = nullptr;
488 : ObjectData* data_ = nullptr;
489 : ObjectData* source_ = nullptr;
490 : ObjectData* flags_ = nullptr;
491 : ObjectData* last_index_ = nullptr;
492 : };
493 :
494 : class HeapNumberData : public HeapObjectData {
495 : public:
496 464238 : HeapNumberData(JSHeapBroker* broker, ObjectData** storage,
497 : Handle<HeapNumber> object)
498 928477 : : HeapObjectData(broker, storage, object), value_(object->value()) {}
499 :
500 : double value() const { return value_; }
501 :
502 : private:
503 : double const value_;
504 : };
505 :
506 : class MutableHeapNumberData : public HeapObjectData {
507 : public:
508 0 : MutableHeapNumberData(JSHeapBroker* broker, ObjectData** storage,
509 : Handle<MutableHeapNumber> object)
510 0 : : HeapObjectData(broker, storage, object), value_(object->value()) {}
511 :
512 : double value() const { return value_; }
513 :
514 : private:
515 : double const value_;
516 : };
517 :
518 : class ContextData : public HeapObjectData {
519 : public:
520 : ContextData(JSHeapBroker* broker, ObjectData** storage,
521 : Handle<Context> object);
522 : void SerializeContextChain(JSHeapBroker* broker);
523 :
524 : ContextData* previous() const {
525 0 : CHECK(serialized_context_chain_);
526 0 : return previous_;
527 : }
528 :
529 : void SerializeSlot(JSHeapBroker* broker, int index);
530 :
531 16 : ObjectData* GetSlot(int index) {
532 : auto search = slots_.find(index);
533 16 : CHECK(search != slots_.end());
534 16 : return search->second;
535 : }
536 :
537 : private:
538 : ZoneMap<int, ObjectData*> slots_;
539 : bool serialized_context_chain_ = false;
540 : ContextData* previous_ = nullptr;
541 : };
542 :
543 196035 : ContextData::ContextData(JSHeapBroker* broker, ObjectData** storage,
544 : Handle<Context> object)
545 1320308 : : HeapObjectData(broker, storage, object), slots_(broker->zone()) {}
546 :
547 1178736 : void ContextData::SerializeContextChain(JSHeapBroker* broker) {
548 1798870 : if (serialized_context_chain_) return;
549 558602 : serialized_context_chain_ = true;
550 :
551 558602 : TraceScope tracer(broker, this, "ContextData::SerializeContextChain");
552 : Handle<Context> context = Handle<Context>::cast(object());
553 :
554 : DCHECK_NULL(previous_);
555 : // Context::previous DCHECK-fails when called on the native context.
556 558603 : if (!context->IsNativeContext()) {
557 94489 : previous_ = broker->GetOrCreateData(context->previous())->AsContext();
558 94489 : previous_->SerializeContextChain(broker);
559 : }
560 : }
561 :
562 16 : void ContextData::SerializeSlot(JSHeapBroker* broker, int index) {
563 16 : TraceScope tracer(broker, this, "ContextData::SerializeSlot");
564 16 : TRACE(broker, "Serializing script context slot " << index);
565 : Handle<Context> context = Handle<Context>::cast(object());
566 32 : CHECK(index >= 0 && index < context->length());
567 16 : ObjectData* odata = broker->GetOrCreateData(context->get(index));
568 32 : slots_.insert(std::make_pair(index, odata));
569 16 : }
570 :
571 : class NativeContextData : public ContextData {
572 : public:
573 : #define DECL_ACCESSOR(type, name) \
574 : type##Data* name() const { return name##_; }
575 : BROKER_NATIVE_CONTEXT_FIELDS(DECL_ACCESSOR)
576 : #undef DECL_ACCESSOR
577 :
578 : const ZoneVector<MapData*>& function_maps() const {
579 32152 : CHECK(serialized_);
580 : return function_maps_;
581 : }
582 :
583 : NativeContextData(JSHeapBroker* broker, ObjectData** storage,
584 : Handle<NativeContext> object);
585 : void Serialize(JSHeapBroker* broker);
586 :
587 : private:
588 : bool serialized_ = false;
589 : #define DECL_MEMBER(type, name) type##Data* name##_ = nullptr;
590 : BROKER_NATIVE_CONTEXT_FIELDS(DECL_MEMBER)
591 : #undef DECL_MEMBER
592 : ZoneVector<MapData*> function_maps_;
593 : };
594 :
595 : class NameData : public HeapObjectData {
596 : public:
597 0 : NameData(JSHeapBroker* broker, ObjectData** storage, Handle<Name> object)
598 7652765 : : HeapObjectData(broker, storage, object) {}
599 : };
600 :
601 : class StringData : public NameData {
602 : public:
603 : StringData(JSHeapBroker* broker, ObjectData** storage, Handle<String> object);
604 :
605 : int length() const { return length_; }
606 : uint16_t first_char() const { return first_char_; }
607 842 : base::Optional<double> to_number() const { return to_number_; }
608 : bool is_external_string() const { return is_external_string_; }
609 : bool is_seq_string() const { return is_seq_string_; }
610 :
611 : StringData* GetCharAsString(JSHeapBroker* broker, uint32_t index,
612 : bool serialize);
613 :
614 : private:
615 : int const length_;
616 : uint16_t const first_char_;
617 : base::Optional<double> to_number_;
618 : bool const is_external_string_;
619 : bool const is_seq_string_;
620 :
621 : // Known individual characters as strings, corresponding to the semantics of
622 : // element access (s[i]). The first pair component is always less than
623 : // {length_}. The second component is never nullptr.
624 : ZoneVector<std::pair<uint32_t, StringData*>> chars_as_strings_;
625 :
626 : static constexpr int kMaxLengthForDoubleConversion = 23;
627 : };
628 :
629 : class SymbolData : public NameData {
630 : public:
631 36686 : SymbolData(JSHeapBroker* broker, ObjectData** storage, Handle<Symbol> object)
632 36686 : : NameData(broker, storage, object) {}
633 : };
634 :
635 7616079 : StringData::StringData(JSHeapBroker* broker, ObjectData** storage,
636 : Handle<String> object)
637 : : NameData(broker, storage, object),
638 : length_(object->length()),
639 : first_char_(length_ > 0 ? object->Get(0) : 0),
640 : is_external_string_(object->IsExternalString()),
641 : is_seq_string_(object->IsSeqString()),
642 30464296 : chars_as_strings_(broker->zone()) {
643 : int flags = ALLOW_HEX | ALLOW_OCTAL | ALLOW_BINARY;
644 7616074 : if (length_ <= kMaxLengthForDoubleConversion) {
645 7568235 : to_number_ = StringToDouble(broker->isolate(), object, flags);
646 : }
647 7616073 : }
648 :
649 : class InternalizedStringData : public StringData {
650 : public:
651 : InternalizedStringData(JSHeapBroker* broker, ObjectData** storage,
652 : Handle<InternalizedString> object);
653 :
654 : uint32_t array_index() const { return array_index_; }
655 :
656 : private:
657 : uint32_t array_index_;
658 : };
659 :
660 0 : StringData* StringData::GetCharAsString(JSHeapBroker* broker, uint32_t index,
661 : bool serialize) {
662 0 : if (index >= static_cast<uint32_t>(length())) return nullptr;
663 :
664 0 : for (auto const& p : chars_as_strings_) {
665 0 : if (p.first == index) return p.second;
666 : }
667 :
668 0 : if (!serialize) {
669 0 : TRACE_MISSING(broker, "knowledge about index " << index << " on " << this);
670 : return nullptr;
671 : }
672 :
673 : base::Optional<ObjectRef> element =
674 0 : GetOwnElementFromHeap(broker, object(), index, true);
675 : StringData* result =
676 0 : element.has_value() ? element->data()->AsString() : nullptr;
677 0 : chars_as_strings_.push_back({index, result});
678 0 : return result;
679 : }
680 :
681 7615741 : InternalizedStringData::InternalizedStringData(
682 : JSHeapBroker* broker, ObjectData** storage,
683 : Handle<InternalizedString> object)
684 7615741 : : StringData(broker, storage, object) {}
685 :
686 : namespace {
687 :
688 7191 : bool IsFastLiteralHelper(Handle<JSObject> boilerplate, int max_depth,
689 : int* max_properties) {
690 : DCHECK_GE(max_depth, 0);
691 : DCHECK_GE(*max_properties, 0);
692 :
693 : // Make sure the boilerplate map is not deprecated.
694 7191 : if (!JSObject::TryMigrateInstance(boilerplate)) return false;
695 :
696 : // Check for too deep nesting.
697 7191 : if (max_depth == 0) return false;
698 :
699 : // Check the elements.
700 : Isolate* const isolate = boilerplate->GetIsolate();
701 : Handle<FixedArrayBase> elements(boilerplate->elements(), isolate);
702 11697 : if (elements->length() > 0 &&
703 : elements->map() != ReadOnlyRoots(isolate).fixed_cow_array_map()) {
704 2445 : if (boilerplate->HasSmiOrObjectElements()) {
705 : Handle<FixedArray> fast_elements = Handle<FixedArray>::cast(elements);
706 : int length = elements->length();
707 24618 : for (int i = 0; i < length; i++) {
708 11392 : if ((*max_properties)-- == 0) return false;
709 : Handle<Object> value(fast_elements->get(i), isolate);
710 11378 : if (value->IsJSObject()) {
711 700 : Handle<JSObject> value_object = Handle<JSObject>::cast(value);
712 700 : if (!IsFastLiteralHelper(value_object, max_depth - 1,
713 : max_properties)) {
714 0 : return false;
715 : }
716 : }
717 : }
718 583 : } else if (boilerplate->HasDoubleElements()) {
719 547 : if (elements->Size() > kMaxRegularHeapObjectSize) return false;
720 : } else {
721 : return false;
722 : }
723 : }
724 :
725 : // TODO(turbofan): Do we want to support out-of-object properties?
726 14268 : if (!(boilerplate->HasFastProperties() &&
727 21238 : boilerplate->property_array()->length() == 0)) {
728 : return false;
729 : }
730 :
731 : // Check the in-object properties.
732 : Handle<DescriptorArray> descriptors(
733 : boilerplate->map()->instance_descriptors(), isolate);
734 : int limit = boilerplate->map()->NumberOfOwnDescriptors();
735 21718 : for (int i = 0; i < limit; i++) {
736 7340 : PropertyDetails details = descriptors->GetDetails(i);
737 11938 : if (details.location() != kField) continue;
738 : DCHECK_EQ(kData, details.kind());
739 2877 : if ((*max_properties)-- == 0) return false;
740 2870 : FieldIndex field_index = FieldIndex::ForDescriptor(boilerplate->map(), i);
741 2870 : if (boilerplate->IsUnboxedDoubleField(field_index)) continue;
742 5484 : Handle<Object> value(boilerplate->RawFastPropertyAt(field_index), isolate);
743 2742 : if (value->IsJSObject()) {
744 291 : Handle<JSObject> value_object = Handle<JSObject>::cast(value);
745 291 : if (!IsFastLiteralHelper(value_object, max_depth - 1, max_properties)) {
746 7 : return false;
747 : }
748 : }
749 : }
750 : return true;
751 : }
752 :
753 : // Maximum depth and total number of elements and properties for literal
754 : // graphs to be considered for fast deep-copying. The limit is chosen to
755 : // match the maximum number of inobject properties, to ensure that the
756 : // performance of using object literals is not worse than using constructor
757 : // functions, see crbug.com/v8/6211 for details.
758 : const int kMaxFastLiteralDepth = 3;
759 : const int kMaxFastLiteralProperties = JSObject::kMaxInObjectProperties;
760 :
761 : // Determines whether the given array or object literal boilerplate satisfies
762 : // all limits to be considered for fast deep-copying and computes the total
763 : // size of all objects that are part of the graph.
764 : bool IsInlinableFastLiteral(Handle<JSObject> boilerplate) {
765 6200 : int max_properties = kMaxFastLiteralProperties;
766 : return IsFastLiteralHelper(boilerplate, kMaxFastLiteralDepth,
767 6200 : &max_properties);
768 : }
769 :
770 : } // namespace
771 :
772 : class AllocationSiteData : public HeapObjectData {
773 : public:
774 : AllocationSiteData(JSHeapBroker* broker, ObjectData** storage,
775 : Handle<AllocationSite> object);
776 : void SerializeBoilerplate(JSHeapBroker* broker);
777 :
778 : bool PointsToLiteral() const { return PointsToLiteral_; }
779 : AllocationType GetAllocationType() const { return GetAllocationType_; }
780 : ObjectData* nested_site() const { return nested_site_; }
781 : bool IsFastLiteral() const { return IsFastLiteral_; }
782 : JSObjectData* boilerplate() const { return boilerplate_; }
783 :
784 : // These are only valid if PointsToLiteral is false.
785 : ElementsKind GetElementsKind() const { return GetElementsKind_; }
786 : bool CanInlineCall() const { return CanInlineCall_; }
787 :
788 : private:
789 : bool const PointsToLiteral_;
790 : AllocationType const GetAllocationType_;
791 : ObjectData* nested_site_ = nullptr;
792 : bool IsFastLiteral_ = false;
793 : JSObjectData* boilerplate_ = nullptr;
794 : ElementsKind GetElementsKind_ = NO_ELEMENTS;
795 : bool CanInlineCall_ = false;
796 : bool serialized_boilerplate_ = false;
797 : };
798 :
799 : // Only used in JSNativeContextSpecialization.
800 : class ScriptContextTableData : public HeapObjectData {
801 : public:
802 464113 : ScriptContextTableData(JSHeapBroker* broker, ObjectData** storage,
803 : Handle<ScriptContextTable> object)
804 464113 : : HeapObjectData(broker, storage, object) {}
805 : };
806 :
807 8842 : struct PropertyDescriptor {
808 : NameData* key = nullptr;
809 : PropertyDetails details = PropertyDetails::Empty();
810 : FieldIndex field_index;
811 : MapData* field_owner = nullptr;
812 : ObjectData* field_type = nullptr;
813 : bool is_unboxed_double_field = false;
814 : };
815 :
816 : class MapData : public HeapObjectData {
817 : public:
818 : MapData(JSHeapBroker* broker, ObjectData** storage, Handle<Map> object);
819 :
820 : InstanceType instance_type() const { return instance_type_; }
821 : int instance_size() const { return instance_size_; }
822 : byte bit_field() const { return bit_field_; }
823 : byte bit_field2() const { return bit_field2_; }
824 : uint32_t bit_field3() const { return bit_field3_; }
825 : bool can_be_deprecated() const { return can_be_deprecated_; }
826 : bool can_transition() const { return can_transition_; }
827 : int in_object_properties_start_in_words() const {
828 40981 : CHECK(InstanceTypeChecker::IsJSObject(instance_type()));
829 40981 : return in_object_properties_start_in_words_;
830 : }
831 : int in_object_properties() const {
832 76778 : CHECK(InstanceTypeChecker::IsJSObject(instance_type()));
833 76778 : return in_object_properties_;
834 : }
835 : int constructor_function_index() const { return constructor_function_index_; }
836 : int NextFreePropertyIndex() const { return next_free_property_index_; }
837 : int UnusedPropertyFields() const { return unused_property_fields_; }
838 : bool supports_fast_array_iteration() const {
839 : return supports_fast_array_iteration_;
840 : }
841 : bool supports_fast_array_resize() const {
842 : return supports_fast_array_resize_;
843 : }
844 : bool IsMapOfCurrentGlobalProxy() const {
845 : return is_map_of_current_global_proxy_;
846 : }
847 :
848 : // Extra information.
849 :
850 : void SerializeElementsKindGeneralizations(JSHeapBroker* broker);
851 : const ZoneVector<MapData*>& elements_kind_generalizations() const {
852 1098 : CHECK(serialized_elements_kind_generalizations_);
853 : return elements_kind_generalizations_;
854 : }
855 :
856 : // Serialize the own part of the descriptor array and, recursively, that of
857 : // any field owner.
858 : void SerializeOwnDescriptors(JSHeapBroker* broker);
859 : DescriptorArrayData* instance_descriptors() const {
860 17627 : CHECK(serialized_own_descriptors_);
861 17627 : return instance_descriptors_;
862 : }
863 :
864 : void SerializeConstructor(JSHeapBroker* broker);
865 : ObjectData* GetConstructor() const {
866 4942 : CHECK(serialized_constructor_);
867 4942 : return constructor_;
868 : }
869 :
870 : void SerializeBackPointer(JSHeapBroker* broker);
871 : HeapObjectData* GetBackPointer() const {
872 0 : CHECK(serialized_backpointer_);
873 0 : return backpointer_;
874 : }
875 :
876 : void SerializePrototype(JSHeapBroker* broker);
877 : bool serialized_prototype() const { return serialized_prototype_; }
878 : ObjectData* prototype() const {
879 50 : CHECK(serialized_prototype_);
880 50 : return prototype_;
881 : }
882 :
883 : void SerializeForElementLoad(JSHeapBroker* broker);
884 :
885 : void SerializeForElementStore(JSHeapBroker* broker);
886 :
887 : private:
888 : InstanceType const instance_type_;
889 : int const instance_size_;
890 : byte const bit_field_;
891 : byte const bit_field2_;
892 : uint32_t const bit_field3_;
893 : bool const can_be_deprecated_;
894 : bool const can_transition_;
895 : int const in_object_properties_start_in_words_;
896 : int const in_object_properties_;
897 : int const constructor_function_index_;
898 : int const next_free_property_index_;
899 : int const unused_property_fields_;
900 : bool const supports_fast_array_iteration_;
901 : bool const supports_fast_array_resize_;
902 : bool const is_map_of_current_global_proxy_;
903 :
904 : bool serialized_elements_kind_generalizations_ = false;
905 : ZoneVector<MapData*> elements_kind_generalizations_;
906 :
907 : bool serialized_own_descriptors_ = false;
908 : DescriptorArrayData* instance_descriptors_ = nullptr;
909 :
910 : bool serialized_constructor_ = false;
911 : ObjectData* constructor_ = nullptr;
912 :
913 : bool serialized_backpointer_ = false;
914 : HeapObjectData* backpointer_ = nullptr;
915 :
916 : bool serialized_prototype_ = false;
917 : ObjectData* prototype_ = nullptr;
918 :
919 : bool serialized_for_element_load_ = false;
920 :
921 : bool serialized_for_element_store_ = false;
922 : };
923 :
924 7696 : AllocationSiteData::AllocationSiteData(JSHeapBroker* broker,
925 : ObjectData** storage,
926 : Handle<AllocationSite> object)
927 : : HeapObjectData(broker, storage, object),
928 : PointsToLiteral_(object->PointsToLiteral()),
929 23088 : GetAllocationType_(object->GetAllocationType()) {
930 7696 : if (PointsToLiteral_) {
931 : IsFastLiteral_ = IsInlinableFastLiteral(
932 6200 : handle(object->boilerplate(), broker->isolate()));
933 : } else {
934 1496 : GetElementsKind_ = object->GetElementsKind();
935 1496 : CanInlineCall_ = object->CanInlineCall();
936 : }
937 7696 : }
938 :
939 6061 : void AllocationSiteData::SerializeBoilerplate(JSHeapBroker* broker) {
940 6061 : if (serialized_boilerplate_) return;
941 6061 : serialized_boilerplate_ = true;
942 :
943 6061 : TraceScope tracer(broker, this, "AllocationSiteData::SerializeBoilerplate");
944 : Handle<AllocationSite> site = Handle<AllocationSite>::cast(object());
945 :
946 6061 : CHECK(IsFastLiteral_);
947 : DCHECK_NULL(boilerplate_);
948 6061 : boilerplate_ = broker->GetOrCreateData(site->boilerplate())->AsJSObject();
949 : boilerplate_->SerializeAsBoilerplate(broker);
950 :
951 : DCHECK_NULL(nested_site_);
952 6061 : nested_site_ = broker->GetOrCreateData(site->nested_site());
953 6061 : if (nested_site_->IsAllocationSite()) {
954 227 : nested_site_->AsAllocationSite()->SerializeBoilerplate(broker);
955 : }
956 : }
957 :
958 91729391 : HeapObjectData::HeapObjectData(JSHeapBroker* broker, ObjectData** storage,
959 : Handle<HeapObject> object)
960 : : ObjectData(broker, storage, object, kSerializedHeapObject),
961 183458062 : boolean_value_(object->BooleanValue(broker->isolate())),
962 : // We have to use a raw cast below instead of AsMap() because of
963 : // recursion. AsMap() would call IsMap(), which accesses the
964 : // instance_type_ member. In the case of constructing the MapData for the
965 : // meta map (whose map is itself), this member has not yet been
966 : // initialized.
967 275187181 : map_(static_cast<MapData*>(broker->GetOrCreateData(object->map()))) {
968 91728926 : CHECK(broker->SerializingAllowed());
969 91728926 : }
970 :
971 : namespace {
972 2762518 : bool IsReadOnlyLengthDescriptor(Isolate* isolate, Handle<Map> jsarray_map) {
973 : DCHECK(!jsarray_map->is_dictionary_map());
974 : Handle<Name> length_string = isolate->factory()->length_string();
975 2762518 : DescriptorArray descriptors = jsarray_map->instance_descriptors();
976 : int number = descriptors->Search(*length_string, *jsarray_map);
977 : DCHECK_NE(DescriptorArray::kNotFound, number);
978 5525036 : return descriptors->GetDetails(number).IsReadOnly();
979 : }
980 :
981 96357755 : bool SupportsFastArrayIteration(Isolate* isolate, Handle<Map> map) {
982 6517055 : return map->instance_type() == JS_ARRAY_TYPE &&
983 6514065 : IsFastElementsKind(map->elements_kind()) &&
984 5578936 : map->prototype()->IsJSArray() &&
985 5578939 : isolate->IsAnyInitialArrayPrototype(
986 101936327 : handle(JSArray::cast(map->prototype()), isolate)) &&
987 101936322 : isolate->IsNoElementsProtectorIntact();
988 : }
989 :
990 48178618 : bool SupportsFastArrayResize(Isolate* isolate, Handle<Map> map) {
991 53703660 : return SupportsFastArrayIteration(isolate, map) && map->is_extensible() &&
992 50941053 : !map->is_dictionary_map() && !IsReadOnlyLengthDescriptor(isolate, map);
993 : }
994 : } // namespace
995 :
996 48175462 : MapData::MapData(JSHeapBroker* broker, ObjectData** storage, Handle<Map> object)
997 : : HeapObjectData(broker, storage, object),
998 : instance_type_(object->instance_type()),
999 : instance_size_(object->instance_size()),
1000 : bit_field_(object->bit_field()),
1001 : bit_field2_(object->bit_field2()),
1002 : bit_field3_(object->bit_field3()),
1003 : can_be_deprecated_(object->NumberOfOwnDescriptors() > 0
1004 73349248 : ? object->CanBeDeprecated()
1005 : : false),
1006 : can_transition_(object->CanTransition()),
1007 : in_object_properties_start_in_words_(
1008 : object->IsJSObjectMap() ? object->GetInObjectPropertiesStartInWords()
1009 : : 0),
1010 : in_object_properties_(
1011 80795075 : object->IsJSObjectMap() ? object->GetInObjectProperties() : 0),
1012 : constructor_function_index_(object->IsPrimitiveMap()
1013 : ? object->GetConstructorFunctionIndex()
1014 : : Map::kNoConstructorFunctionIndex),
1015 96350691 : next_free_property_index_(object->NextFreePropertyIndex()),
1016 96350595 : unused_property_fields_(object->UnusedPropertyFields()),
1017 : supports_fast_array_iteration_(
1018 48175298 : SupportsFastArrayIteration(broker->isolate(), object)),
1019 : supports_fast_array_resize_(
1020 48175256 : SupportsFastArrayResize(broker->isolate(), object)),
1021 : is_map_of_current_global_proxy_(
1022 144525454 : object->IsMapOfGlobalProxy(broker->isolate()->native_context())),
1023 1021298892 : elements_kind_generalizations_(broker->zone()) {}
1024 :
1025 7504016 : JSFunctionData::JSFunctionData(JSHeapBroker* broker, ObjectData** storage,
1026 : Handle<JSFunction> object)
1027 : : JSObjectData(broker, storage, object),
1028 15008035 : has_feedback_vector_(object->has_feedback_vector()),
1029 21471566 : has_initial_map_(object->has_prototype_slot() &&
1030 13967541 : object->has_initial_map()),
1031 21471561 : has_prototype_(object->has_prototype_slot() && object->has_prototype()),
1032 : PrototypeRequiresRuntimeLookup_(
1033 37520102 : object->PrototypeRequiresRuntimeLookup()) {}
1034 :
1035 5217786 : void JSFunctionData::Serialize(JSHeapBroker* broker) {
1036 5714886 : if (serialized_) return;
1037 4720686 : serialized_ = true;
1038 :
1039 4720686 : TraceScope tracer(broker, this, "JSFunctionData::Serialize");
1040 : Handle<JSFunction> function = Handle<JSFunction>::cast(object());
1041 :
1042 : DCHECK_NULL(context_);
1043 : DCHECK_NULL(native_context_);
1044 : DCHECK_NULL(initial_map_);
1045 : DCHECK_NULL(prototype_);
1046 : DCHECK_NULL(shared_);
1047 : DCHECK_NULL(feedback_vector_);
1048 :
1049 4720687 : context_ = broker->GetOrCreateData(function->context())->AsContext();
1050 : native_context_ =
1051 4720679 : broker->GetOrCreateData(function->native_context())->AsNativeContext();
1052 4720679 : shared_ = broker->GetOrCreateData(function->shared())->AsSharedFunctionInfo();
1053 : feedback_vector_ = has_feedback_vector()
1054 471135 : ? broker->GetOrCreateData(function->feedback_vector())
1055 471135 : ->AsFeedbackVector()
1056 5191816 : : nullptr;
1057 : initial_map_ = has_initial_map()
1058 3724898 : ? broker->GetOrCreateData(function->initial_map())->AsMap()
1059 8445582 : : nullptr;
1060 12176522 : prototype_ = has_prototype() ? broker->GetOrCreateData(function->prototype())
1061 9441372 : : nullptr;
1062 :
1063 4720679 : if (initial_map_ != nullptr) {
1064 : initial_map_instance_size_with_min_slack_ =
1065 3724890 : function->ComputeInstanceSizeWithMinSlack(broker->isolate());
1066 3724897 : if (initial_map_->instance_type() == JS_ARRAY_TYPE) {
1067 464698 : initial_map_->SerializeElementsKindGeneralizations(broker);
1068 : }
1069 3724897 : initial_map_->SerializeConstructor(broker);
1070 : // TODO(neis): This is currently only needed for native_context's
1071 : // object_function, as used by GetObjectCreateMap. If no further use sites
1072 : // show up, we should move this into NativeContextData::Serialize.
1073 3724899 : initial_map_->SerializePrototype(broker);
1074 : }
1075 : }
1076 :
1077 464698 : void MapData::SerializeElementsKindGeneralizations(JSHeapBroker* broker) {
1078 464698 : if (serialized_elements_kind_generalizations_) return;
1079 464698 : serialized_elements_kind_generalizations_ = true;
1080 :
1081 : TraceScope tracer(broker, this,
1082 464698 : "MapData::SerializeElementsKindGeneralizations");
1083 : DCHECK_EQ(instance_type(), JS_ARRAY_TYPE);
1084 : MapRef self(broker, this);
1085 464696 : ElementsKind from_kind = self.elements_kind();
1086 : DCHECK(elements_kind_generalizations_.empty());
1087 6041066 : for (int i = FIRST_FAST_ELEMENTS_KIND; i <= LAST_FAST_ELEMENTS_KIND; i++) {
1088 : ElementsKind to_kind = static_cast<ElementsKind>(i);
1089 2788185 : if (IsMoreGeneralElementsKindTransition(from_kind, to_kind)) {
1090 : Handle<Map> target =
1091 2323488 : Map::AsElementsKind(broker->isolate(), self.object(), to_kind);
1092 4646970 : elements_kind_generalizations_.push_back(
1093 4646968 : broker->GetOrCreateData(target)->AsMap());
1094 : }
1095 : }
1096 : }
1097 :
1098 : class DescriptorArrayData : public HeapObjectData {
1099 : public:
1100 4198 : DescriptorArrayData(JSHeapBroker* broker, ObjectData** storage,
1101 : Handle<DescriptorArray> object)
1102 8396 : : HeapObjectData(broker, storage, object), contents_(broker->zone()) {}
1103 :
1104 : ZoneVector<PropertyDescriptor>& contents() { return contents_; }
1105 :
1106 : private:
1107 : ZoneVector<PropertyDescriptor> contents_;
1108 : };
1109 :
1110 : class FeedbackVectorData : public HeapObjectData {
1111 : public:
1112 : const ZoneVector<ObjectData*>& feedback() { return feedback_; }
1113 :
1114 : FeedbackVectorData(JSHeapBroker* broker, ObjectData** storage,
1115 : Handle<FeedbackVector> object);
1116 :
1117 : void SerializeSlots(JSHeapBroker* broker);
1118 :
1119 : private:
1120 : bool serialized_ = false;
1121 : ZoneVector<ObjectData*> feedback_;
1122 : };
1123 :
1124 471712 : FeedbackVectorData::FeedbackVectorData(JSHeapBroker* broker,
1125 : ObjectData** storage,
1126 : Handle<FeedbackVector> object)
1127 943425 : : HeapObjectData(broker, storage, object), feedback_(broker->zone()) {}
1128 :
1129 53205 : void FeedbackVectorData::SerializeSlots(JSHeapBroker* broker) {
1130 71610 : if (serialized_) return;
1131 34800 : serialized_ = true;
1132 :
1133 34800 : TraceScope tracer(broker, this, "FeedbackVectorData::SerializeSlots");
1134 : Handle<FeedbackVector> vector = Handle<FeedbackVector>::cast(object());
1135 : DCHECK(feedback_.empty());
1136 34800 : feedback_.reserve(vector->length());
1137 1369948 : for (int i = 0; i < vector->length(); ++i) {
1138 : MaybeObject value = vector->get(i);
1139 : ObjectData* slot_value =
1140 : value->IsObject() ? broker->GetOrCreateData(value->cast<Object>())
1141 667574 : : nullptr;
1142 667575 : feedback_.push_back(slot_value);
1143 768483 : if (slot_value == nullptr) continue;
1144 :
1145 573675 : if (slot_value->IsAllocationSite() &&
1146 7008 : slot_value->AsAllocationSite()->IsFastLiteral()) {
1147 5834 : slot_value->AsAllocationSite()->SerializeBoilerplate(broker);
1148 560833 : } else if (slot_value->IsJSRegExp()) {
1149 492 : slot_value->AsJSRegExp()->SerializeAsRegExpBoilerplate(broker);
1150 : }
1151 : }
1152 : DCHECK_EQ(vector->length(), feedback_.size());
1153 34800 : TRACE(broker, "Copied " << feedback_.size() << " slots");
1154 : }
1155 :
1156 : class FixedArrayBaseData : public HeapObjectData {
1157 : public:
1158 0 : FixedArrayBaseData(JSHeapBroker* broker, ObjectData** storage,
1159 : Handle<FixedArrayBase> object)
1160 2259155 : : HeapObjectData(broker, storage, object), length_(object->length()) {}
1161 :
1162 : int length() const { return length_; }
1163 :
1164 : private:
1165 : int const length_;
1166 : };
1167 :
1168 : class FixedArrayData : public FixedArrayBaseData {
1169 : public:
1170 : FixedArrayData(JSHeapBroker* broker, ObjectData** storage,
1171 : Handle<FixedArray> object);
1172 :
1173 : // Creates all elements of the fixed array.
1174 : void SerializeContents(JSHeapBroker* broker);
1175 :
1176 : ObjectData* Get(int i) const;
1177 :
1178 : private:
1179 : bool serialized_contents_ = false;
1180 : ZoneVector<ObjectData*> contents_;
1181 : };
1182 :
1183 160 : JSDataViewData::JSDataViewData(JSHeapBroker* broker, ObjectData** storage,
1184 : Handle<JSDataView> object)
1185 : : JSObjectData(broker, storage, object),
1186 : byte_length_(object->byte_length()),
1187 480 : byte_offset_(object->byte_offset()) {}
1188 :
1189 161 : JSBoundFunctionData::JSBoundFunctionData(JSHeapBroker* broker,
1190 : ObjectData** storage,
1191 : Handle<JSBoundFunction> object)
1192 161 : : JSObjectData(broker, storage, object) {}
1193 :
1194 0 : void JSBoundFunctionData::Serialize(JSHeapBroker* broker) {
1195 0 : if (serialized_) return;
1196 0 : serialized_ = true;
1197 :
1198 0 : TraceScope tracer(broker, this, "JSBoundFunctionData::Serialize");
1199 : Handle<JSBoundFunction> function = Handle<JSBoundFunction>::cast(object());
1200 :
1201 : DCHECK_NULL(bound_target_function_);
1202 : DCHECK_NULL(bound_this_);
1203 : DCHECK_NULL(bound_arguments_);
1204 :
1205 : bound_target_function_ =
1206 0 : broker->GetOrCreateData(function->bound_target_function());
1207 0 : bound_this_ = broker->GetOrCreateData(function->bound_this());
1208 : bound_arguments_ =
1209 0 : broker->GetOrCreateData(function->bound_arguments())->AsFixedArray();
1210 :
1211 0 : bound_arguments_->SerializeContents(broker);
1212 : }
1213 :
1214 11758708 : JSObjectData::JSObjectData(JSHeapBroker* broker, ObjectData** storage,
1215 : Handle<JSObject> object)
1216 : : HeapObjectData(broker, storage, object),
1217 : inobject_fields_(broker->zone()),
1218 35276086 : own_constant_elements_(broker->zone()) {}
1219 :
1220 513866 : FixedArrayData::FixedArrayData(JSHeapBroker* broker, ObjectData** storage,
1221 : Handle<FixedArray> object)
1222 1027732 : : FixedArrayBaseData(broker, storage, object), contents_(broker->zone()) {}
1223 :
1224 1811 : void FixedArrayData::SerializeContents(JSHeapBroker* broker) {
1225 1811 : if (serialized_contents_) return;
1226 1811 : serialized_contents_ = true;
1227 :
1228 1811 : TraceScope tracer(broker, this, "FixedArrayData::SerializeContents");
1229 : Handle<FixedArray> array = Handle<FixedArray>::cast(object());
1230 1811 : CHECK_EQ(array->length(), length());
1231 1811 : CHECK(contents_.empty());
1232 1811 : contents_.reserve(static_cast<size_t>(length()));
1233 :
1234 16853 : for (int i = 0; i < length(); i++) {
1235 : Handle<Object> value(array->get(i), broker->isolate());
1236 15042 : contents_.push_back(broker->GetOrCreateData(value));
1237 : }
1238 1811 : TRACE(broker, "Copied " << contents_.size() << " elements");
1239 : }
1240 :
1241 : class FixedDoubleArrayData : public FixedArrayBaseData {
1242 : public:
1243 : FixedDoubleArrayData(JSHeapBroker* broker, ObjectData** storage,
1244 : Handle<FixedDoubleArray> object);
1245 :
1246 : // Serializes all elements of the fixed array.
1247 : void SerializeContents(JSHeapBroker* broker);
1248 :
1249 : Float64 Get(int i) const;
1250 :
1251 : private:
1252 : bool serialized_contents_ = false;
1253 : ZoneVector<Float64> contents_;
1254 : };
1255 :
1256 518 : FixedDoubleArrayData::FixedDoubleArrayData(JSHeapBroker* broker,
1257 : ObjectData** storage,
1258 : Handle<FixedDoubleArray> object)
1259 1036 : : FixedArrayBaseData(broker, storage, object), contents_(broker->zone()) {}
1260 :
1261 518 : void FixedDoubleArrayData::SerializeContents(JSHeapBroker* broker) {
1262 518 : if (serialized_contents_) return;
1263 518 : serialized_contents_ = true;
1264 :
1265 518 : TraceScope tracer(broker, this, "FixedDoubleArrayData::SerializeContents");
1266 : Handle<FixedDoubleArray> self = Handle<FixedDoubleArray>::cast(object());
1267 518 : CHECK_EQ(self->length(), length());
1268 518 : CHECK(contents_.empty());
1269 518 : contents_.reserve(static_cast<size_t>(length()));
1270 :
1271 14940 : for (int i = 0; i < length(); i++) {
1272 14422 : contents_.push_back(Float64::FromBits(self->get_representation(i)));
1273 : }
1274 518 : TRACE(broker, "Copied " << contents_.size() << " elements");
1275 : }
1276 :
1277 : class BytecodeArrayData : public FixedArrayBaseData {
1278 : public:
1279 : int register_count() const { return register_count_; }
1280 :
1281 615193 : BytecodeArrayData(JSHeapBroker* broker, ObjectData** storage,
1282 : Handle<BytecodeArray> object)
1283 : : FixedArrayBaseData(broker, storage, object),
1284 615194 : register_count_(object->register_count()) {}
1285 :
1286 : private:
1287 : int const register_count_;
1288 : };
1289 :
1290 : class JSArrayData : public JSObjectData {
1291 : public:
1292 : JSArrayData(JSHeapBroker* broker, ObjectData** storage,
1293 : Handle<JSArray> object);
1294 :
1295 : void Serialize(JSHeapBroker* broker);
1296 : ObjectData* length() const { return length_; }
1297 :
1298 : ObjectData* GetOwnElement(JSHeapBroker* broker, uint32_t index,
1299 : bool serialize);
1300 :
1301 : private:
1302 : bool serialized_ = false;
1303 : ObjectData* length_ = nullptr;
1304 :
1305 : // Elements (indexed properties) that either
1306 : // (1) are known to exist directly on the object, or
1307 : // (2) are known not to (possibly they don't exist at all).
1308 : // In case (2), the second pair component is nullptr.
1309 : ZoneVector<std::pair<uint32_t, ObjectData*>> own_elements_;
1310 : };
1311 :
1312 473296 : JSArrayData::JSArrayData(JSHeapBroker* broker, ObjectData** storage,
1313 : Handle<JSArray> object)
1314 946597 : : JSObjectData(broker, storage, object), own_elements_(broker->zone()) {}
1315 :
1316 4200 : void JSArrayData::Serialize(JSHeapBroker* broker) {
1317 4200 : if (serialized_) return;
1318 4200 : serialized_ = true;
1319 :
1320 4200 : TraceScope tracer(broker, this, "JSArrayData::Serialize");
1321 : Handle<JSArray> jsarray = Handle<JSArray>::cast(object());
1322 :
1323 : DCHECK_NULL(length_);
1324 4200 : length_ = broker->GetOrCreateData(jsarray->length());
1325 : }
1326 :
1327 0 : ObjectData* JSArrayData::GetOwnElement(JSHeapBroker* broker, uint32_t index,
1328 : bool serialize) {
1329 0 : for (auto const& p : own_elements_) {
1330 0 : if (p.first == index) return p.second;
1331 : }
1332 :
1333 0 : if (!serialize) {
1334 0 : TRACE_MISSING(broker, "knowledge about index " << index << " on " << this);
1335 : return nullptr;
1336 : }
1337 :
1338 : base::Optional<ObjectRef> element =
1339 0 : GetOwnElementFromHeap(broker, object(), index, false);
1340 0 : ObjectData* result = element.has_value() ? element->data() : nullptr;
1341 0 : own_elements_.push_back({index, result});
1342 0 : return result;
1343 : }
1344 :
1345 : class ScopeInfoData : public HeapObjectData {
1346 : public:
1347 : ScopeInfoData(JSHeapBroker* broker, ObjectData** storage,
1348 : Handle<ScopeInfo> object);
1349 :
1350 : int context_length() const { return context_length_; }
1351 :
1352 : private:
1353 : int const context_length_;
1354 : };
1355 :
1356 56751 : ScopeInfoData::ScopeInfoData(JSHeapBroker* broker, ObjectData** storage,
1357 : Handle<ScopeInfo> object)
1358 : : HeapObjectData(broker, storage, object),
1359 113502 : context_length_(object->ContextLength()) {}
1360 :
1361 : class SharedFunctionInfoData : public HeapObjectData {
1362 : public:
1363 : SharedFunctionInfoData(JSHeapBroker* broker, ObjectData** storage,
1364 : Handle<SharedFunctionInfo> object);
1365 :
1366 : int builtin_id() const { return builtin_id_; }
1367 : BytecodeArrayData* GetBytecodeArray() const { return GetBytecodeArray_; }
1368 : void SetSerializedForCompilation(JSHeapBroker* broker,
1369 : FeedbackVectorRef feedback);
1370 : bool IsSerializedForCompilation(FeedbackVectorRef feedback) const;
1371 : #define DECL_ACCESSOR(type, name) \
1372 : type name() const { return name##_; }
1373 : BROKER_SFI_FIELDS(DECL_ACCESSOR)
1374 : #undef DECL_ACCESSOR
1375 :
1376 : private:
1377 : int const builtin_id_;
1378 : BytecodeArrayData* const GetBytecodeArray_;
1379 : ZoneUnorderedSet<Handle<FeedbackVector>, Handle<FeedbackVector>::hash,
1380 : Handle<FeedbackVector>::equal_to>
1381 : serialized_for_compilation_;
1382 : #define DECL_MEMBER(type, name) type const name##_;
1383 : BROKER_SFI_FIELDS(DECL_MEMBER)
1384 : #undef DECL_MEMBER
1385 : };
1386 :
1387 7018560 : SharedFunctionInfoData::SharedFunctionInfoData(
1388 : JSHeapBroker* broker, ObjectData** storage,
1389 : Handle<SharedFunctionInfo> object)
1390 : : HeapObjectData(broker, storage, object),
1391 : builtin_id_(object->HasBuiltinId() ? object->builtin_id()
1392 : : Builtins::kNoBuiltinId),
1393 : GetBytecodeArray_(
1394 14037107 : object->HasBytecodeArray()
1395 7633747 : ? broker->GetOrCreateData(object->GetBytecodeArray())
1396 615194 : ->AsBytecodeArray()
1397 : : nullptr),
1398 : serialized_for_compilation_(broker->zone())
1399 : #define INIT_MEMBER(type, name) , name##_(object->name())
1400 112911982 : BROKER_SFI_FIELDS(INIT_MEMBER)
1401 : #undef INIT_MEMBER
1402 : {
1403 : DCHECK_EQ(HasBuiltinId_, builtin_id_ != Builtins::kNoBuiltinId);
1404 : DCHECK_EQ(HasBytecodeArray_, GetBytecodeArray_ != nullptr);
1405 7018551 : }
1406 :
1407 162 : void SharedFunctionInfoData::SetSerializedForCompilation(
1408 : JSHeapBroker* broker, FeedbackVectorRef feedback) {
1409 324 : CHECK(serialized_for_compilation_.insert(feedback.object()).second);
1410 162 : TRACE(broker, "Set function " << object() << " with " << feedback.object()
1411 : << " as serialized for compilation");
1412 162 : }
1413 :
1414 0 : bool SharedFunctionInfoData::IsSerializedForCompilation(
1415 : FeedbackVectorRef feedback) const {
1416 832 : return serialized_for_compilation_.find(feedback.object()) !=
1417 0 : serialized_for_compilation_.end();
1418 : }
1419 :
1420 : class ModuleData : public HeapObjectData {
1421 : public:
1422 : ModuleData(JSHeapBroker* broker, ObjectData** storage, Handle<Module> object);
1423 : void Serialize(JSHeapBroker* broker);
1424 :
1425 : CellData* GetCell(int cell_index) const;
1426 :
1427 : private:
1428 : bool serialized_ = false;
1429 : ZoneVector<CellData*> imports_;
1430 : ZoneVector<CellData*> exports_;
1431 : };
1432 :
1433 85 : ModuleData::ModuleData(JSHeapBroker* broker, ObjectData** storage,
1434 : Handle<Module> object)
1435 : : HeapObjectData(broker, storage, object),
1436 : imports_(broker->zone()),
1437 170 : exports_(broker->zone()) {}
1438 :
1439 138 : CellData* ModuleData::GetCell(int cell_index) const {
1440 138 : CHECK(serialized_);
1441 : CellData* cell;
1442 138 : switch (ModuleDescriptor::GetCellIndexKind(cell_index)) {
1443 : case ModuleDescriptor::kImport:
1444 62 : cell = imports_.at(Module::ImportIndex(cell_index));
1445 31 : break;
1446 : case ModuleDescriptor::kExport:
1447 214 : cell = exports_.at(Module::ExportIndex(cell_index));
1448 107 : break;
1449 : case ModuleDescriptor::kInvalid:
1450 0 : UNREACHABLE();
1451 : break;
1452 : }
1453 138 : CHECK_NOT_NULL(cell);
1454 138 : return cell;
1455 : }
1456 :
1457 170 : void ModuleData::Serialize(JSHeapBroker* broker) {
1458 255 : if (serialized_) return;
1459 85 : serialized_ = true;
1460 :
1461 85 : TraceScope tracer(broker, this, "ModuleData::Serialize");
1462 : Handle<Module> module = Handle<Module>::cast(object());
1463 :
1464 : // TODO(neis): We could be smarter and only serialize the cells we care about.
1465 : // TODO(neis): Define a helper for serializing a FixedArray into a ZoneVector.
1466 :
1467 : DCHECK(imports_.empty());
1468 : Handle<FixedArray> imports(module->regular_imports(), broker->isolate());
1469 : int const imports_length = imports->length();
1470 85 : imports_.reserve(imports_length);
1471 273 : for (int i = 0; i < imports_length; ++i) {
1472 188 : imports_.push_back(broker->GetOrCreateData(imports->get(i))->AsCell());
1473 : }
1474 85 : TRACE(broker, "Copied " << imports_.size() << " imports");
1475 :
1476 : DCHECK(exports_.empty());
1477 : Handle<FixedArray> exports(module->regular_exports(), broker->isolate());
1478 : int const exports_length = exports->length();
1479 85 : exports_.reserve(exports_length);
1480 433 : for (int i = 0; i < exports_length; ++i) {
1481 348 : exports_.push_back(broker->GetOrCreateData(exports->get(i))->AsCell());
1482 : }
1483 85 : TRACE(broker, "Copied " << exports_.size() << " exports");
1484 : }
1485 :
1486 : class CellData : public HeapObjectData {
1487 : public:
1488 : CellData(JSHeapBroker* broker, ObjectData** storage, Handle<Cell> object);
1489 :
1490 : void Serialize(JSHeapBroker* broker);
1491 : ObjectData* value() { return value_; }
1492 :
1493 : private:
1494 : bool serialized_ = false;
1495 : ObjectData* value_ = nullptr;
1496 : };
1497 :
1498 928487 : CellData::CellData(JSHeapBroker* broker, ObjectData** storage,
1499 : Handle<Cell> object)
1500 928487 : : HeapObjectData(broker, storage, object) {}
1501 :
1502 928228 : void CellData::Serialize(JSHeapBroker* broker) {
1503 928228 : if (serialized_) return;
1504 928228 : serialized_ = true;
1505 :
1506 928228 : TraceScope tracer(broker, this, "CellData::Serialize");
1507 : auto cell = Handle<Cell>::cast(object());
1508 : DCHECK_NULL(value_);
1509 928228 : value_ = broker->GetOrCreateData(cell->value());
1510 : }
1511 :
1512 : class JSGlobalProxyData : public JSObjectData {
1513 : public:
1514 : JSGlobalProxyData(JSHeapBroker* broker, ObjectData** storage,
1515 : Handle<JSGlobalProxy> object);
1516 :
1517 : PropertyCellData* GetPropertyCell(JSHeapBroker* broker, NameData* name,
1518 : bool serialize);
1519 :
1520 : private:
1521 : // Properties that either
1522 : // (1) are known to exist as property cells on the global object, or
1523 : // (2) are known not to (possibly they don't exist at all).
1524 : // In case (2), the second pair component is nullptr.
1525 : ZoneVector<std::pair<NameData*, PropertyCellData*>> properties_;
1526 : };
1527 :
1528 464115 : JSGlobalProxyData::JSGlobalProxyData(JSHeapBroker* broker, ObjectData** storage,
1529 : Handle<JSGlobalProxy> object)
1530 928230 : : JSObjectData(broker, storage, object), properties_(broker->zone()) {}
1531 :
1532 : namespace {
1533 246 : base::Optional<PropertyCellRef> GetPropertyCellFromHeap(JSHeapBroker* broker,
1534 : Handle<Name> name) {
1535 : LookupIterator it(broker->isolate(),
1536 738 : handle(broker->native_context().object()->global_object(),
1537 : broker->isolate()),
1538 492 : name, LookupIterator::OWN);
1539 246 : it.TryLookupCachedProperty();
1540 472 : if (it.state() == LookupIterator::DATA &&
1541 : it.GetHolder<JSObject>()->IsJSGlobalObject()) {
1542 452 : return PropertyCellRef(broker, it.GetPropertyCell());
1543 : }
1544 : return base::nullopt;
1545 : }
1546 : } // namespace
1547 :
1548 0 : PropertyCellData* JSGlobalProxyData::GetPropertyCell(JSHeapBroker* broker,
1549 : NameData* name,
1550 : bool serialize) {
1551 0 : CHECK_NOT_NULL(name);
1552 0 : for (auto const& p : properties_) {
1553 0 : if (p.first == name) return p.second;
1554 : }
1555 :
1556 0 : if (!serialize) {
1557 0 : TRACE_MISSING(broker, "knowledge about global property " << name);
1558 : return nullptr;
1559 : }
1560 :
1561 : PropertyCellData* result = nullptr;
1562 : base::Optional<PropertyCellRef> cell =
1563 0 : GetPropertyCellFromHeap(broker, Handle<Name>::cast(name->object()));
1564 0 : if (cell.has_value()) {
1565 0 : cell->Serialize();
1566 0 : result = cell->data()->AsPropertyCell();
1567 : }
1568 0 : properties_.push_back({name, result});
1569 0 : return result;
1570 : }
1571 :
1572 : class CodeData : public HeapObjectData {
1573 : public:
1574 5951445 : CodeData(JSHeapBroker* broker, ObjectData** storage, Handle<Code> object)
1575 5951445 : : HeapObjectData(broker, storage, object) {}
1576 : };
1577 :
1578 : #define DEFINE_IS_AND_AS(Name) \
1579 : bool ObjectData::Is##Name() const { \
1580 : if (kind() == kUnserializedHeapObject) { \
1581 : AllowHandleDereference allow_handle_dereference; \
1582 : return object()->Is##Name(); \
1583 : } \
1584 : if (is_smi()) return false; \
1585 : InstanceType instance_type = \
1586 : static_cast<const HeapObjectData*>(this)->map()->instance_type(); \
1587 : return InstanceTypeChecker::Is##Name(instance_type); \
1588 : } \
1589 : Name##Data* ObjectData::As##Name() { \
1590 : CHECK_EQ(kind(), kSerializedHeapObject); \
1591 : CHECK(Is##Name()); \
1592 : return static_cast<Name##Data*>(this); \
1593 : }
1594 923955780 : HEAP_BROKER_OBJECT_LIST(DEFINE_IS_AND_AS)
1595 : #undef DEFINE_IS_AND_AS
1596 :
1597 3330 : const JSObjectField& JSObjectData::GetInobjectField(int property_index) const {
1598 3330 : CHECK_LT(static_cast<size_t>(property_index), inobject_fields_.size());
1599 3330 : return inobject_fields_[property_index];
1600 : }
1601 :
1602 0 : bool JSObjectData::cow_or_empty_elements_tenured() const {
1603 40 : return cow_or_empty_elements_tenured_;
1604 : }
1605 :
1606 7617 : FixedArrayBaseData* JSObjectData::elements() const { return elements_; }
1607 :
1608 0 : void JSObjectData::SerializeAsBoilerplate(JSHeapBroker* broker) {
1609 6061 : SerializeRecursive(broker, kMaxFastLiteralDepth);
1610 0 : }
1611 :
1612 492 : void JSObjectData::SerializeElements(JSHeapBroker* broker) {
1613 492 : if (serialized_elements_) return;
1614 492 : serialized_elements_ = true;
1615 :
1616 492 : TraceScope tracer(broker, this, "JSObjectData::SerializeElements");
1617 : Handle<JSObject> boilerplate = Handle<JSObject>::cast(object());
1618 : Handle<FixedArrayBase> elements_object(boilerplate->elements(),
1619 : broker->isolate());
1620 : DCHECK_NULL(elements_);
1621 492 : elements_ = broker->GetOrCreateData(elements_object)->AsFixedArrayBase();
1622 : }
1623 :
1624 13467237 : void MapData::SerializeConstructor(JSHeapBroker* broker) {
1625 13931350 : if (serialized_constructor_) return;
1626 13003124 : serialized_constructor_ = true;
1627 :
1628 13003124 : TraceScope tracer(broker, this, "MapData::SerializeConstructor");
1629 : Handle<Map> map = Handle<Map>::cast(object());
1630 : DCHECK_NULL(constructor_);
1631 13003121 : constructor_ = broker->GetOrCreateData(map->GetConstructor());
1632 : }
1633 :
1634 0 : void MapData::SerializeBackPointer(JSHeapBroker* broker) {
1635 0 : if (serialized_backpointer_) return;
1636 0 : serialized_backpointer_ = true;
1637 :
1638 0 : TraceScope tracer(broker, this, "MapData::SerializeBackPointer");
1639 : Handle<Map> map = Handle<Map>::cast(object());
1640 : DCHECK_NULL(backpointer_);
1641 0 : backpointer_ = broker->GetOrCreateData(map->GetBackPointer())->AsHeapObject();
1642 : }
1643 :
1644 4653130 : void MapData::SerializePrototype(JSHeapBroker* broker) {
1645 4653130 : if (serialized_prototype_) return;
1646 4653130 : serialized_prototype_ = true;
1647 :
1648 4653130 : TraceScope tracer(broker, this, "MapData::SerializePrototype");
1649 : Handle<Map> map = Handle<Map>::cast(object());
1650 : DCHECK_NULL(prototype_);
1651 4653130 : prototype_ = broker->GetOrCreateData(map->prototype());
1652 : }
1653 :
1654 8988 : void MapData::SerializeOwnDescriptors(JSHeapBroker* broker) {
1655 14267 : if (serialized_own_descriptors_) return;
1656 5220 : serialized_own_descriptors_ = true;
1657 :
1658 5220 : TraceScope tracer(broker, this, "MapData::SerializeOwnDescriptors");
1659 : Handle<Map> map = Handle<Map>::cast(object());
1660 :
1661 : DCHECK_NULL(instance_descriptors_);
1662 : instance_descriptors_ =
1663 5220 : broker->GetOrCreateData(map->instance_descriptors())->AsDescriptorArray();
1664 :
1665 : int const number_of_own = map->NumberOfOwnDescriptors();
1666 5220 : ZoneVector<PropertyDescriptor>& contents = instance_descriptors_->contents();
1667 5220 : int const current_size = static_cast<int>(contents.size());
1668 5220 : if (number_of_own <= current_size) return;
1669 :
1670 : Isolate* const isolate = broker->isolate();
1671 : auto descriptors =
1672 : Handle<DescriptorArray>::cast(instance_descriptors_->object());
1673 3709 : CHECK_EQ(*descriptors, map->instance_descriptors());
1674 3709 : contents.reserve(number_of_own);
1675 :
1676 : // Copy the new descriptors.
1677 12551 : for (int i = current_size; i < number_of_own; ++i) {
1678 : PropertyDescriptor d;
1679 4421 : d.key = broker->GetOrCreateData(descriptors->GetKey(i))->AsName();
1680 4421 : d.details = descriptors->GetDetails(i);
1681 4421 : if (d.details.location() == kField) {
1682 2217 : d.field_index = FieldIndex::ForDescriptor(*map, i);
1683 : d.field_owner =
1684 2217 : broker->GetOrCreateData(map->FindFieldOwner(isolate, i))->AsMap();
1685 2217 : d.field_type = broker->GetOrCreateData(descriptors->GetFieldType(i));
1686 2217 : d.is_unboxed_double_field = map->IsUnboxedDoubleField(d.field_index);
1687 : // Recurse.
1688 : }
1689 4421 : contents.push_back(d);
1690 : }
1691 3709 : CHECK_EQ(number_of_own, contents.size());
1692 :
1693 : // Recurse on the new owner maps.
1694 12551 : for (int i = current_size; i < number_of_own; ++i) {
1695 4421 : const PropertyDescriptor& d = contents[i];
1696 4421 : if (d.details.location() == kField) {
1697 4434 : CHECK_LE(
1698 : Handle<Map>::cast(d.field_owner->object())->NumberOfOwnDescriptors(),
1699 : number_of_own);
1700 2217 : d.field_owner->SerializeOwnDescriptors(broker);
1701 : }
1702 : }
1703 :
1704 3709 : TRACE(broker, "Copied " << number_of_own - current_size
1705 : << " descriptors into " << instance_descriptors_
1706 : << " (" << number_of_own << " total)");
1707 : }
1708 :
1709 6982 : void JSObjectData::SerializeRecursive(JSHeapBroker* broker, int depth) {
1710 7209 : if (serialized_as_boilerplate_) return;
1711 6755 : serialized_as_boilerplate_ = true;
1712 :
1713 6755 : TraceScope tracer(broker, this, "JSObjectData::SerializeRecursive");
1714 : Handle<JSObject> boilerplate = Handle<JSObject>::cast(object());
1715 :
1716 : // We only serialize boilerplates that pass the IsInlinableFastLiteral
1717 : // check, so we only do a sanity check on the depth here.
1718 6755 : CHECK_GT(depth, 0);
1719 6755 : CHECK(!boilerplate->map()->is_deprecated());
1720 :
1721 : // Serialize the elements.
1722 : Isolate* const isolate = broker->isolate();
1723 : Handle<FixedArrayBase> elements_object(boilerplate->elements(), isolate);
1724 :
1725 : // Boilerplates need special serialization - we need to make sure COW arrays
1726 : // are tenured. Boilerplate objects should only be reachable from their
1727 : // allocation site, so it is safe to assume that the elements have not been
1728 : // serialized yet.
1729 :
1730 : bool const empty_or_cow =
1731 11033 : elements_object->length() == 0 ||
1732 : elements_object->map() == ReadOnlyRoots(isolate).fixed_cow_array_map();
1733 6755 : if (empty_or_cow) {
1734 : // We need to make sure copy-on-write elements are tenured.
1735 4426 : if (ObjectInYoungGeneration(*elements_object)) {
1736 : elements_object = isolate->factory()->CopyAndTenureFixedCOWArray(
1737 1609 : Handle<FixedArray>::cast(elements_object));
1738 1609 : boilerplate->set_elements(*elements_object);
1739 : }
1740 4426 : cow_or_empty_elements_tenured_ = true;
1741 : }
1742 :
1743 : DCHECK_NULL(elements_);
1744 6755 : elements_ = broker->GetOrCreateData(elements_object)->AsFixedArrayBase();
1745 :
1746 6755 : if (empty_or_cow) {
1747 : // No need to do anything here. Empty or copy-on-write elements
1748 : // do not need to be serialized because we only need to store the elements
1749 : // reference to the allocated object.
1750 2329 : } else if (boilerplate->HasSmiOrObjectElements()) {
1751 1811 : elements_->AsFixedArray()->SerializeContents(broker);
1752 : Handle<FixedArray> fast_elements =
1753 : Handle<FixedArray>::cast(elements_object);
1754 : int length = elements_object->length();
1755 16853 : for (int i = 0; i < length; i++) {
1756 : Handle<Object> value(fast_elements->get(i), isolate);
1757 7521 : if (value->IsJSObject()) {
1758 637 : ObjectData* value_data = broker->GetOrCreateData(value);
1759 637 : value_data->AsJSObject()->SerializeRecursive(broker, depth - 1);
1760 : }
1761 : }
1762 : } else {
1763 518 : CHECK(boilerplate->HasDoubleElements());
1764 518 : CHECK_LE(elements_object->Size(), kMaxRegularHeapObjectSize);
1765 518 : elements_->AsFixedDoubleArray()->SerializeContents(broker);
1766 : }
1767 :
1768 : // TODO(turbofan): Do we want to support out-of-object properties?
1769 20265 : CHECK(boilerplate->HasFastProperties() &&
1770 : boilerplate->property_array()->length() == 0);
1771 6755 : CHECK_EQ(inobject_fields_.size(), 0u);
1772 :
1773 : // Check the in-object properties.
1774 : Handle<DescriptorArray> descriptors(
1775 : boilerplate->map()->instance_descriptors(), isolate);
1776 : int const limit = boilerplate->map()->NumberOfOwnDescriptors();
1777 20881 : for (int i = 0; i < limit; i++) {
1778 7063 : PropertyDetails details = descriptors->GetDetails(i);
1779 11263 : if (details.location() != kField) continue;
1780 : DCHECK_EQ(kData, details.kind());
1781 :
1782 2863 : FieldIndex field_index = FieldIndex::ForDescriptor(boilerplate->map(), i);
1783 : // Make sure {field_index} agrees with {inobject_properties} on the index of
1784 : // this field.
1785 : DCHECK_EQ(field_index.property_index(),
1786 : static_cast<int>(inobject_fields_.size()));
1787 2863 : if (boilerplate->IsUnboxedDoubleField(field_index)) {
1788 : double value = boilerplate->RawFastDoublePropertyAt(field_index);
1789 256 : inobject_fields_.push_back(JSObjectField{value});
1790 : } else {
1791 : Handle<Object> value(boilerplate->RawFastPropertyAt(field_index),
1792 5470 : isolate);
1793 2735 : ObjectData* value_data = broker->GetOrCreateData(value);
1794 2735 : if (value->IsJSObject()) {
1795 284 : value_data->AsJSObject()->SerializeRecursive(broker, depth - 1);
1796 : }
1797 5470 : inobject_fields_.push_back(JSObjectField{value_data});
1798 : }
1799 : }
1800 6755 : TRACE(broker, "Copied " << inobject_fields_.size() << " in-object fields");
1801 :
1802 6755 : map()->SerializeOwnDescriptors(broker);
1803 :
1804 6755 : if (IsJSArray()) AsJSArray()->Serialize(broker);
1805 : }
1806 :
1807 492 : void JSRegExpData::SerializeAsRegExpBoilerplate(JSHeapBroker* broker) {
1808 492 : if (serialized_as_reg_exp_boilerplate_) return;
1809 492 : serialized_as_reg_exp_boilerplate_ = true;
1810 :
1811 492 : TraceScope tracer(broker, this, "JSRegExpData::SerializeAsRegExpBoilerplate");
1812 : Handle<JSRegExp> boilerplate = Handle<JSRegExp>::cast(object());
1813 :
1814 492 : SerializeElements(broker);
1815 :
1816 : raw_properties_or_hash_ =
1817 492 : broker->GetOrCreateData(boilerplate->raw_properties_or_hash());
1818 492 : data_ = broker->GetOrCreateData(boilerplate->data());
1819 492 : source_ = broker->GetOrCreateData(boilerplate->source());
1820 492 : flags_ = broker->GetOrCreateData(boilerplate->flags());
1821 492 : last_index_ = broker->GetOrCreateData(boilerplate->last_index());
1822 : }
1823 :
1824 1405743 : bool ObjectRef::equals(const ObjectRef& other) const {
1825 33852349 : return data_ == other.data_;
1826 : }
1827 :
1828 1937778 : Isolate* ObjectRef::isolate() const { return broker()->isolate(); }
1829 :
1830 23615 : ContextRef ContextRef::previous() const {
1831 23615 : if (broker()->mode() == JSHeapBroker::kDisabled) {
1832 : AllowHandleAllocation handle_allocation;
1833 : AllowHandleDereference handle_dereference;
1834 : return ContextRef(broker(),
1835 23615 : handle(object()->previous(), broker()->isolate()));
1836 : }
1837 0 : return ContextRef(broker(), data()->AsContext()->previous());
1838 : }
1839 :
1840 : // Not needed for TypedLowering.
1841 27709 : ObjectRef ContextRef::get(int index) const {
1842 27709 : if (broker()->mode() == JSHeapBroker::kDisabled) {
1843 : AllowHandleAllocation handle_allocation;
1844 : AllowHandleDereference handle_dereference;
1845 : Handle<Object> value(object()->get(index), broker()->isolate());
1846 27693 : return ObjectRef(broker(), value);
1847 : }
1848 32 : return ObjectRef(broker(), data()->AsContext()->GetSlot(index));
1849 : }
1850 :
1851 485858 : JSHeapBroker::JSHeapBroker(Isolate* isolate, Zone* broker_zone)
1852 : : isolate_(isolate),
1853 : broker_zone_(broker_zone),
1854 : current_zone_(broker_zone),
1855 : refs_(new (zone())
1856 485858 : RefsMap(kMinimalRefsBucketCount, AddressMatcher(), zone())),
1857 : array_and_object_prototypes_(zone()),
1858 1943428 : feedback_(zone()) {
1859 : // Note that this initialization of the refs_ pointer with the minimal
1860 : // initial capacity is redundant in the normal use case (concurrent
1861 : // compilation enabled, standard objects to be serialized), as the map
1862 : // is going to be replaced immediatelly with a larger capacity one.
1863 : // It doesn't seem to affect the performance in a noticeable way though.
1864 485860 : TRACE(this, "Constructing heap broker");
1865 485860 : }
1866 :
1867 0 : std::ostream& JSHeapBroker::Trace() {
1868 0 : return trace_out_ << "[" << this << "] "
1869 0 : << std::string(trace_indentation_ * 2, ' ');
1870 : }
1871 :
1872 464112 : void JSHeapBroker::StartSerializing() {
1873 464112 : CHECK_EQ(mode_, kDisabled);
1874 464112 : TRACE(this, "Starting serialization");
1875 464112 : mode_ = kSerializing;
1876 464112 : refs_->Clear();
1877 464112 : }
1878 :
1879 464114 : void JSHeapBroker::StopSerializing() {
1880 464114 : CHECK_EQ(mode_, kSerializing);
1881 464114 : TRACE(this, "Stopping serialization");
1882 464114 : mode_ = kSerialized;
1883 464114 : }
1884 :
1885 463847 : void JSHeapBroker::Retire() {
1886 463847 : CHECK_EQ(mode_, kSerialized);
1887 463847 : TRACE(this, "Retiring");
1888 463847 : mode_ = kRetired;
1889 463847 : }
1890 :
1891 0 : bool JSHeapBroker::SerializingAllowed() const { return mode() == kSerializing; }
1892 :
1893 928725 : void JSHeapBroker::SetNativeContextRef() {
1894 1857451 : native_context_ = NativeContextRef(this, isolate()->native_context());
1895 928726 : }
1896 :
1897 5401764 : bool IsShareable(Handle<Object> object, Isolate* isolate) {
1898 : Builtins* const b = isolate->builtins();
1899 :
1900 : int index;
1901 : RootIndex root_index;
1902 5401764 : return (object->IsHeapObject() &&
1903 5431608 : b->IsBuiltinHandle(Handle<HeapObject>::cast(object), &index)) ||
1904 5401764 : isolate->roots_table().IsRootHandle(object, &root_index);
1905 : }
1906 :
1907 464110 : void JSHeapBroker::SerializeShareableObjects() {
1908 464110 : PerIsolateCompilerCache::Setup(isolate());
1909 464114 : compiler_cache_ = isolate()->compiler_cache();
1910 :
1911 464114 : if (compiler_cache_->HasSnapshot()) {
1912 : RefsMap* snapshot = compiler_cache_->GetSnapshot();
1913 :
1914 449192 : refs_ = new (zone()) RefsMap(snapshot, zone());
1915 449192 : return;
1916 : }
1917 :
1918 : TraceScope tracer(
1919 : this, "JSHeapBroker::SerializeShareableObjects (building snapshot)");
1920 :
1921 : refs_ =
1922 29844 : new (zone()) RefsMap(kInitialRefsBucketCount, AddressMatcher(), zone());
1923 :
1924 14922 : current_zone_ = compiler_cache_->zone();
1925 :
1926 : Builtins* const b = isolate()->builtins();
1927 : {
1928 : Builtins::Name builtins[] = {
1929 : Builtins::kAllocateInYoungGeneration,
1930 : Builtins::kAllocateInOldGeneration,
1931 : Builtins::kArgumentsAdaptorTrampoline,
1932 : Builtins::kArrayConstructorImpl,
1933 : Builtins::kCallFunctionForwardVarargs,
1934 : Builtins::kCallFunction_ReceiverIsAny,
1935 : Builtins::kCallFunction_ReceiverIsNotNullOrUndefined,
1936 : Builtins::kCallFunction_ReceiverIsNullOrUndefined,
1937 : Builtins::kConstructFunctionForwardVarargs,
1938 : Builtins::kForInFilter,
1939 : Builtins::kJSBuiltinsConstructStub,
1940 : Builtins::kJSConstructStubGeneric,
1941 : Builtins::kStringAdd_CheckNone,
1942 : Builtins::kStringAdd_ConvertLeft,
1943 : Builtins::kStringAdd_ConvertRight,
1944 : Builtins::kToNumber,
1945 : Builtins::kToObject,
1946 14922 : };
1947 522270 : for (auto id : builtins) {
1948 507348 : GetOrCreateData(b->builtin_handle(id));
1949 : }
1950 : }
1951 45407562 : for (int32_t id = 0; id < Builtins::builtin_count; ++id) {
1952 22696320 : if (Builtins::KindOf(id) == Builtins::TFJ) {
1953 10236450 : GetOrCreateData(b->builtin_handle(id));
1954 : }
1955 : }
1956 :
1957 16235136 : for (RefsMap::Entry* p = refs_->Start(); p != nullptr; p = refs_->Next(p)) {
1958 5401764 : CHECK(IsShareable(p->value->object(), isolate()));
1959 : }
1960 :
1961 : // TODO(mslekova):
1962 : // Serialize root objects (from factory).
1963 14922 : compiler_cache()->SetSnapshot(refs_);
1964 14922 : current_zone_ = broker_zone_;
1965 : }
1966 :
1967 464114 : void JSHeapBroker::CollectArrayAndObjectPrototypes() {
1968 : DisallowHeapAllocation no_gc;
1969 464114 : CHECK_EQ(mode(), kSerializing);
1970 464114 : CHECK(array_and_object_prototypes_.empty());
1971 :
1972 : Object maybe_context = isolate()->heap()->native_contexts_list();
1973 3722162 : while (!maybe_context->IsUndefined(isolate())) {
1974 1629024 : Context context = Context::cast(maybe_context);
1975 : Object array_prot = context->get(Context::INITIAL_ARRAY_PROTOTYPE_INDEX);
1976 : Object object_prot = context->get(Context::INITIAL_OBJECT_PROTOTYPE_INDEX);
1977 3258048 : array_and_object_prototypes_.emplace(JSObject::cast(array_prot), isolate());
1978 3258048 : array_and_object_prototypes_.emplace(JSObject::cast(object_prot),
1979 3258048 : isolate());
1980 1629024 : maybe_context = context->next_context_link();
1981 : }
1982 :
1983 464114 : CHECK(!array_and_object_prototypes_.empty());
1984 464114 : }
1985 :
1986 66798 : bool JSHeapBroker::IsArrayOrObjectPrototype(const JSObjectRef& object) const {
1987 66798 : if (mode() == kDisabled) {
1988 133580 : return isolate()->IsInAnyContext(*object.object(),
1989 130202 : Context::INITIAL_ARRAY_PROTOTYPE_INDEX) ||
1990 63412 : isolate()->IsInAnyContext(*object.object(),
1991 : Context::INITIAL_OBJECT_PROTOTYPE_INDEX);
1992 : }
1993 8 : CHECK(!array_and_object_prototypes_.empty());
1994 16 : return array_and_object_prototypes_.find(object.object()) !=
1995 : array_and_object_prototypes_.end();
1996 : }
1997 :
1998 464134 : void JSHeapBroker::SerializeStandardObjects() {
1999 464158 : if (mode() == kDisabled) return;
2000 464110 : CHECK_EQ(mode(), kSerializing);
2001 :
2002 464110 : SerializeShareableObjects();
2003 :
2004 : TraceScope tracer(this, "JSHeapBroker::SerializeStandardObjects");
2005 :
2006 464114 : CollectArrayAndObjectPrototypes();
2007 :
2008 464114 : SetNativeContextRef();
2009 464114 : native_context().Serialize();
2010 :
2011 : Factory* const f = isolate()->factory();
2012 :
2013 : // Maps, strings, oddballs
2014 464114 : GetOrCreateData(f->arguments_marker_map());
2015 464114 : GetOrCreateData(f->bigint_string());
2016 464113 : GetOrCreateData(f->block_context_map());
2017 464113 : GetOrCreateData(f->boolean_map());
2018 464114 : GetOrCreateData(f->boolean_string());
2019 464114 : GetOrCreateData(f->catch_context_map());
2020 464114 : GetOrCreateData(f->empty_fixed_array());
2021 464114 : GetOrCreateData(f->empty_string());
2022 464113 : GetOrCreateData(f->eval_context_map());
2023 464113 : GetOrCreateData(f->false_string());
2024 464113 : GetOrCreateData(f->false_value());
2025 464113 : GetOrCreateData(f->fixed_array_map());
2026 464113 : GetOrCreateData(f->fixed_cow_array_map());
2027 464113 : GetOrCreateData(f->fixed_double_array_map());
2028 464110 : GetOrCreateData(f->function_context_map());
2029 464113 : GetOrCreateData(f->function_string());
2030 464114 : GetOrCreateData(f->heap_number_map());
2031 464113 : GetOrCreateData(f->length_string());
2032 464114 : GetOrCreateData(f->many_closures_cell_map());
2033 464114 : GetOrCreateData(f->minus_zero_value());
2034 464114 : GetOrCreateData(f->mutable_heap_number_map());
2035 464112 : GetOrCreateData(f->name_dictionary_map());
2036 464114 : GetOrCreateData(f->NaN_string());
2037 464114 : GetOrCreateData(f->null_map());
2038 464114 : GetOrCreateData(f->null_string());
2039 464114 : GetOrCreateData(f->null_value());
2040 464114 : GetOrCreateData(f->number_string());
2041 464114 : GetOrCreateData(f->object_string());
2042 464114 : GetOrCreateData(f->one_pointer_filler_map());
2043 464113 : GetOrCreateData(f->optimized_out());
2044 464113 : GetOrCreateData(f->optimized_out_map());
2045 464113 : GetOrCreateData(f->property_array_map());
2046 464112 : GetOrCreateData(f->sloppy_arguments_elements_map());
2047 464113 : GetOrCreateData(f->stale_register());
2048 464114 : GetOrCreateData(f->stale_register_map());
2049 464113 : GetOrCreateData(f->string_string());
2050 464114 : GetOrCreateData(f->symbol_string());
2051 464113 : GetOrCreateData(f->termination_exception_map());
2052 464114 : GetOrCreateData(f->the_hole_map());
2053 464114 : GetOrCreateData(f->the_hole_value());
2054 464114 : GetOrCreateData(f->true_string());
2055 464114 : GetOrCreateData(f->true_value());
2056 464114 : GetOrCreateData(f->undefined_map());
2057 464114 : GetOrCreateData(f->undefined_string());
2058 464114 : GetOrCreateData(f->undefined_value());
2059 464114 : GetOrCreateData(f->uninitialized_map());
2060 464114 : GetOrCreateData(f->with_context_map());
2061 464114 : GetOrCreateData(f->zero_string());
2062 :
2063 : // Protector cells
2064 : GetOrCreateData(f->array_buffer_detaching_protector())
2065 : ->AsPropertyCell()
2066 464114 : ->Serialize(this);
2067 464113 : GetOrCreateData(f->array_constructor_protector())->AsCell()->Serialize(this);
2068 : GetOrCreateData(f->array_iterator_protector())
2069 : ->AsPropertyCell()
2070 464114 : ->Serialize(this);
2071 : GetOrCreateData(f->array_species_protector())
2072 : ->AsPropertyCell()
2073 464113 : ->Serialize(this);
2074 : GetOrCreateData(f->no_elements_protector())
2075 : ->AsPropertyCell()
2076 464114 : ->Serialize(this);
2077 : GetOrCreateData(f->promise_hook_protector())
2078 : ->AsPropertyCell()
2079 464113 : ->Serialize(this);
2080 : GetOrCreateData(f->promise_species_protector())
2081 : ->AsPropertyCell()
2082 464114 : ->Serialize(this);
2083 : GetOrCreateData(f->promise_then_protector())
2084 : ->AsPropertyCell()
2085 464114 : ->Serialize(this);
2086 464114 : GetOrCreateData(f->string_length_protector())->AsCell()->Serialize(this);
2087 :
2088 : // CEntry stub
2089 928228 : GetOrCreateData(
2090 464114 : CodeFactory::CEntry(isolate(), 1, kDontSaveFPRegs, kArgvOnStack, true));
2091 :
2092 464114 : TRACE(this, "Finished serializing standard objects");
2093 : }
2094 :
2095 0 : ObjectData* JSHeapBroker::GetData(Handle<Object> object) const {
2096 51583299 : RefsMap::Entry* entry = refs_->Lookup(object.address());
2097 51583409 : return entry ? entry->value : nullptr;
2098 : }
2099 :
2100 : // clang-format off
2101 208761155 : ObjectData* JSHeapBroker::GetOrCreateData(Handle<Object> object) {
2102 208761155 : CHECK(SerializingAllowed());
2103 208761155 : RefsMap::Entry* entry = refs_->LookupOrInsert(object.address(), zone());
2104 208762384 : ObjectData** data_storage = &(entry->value);
2105 208762384 : if (*data_storage == nullptr) {
2106 : // TODO(neis): Remove these Allow* once we serialize everything upfront.
2107 : AllowHandleAllocation handle_allocation;
2108 : AllowHandleDereference handle_dereference;
2109 92270206 : if (object->IsSmi()) {
2110 1078498 : new (zone()) ObjectData(this, data_storage, object, kSmi);
2111 : #define CREATE_DATA_IF_MATCH(name) \
2112 : } else if (object->Is##name()) { \
2113 : new (zone()) name##Data(this, data_storage, Handle<name>::cast(object));
2114 2332421334 : HEAP_BROKER_OBJECT_LIST(CREATE_DATA_IF_MATCH)
2115 : #undef CREATE_DATA_IF_MATCH
2116 : } else {
2117 0 : UNREACHABLE();
2118 : }
2119 : }
2120 208761858 : CHECK_NOT_NULL(*data_storage);
2121 208761858 : return (*data_storage);
2122 : }
2123 : // clang-format on
2124 :
2125 165260865 : ObjectData* JSHeapBroker::GetOrCreateData(Object object) {
2126 165260297 : return GetOrCreateData(handle(object, isolate()));
2127 : }
2128 :
2129 : #define DEFINE_IS_AND_AS(Name) \
2130 : bool ObjectRef::Is##Name() const { return data()->Is##Name(); } \
2131 : Name##Ref ObjectRef::As##Name() const { \
2132 : DCHECK(Is##Name()); \
2133 : return Name##Ref(broker(), data()); \
2134 : }
2135 81801381 : HEAP_BROKER_OBJECT_LIST(DEFINE_IS_AND_AS)
2136 : #undef DEFINE_IS_AND_AS
2137 :
2138 25374349 : bool ObjectRef::IsSmi() const { return data()->is_smi(); }
2139 :
2140 708934 : int ObjectRef::AsSmi() const {
2141 : DCHECK(IsSmi());
2142 : // Handle-dereference is always allowed for Handle<Smi>.
2143 708934 : return Handle<Smi>::cast(object())->value();
2144 : }
2145 :
2146 16 : base::Optional<MapRef> JSObjectRef::GetObjectCreateMap() const {
2147 16 : if (broker()->mode() == JSHeapBroker::kDisabled) {
2148 : AllowHandleAllocation handle_allocation;
2149 : AllowHandleDereference allow_handle_dereference;
2150 : AllowHeapAllocation heap_allocation;
2151 : Handle<Map> instance_map;
2152 0 : if (Map::TryGetObjectCreateMap(broker()->isolate(), object())
2153 : .ToHandle(&instance_map)) {
2154 0 : return MapRef(broker(), instance_map);
2155 : } else {
2156 0 : return base::Optional<MapRef>();
2157 : }
2158 : }
2159 16 : MapData* map_data = data()->AsJSObject()->object_create_map();
2160 : return map_data != nullptr ? MapRef(broker(), map_data)
2161 24 : : base::Optional<MapRef>();
2162 : }
2163 :
2164 : #define DEF_TESTER(Type, ...) \
2165 : bool MapRef::Is##Type##Map() const { \
2166 : return InstanceTypeChecker::Is##Type(instance_type()); \
2167 : }
2168 694075 : INSTANCE_TYPE_CHECKERS(DEF_TESTER)
2169 : #undef DEF_TESTER
2170 :
2171 2361 : base::Optional<MapRef> MapRef::AsElementsKind(ElementsKind kind) const {
2172 2361 : if (broker()->mode() == JSHeapBroker::kDisabled) {
2173 : AllowHandleAllocation handle_allocation;
2174 : AllowHeapAllocation heap_allocation;
2175 : AllowHandleDereference allow_handle_dereference;
2176 : return MapRef(broker(),
2177 0 : Map::AsElementsKind(broker()->isolate(), object(), kind));
2178 : }
2179 2361 : if (kind == elements_kind()) return *this;
2180 : const ZoneVector<MapData*>& elements_kind_generalizations =
2181 1098 : data()->AsMap()->elements_kind_generalizations();
2182 1990 : for (auto data : elements_kind_generalizations) {
2183 : MapRef map(broker(), data);
2184 3088 : if (map.elements_kind() == kind) return map;
2185 : }
2186 0 : return base::Optional<MapRef>();
2187 : }
2188 :
2189 0 : void MapRef::SerializeForElementLoad() {
2190 0 : CHECK_EQ(broker()->mode(), JSHeapBroker::kSerializing);
2191 0 : data()->AsMap()->SerializeForElementLoad(broker());
2192 0 : }
2193 :
2194 0 : void MapRef::SerializeForElementStore() {
2195 0 : CHECK_EQ(broker()->mode(), JSHeapBroker::kSerializing);
2196 0 : data()->AsMap()->SerializeForElementStore(broker());
2197 0 : }
2198 :
2199 : namespace {
2200 : // This helper function has two modes. If {prototype_maps} is nullptr, the
2201 : // prototype chain is serialized as necessary to determine the result.
2202 : // Otherwise, the heap is untouched and the encountered prototypes are pushed
2203 : // onto {prototype_maps}.
2204 0 : bool HasOnlyStablePrototypesWithFastElementsHelper(
2205 : JSHeapBroker* broker, MapRef const& map,
2206 : ZoneVector<MapRef>* prototype_maps) {
2207 0 : for (MapRef prototype_map = map;;) {
2208 0 : if (prototype_maps == nullptr) prototype_map.SerializePrototype();
2209 0 : prototype_map = prototype_map.prototype().AsHeapObject().map();
2210 0 : if (prototype_map.oddball_type() == OddballType::kNull) return true;
2211 0 : if (!map.prototype().IsJSObject() || !prototype_map.is_stable() ||
2212 0 : !IsFastElementsKind(prototype_map.elements_kind())) {
2213 : return false;
2214 : }
2215 0 : if (prototype_maps != nullptr) prototype_maps->push_back(prototype_map);
2216 : }
2217 : }
2218 : } // namespace
2219 :
2220 0 : void MapData::SerializeForElementLoad(JSHeapBroker* broker) {
2221 0 : if (serialized_for_element_load_) return;
2222 0 : serialized_for_element_load_ = true;
2223 :
2224 0 : TraceScope tracer(broker, this, "MapData::SerializeForElementLoad");
2225 0 : SerializePrototype(broker);
2226 : }
2227 :
2228 0 : void MapData::SerializeForElementStore(JSHeapBroker* broker) {
2229 0 : if (serialized_for_element_store_) return;
2230 0 : serialized_for_element_store_ = true;
2231 :
2232 0 : TraceScope tracer(broker, this, "MapData::SerializeForElementStore");
2233 0 : HasOnlyStablePrototypesWithFastElementsHelper(broker, MapRef(broker, this),
2234 0 : nullptr);
2235 : }
2236 :
2237 1949 : bool MapRef::HasOnlyStablePrototypesWithFastElements(
2238 : ZoneVector<MapRef>* prototype_maps) {
2239 1949 : for (MapRef prototype_map = *this;;) {
2240 5740 : if (prototype_maps == nullptr) prototype_map.SerializePrototype();
2241 5740 : prototype_map = prototype_map.prototype().AsHeapObject().map();
2242 5740 : if (prototype_map.oddball_type() == OddballType::kNull) return true;
2243 11387 : if (!prototype().IsJSObject() || !prototype_map.is_stable() ||
2244 3791 : !IsFastElementsKind(prototype_map.elements_kind())) {
2245 : return false;
2246 : }
2247 3791 : if (prototype_maps != nullptr) prototype_maps->push_back(prototype_map);
2248 : }
2249 : }
2250 :
2251 4106 : bool MapRef::supports_fast_array_iteration() const {
2252 4106 : if (broker()->mode() == JSHeapBroker::kDisabled) {
2253 : AllowHandleDereference allow_handle_dereference;
2254 : AllowHandleAllocation handle_allocation;
2255 4106 : return SupportsFastArrayIteration(broker()->isolate(), object());
2256 : }
2257 0 : return data()->AsMap()->supports_fast_array_iteration();
2258 : }
2259 :
2260 3354 : bool MapRef::supports_fast_array_resize() const {
2261 3354 : if (broker()->mode() == JSHeapBroker::kDisabled) {
2262 : AllowHandleDereference allow_handle_dereference;
2263 : AllowHandleAllocation handle_allocation;
2264 3354 : return SupportsFastArrayResize(broker()->isolate(), object());
2265 : }
2266 0 : return data()->AsMap()->supports_fast_array_resize();
2267 : }
2268 :
2269 125581 : bool MapRef::IsMapOfCurrentGlobalProxy() const {
2270 125581 : if (broker()->mode() == JSHeapBroker::kDisabled) {
2271 : AllowHandleDereference allow_handle_dereference;
2272 : AllowHandleAllocation handle_allocation;
2273 251113 : return object()->IsMapOfGlobalProxy(broker()->isolate()->native_context());
2274 : }
2275 24 : return data()->AsMap()->IsMapOfCurrentGlobalProxy();
2276 : }
2277 :
2278 5448 : int JSFunctionRef::InitialMapInstanceSizeWithMinSlack() const {
2279 5448 : if (broker()->mode() == JSHeapBroker::kDisabled) {
2280 : AllowHandleDereference allow_handle_dereference;
2281 : AllowHandleAllocation handle_allocation;
2282 1 : return object()->ComputeInstanceSizeWithMinSlack(broker()->isolate());
2283 : }
2284 10894 : return data()->AsJSFunction()->initial_map_instance_size_with_min_slack();
2285 : }
2286 :
2287 : // Not needed for TypedLowering.
2288 : base::Optional<ScriptContextTableRef::LookupResult>
2289 0 : ScriptContextTableRef::lookup(const NameRef& name) const {
2290 : AllowHandleAllocation handle_allocation;
2291 : AllowHandleDereference handle_dereference;
2292 0 : if (!name.IsString()) return {};
2293 : ScriptContextTable::LookupResult lookup_result;
2294 : auto table = object();
2295 0 : if (!ScriptContextTable::Lookup(broker()->isolate(), *table,
2296 0 : *name.AsString().object(), &lookup_result)) {
2297 0 : return {};
2298 : }
2299 : Handle<Context> script_context = ScriptContextTable::GetContext(
2300 0 : broker()->isolate(), table, lookup_result.context_index);
2301 : LookupResult result{ContextRef(broker(), script_context),
2302 0 : lookup_result.mode == VariableMode::kConst,
2303 0 : lookup_result.slot_index};
2304 : return result;
2305 : }
2306 :
2307 16920021 : OddballType MapRef::oddball_type() const {
2308 16920021 : if (instance_type() != ODDBALL_TYPE) {
2309 : return OddballType::kNone;
2310 : }
2311 : Factory* f = broker()->isolate()->factory();
2312 10295307 : if (equals(MapRef(broker(), f->undefined_map()))) {
2313 : return OddballType::kUndefined;
2314 : }
2315 9363644 : if (equals(MapRef(broker(), f->null_map()))) {
2316 : return OddballType::kNull;
2317 : }
2318 9328290 : if (equals(MapRef(broker(), f->boolean_map()))) {
2319 : return OddballType::kBoolean;
2320 : }
2321 2523053 : if (equals(MapRef(broker(), f->the_hole_map()))) {
2322 : return OddballType::kHole;
2323 : }
2324 931388 : if (equals(MapRef(broker(), f->uninitialized_map()))) {
2325 : return OddballType::kUninitialized;
2326 : }
2327 : DCHECK(equals(MapRef(broker(), f->termination_exception_map())) ||
2328 : equals(MapRef(broker(), f->arguments_marker_map())) ||
2329 : equals(MapRef(broker(), f->optimized_out_map())) ||
2330 : equals(MapRef(broker(), f->stale_register_map())));
2331 929433 : return OddballType::kOther;
2332 : }
2333 :
2334 52989 : ObjectRef FeedbackVectorRef::get(FeedbackSlot slot) const {
2335 52989 : if (broker()->mode() == JSHeapBroker::kDisabled) {
2336 : AllowHandleAllocation handle_allocation;
2337 : AllowHandleDereference handle_dereference;
2338 : Handle<Object> value(object()->Get(slot)->cast<Object>(),
2339 : broker()->isolate());
2340 0 : return ObjectRef(broker(), value);
2341 : }
2342 : int i = FeedbackVector::GetIndex(slot);
2343 158967 : return ObjectRef(broker(), data()->AsFeedbackVector()->feedback().at(i));
2344 : }
2345 :
2346 128 : double JSObjectRef::RawFastDoublePropertyAt(FieldIndex index) const {
2347 128 : if (broker()->mode() == JSHeapBroker::kDisabled) {
2348 : AllowHandleDereference handle_dereference;
2349 : return object()->RawFastDoublePropertyAt(index);
2350 : }
2351 128 : JSObjectData* object_data = data()->AsJSObject();
2352 128 : CHECK(index.is_inobject());
2353 256 : return object_data->GetInobjectField(index.property_index()).AsDouble();
2354 : }
2355 :
2356 3202 : ObjectRef JSObjectRef::RawFastPropertyAt(FieldIndex index) const {
2357 3202 : if (broker()->mode() == JSHeapBroker::kDisabled) {
2358 : AllowHandleAllocation handle_allocation;
2359 : AllowHandleDereference handle_dereference;
2360 : return ObjectRef(broker(), handle(object()->RawFastPropertyAt(index),
2361 0 : broker()->isolate()));
2362 : }
2363 3202 : JSObjectData* object_data = data()->AsJSObject();
2364 3202 : CHECK(index.is_inobject());
2365 : return ObjectRef(
2366 : broker(),
2367 6404 : object_data->GetInobjectField(index.property_index()).AsObject());
2368 : }
2369 :
2370 6274 : bool AllocationSiteRef::IsFastLiteral() const {
2371 6274 : if (broker()->mode() == JSHeapBroker::kDisabled) {
2372 : AllowHeapAllocation allow_heap_allocation; // For TryMigrateInstance.
2373 : AllowHandleAllocation allow_handle_allocation;
2374 : AllowHandleDereference allow_handle_dereference;
2375 : return IsInlinableFastLiteral(
2376 : handle(object()->boilerplate(), broker()->isolate()));
2377 : }
2378 6274 : return data()->AsAllocationSite()->IsFastLiteral();
2379 : }
2380 :
2381 40 : void JSObjectRef::EnsureElementsTenured() {
2382 40 : if (broker()->mode() == JSHeapBroker::kDisabled) {
2383 : AllowHandleAllocation allow_handle_allocation;
2384 : AllowHandleDereference allow_handle_dereference;
2385 : AllowHeapAllocation allow_heap_allocation;
2386 :
2387 0 : Handle<FixedArrayBase> object_elements = elements().object();
2388 0 : if (ObjectInYoungGeneration(*object_elements)) {
2389 : // If we would like to pretenure a fixed cow array, we must ensure that
2390 : // the array is already in old space, otherwise we'll create too many
2391 : // old-to-new-space pointers (overflowing the store buffer).
2392 : object_elements =
2393 : broker()->isolate()->factory()->CopyAndTenureFixedCOWArray(
2394 0 : Handle<FixedArray>::cast(object_elements));
2395 0 : object()->set_elements(*object_elements);
2396 : }
2397 : return;
2398 : }
2399 80 : CHECK(data()->AsJSObject()->cow_or_empty_elements_tenured());
2400 : }
2401 :
2402 3330 : FieldIndex MapRef::GetFieldIndexFor(int descriptor_index) const {
2403 3330 : if (broker()->mode() == JSHeapBroker::kDisabled) {
2404 : AllowHandleDereference allow_handle_dereference;
2405 0 : return FieldIndex::ForDescriptor(*object(), descriptor_index);
2406 : }
2407 3330 : DescriptorArrayData* descriptors = data()->AsMap()->instance_descriptors();
2408 6660 : return descriptors->contents().at(descriptor_index).field_index;
2409 : }
2410 :
2411 34572 : int MapRef::GetInObjectPropertyOffset(int i) const {
2412 34572 : if (broker()->mode() == JSHeapBroker::kDisabled) {
2413 : AllowHandleDereference allow_handle_dereference;
2414 : return object()->GetInObjectPropertyOffset(i);
2415 : }
2416 34568 : return (GetInObjectPropertiesStartInWords() + i) * kTaggedSize;
2417 : }
2418 :
2419 189849 : PropertyDetails MapRef::GetPropertyDetails(int descriptor_index) const {
2420 189849 : if (broker()->mode() == JSHeapBroker::kDisabled) {
2421 : AllowHandleDereference allow_handle_dereference;
2422 182260 : return object()->instance_descriptors()->GetDetails(descriptor_index);
2423 : }
2424 7589 : DescriptorArrayData* descriptors = data()->AsMap()->instance_descriptors();
2425 15178 : return descriptors->contents().at(descriptor_index).details;
2426 : }
2427 :
2428 3330 : NameRef MapRef::GetPropertyKey(int descriptor_index) const {
2429 3330 : if (broker()->mode() == JSHeapBroker::kDisabled) {
2430 : AllowHandleAllocation handle_allocation;
2431 : AllowHandleDereference allow_handle_dereference;
2432 : return NameRef(
2433 : broker(),
2434 : handle(object()->instance_descriptors()->GetKey(descriptor_index),
2435 0 : broker()->isolate()));
2436 : }
2437 3330 : DescriptorArrayData* descriptors = data()->AsMap()->instance_descriptors();
2438 9990 : return NameRef(broker(), descriptors->contents().at(descriptor_index).key);
2439 : }
2440 :
2441 4321 : bool MapRef::IsFixedCowArrayMap() const {
2442 : Handle<Map> fixed_cow_array_map =
2443 : ReadOnlyRoots(broker()->isolate()).fixed_cow_array_map_handle();
2444 4321 : return equals(MapRef(broker(), fixed_cow_array_map));
2445 : }
2446 :
2447 111515 : bool MapRef::IsPrimitiveMap() const {
2448 119638 : return instance_type() <= LAST_PRIMITIVE_TYPE;
2449 : }
2450 :
2451 186171 : MapRef MapRef::FindFieldOwner(int descriptor_index) const {
2452 186171 : if (broker()->mode() == JSHeapBroker::kDisabled) {
2453 : AllowHandleAllocation handle_allocation;
2454 : AllowHandleDereference allow_handle_dereference;
2455 : Handle<Map> owner(
2456 : object()->FindFieldOwner(broker()->isolate(), descriptor_index),
2457 372278 : broker()->isolate());
2458 186139 : return MapRef(broker(), owner);
2459 : }
2460 32 : DescriptorArrayData* descriptors = data()->AsMap()->instance_descriptors();
2461 : return MapRef(broker(),
2462 96 : descriptors->contents().at(descriptor_index).field_owner);
2463 : }
2464 :
2465 3895 : ObjectRef MapRef::GetFieldType(int descriptor_index) const {
2466 3895 : if (broker()->mode() == JSHeapBroker::kDisabled) {
2467 : AllowHandleAllocation handle_allocation;
2468 : AllowHandleDereference allow_handle_dereference;
2469 : Handle<FieldType> field_type(
2470 7758 : object()->instance_descriptors()->GetFieldType(descriptor_index),
2471 3879 : broker()->isolate());
2472 3879 : return ObjectRef(broker(), field_type);
2473 : }
2474 16 : DescriptorArrayData* descriptors = data()->AsMap()->instance_descriptors();
2475 : return ObjectRef(broker(),
2476 48 : descriptors->contents().at(descriptor_index).field_type);
2477 : }
2478 :
2479 3330 : bool MapRef::IsUnboxedDoubleField(int descriptor_index) const {
2480 3330 : if (broker()->mode() == JSHeapBroker::kDisabled) {
2481 : AllowHandleDereference allow_handle_dereference;
2482 0 : return object()->IsUnboxedDoubleField(
2483 0 : FieldIndex::ForDescriptor(*object(), descriptor_index));
2484 : }
2485 3330 : DescriptorArrayData* descriptors = data()->AsMap()->instance_descriptors();
2486 6660 : return descriptors->contents().at(descriptor_index).is_unboxed_double_field;
2487 : }
2488 :
2489 104 : uint16_t StringRef::GetFirstChar() {
2490 104 : if (broker()->mode() == JSHeapBroker::kDisabled) {
2491 : AllowHandleDereference allow_handle_dereference;
2492 : return object()->Get(0);
2493 : }
2494 104 : return data()->AsString()->first_char();
2495 : }
2496 :
2497 842 : base::Optional<double> StringRef::ToNumber() {
2498 842 : if (broker()->mode() == JSHeapBroker::kDisabled) {
2499 : AllowHandleDereference allow_handle_dereference;
2500 : AllowHandleAllocation allow_handle_allocation;
2501 : AllowHeapAllocation allow_heap_allocation;
2502 : int flags = ALLOW_HEX | ALLOW_OCTAL | ALLOW_BINARY;
2503 0 : return StringToDouble(broker()->isolate(), object(), flags);
2504 : }
2505 842 : return data()->AsString()->to_number();
2506 : }
2507 :
2508 7751 : ObjectRef FixedArrayRef::get(int i) const {
2509 7751 : if (broker()->mode() == JSHeapBroker::kDisabled) {
2510 : AllowHandleAllocation handle_allocation;
2511 : AllowHandleDereference allow_handle_dereference;
2512 202 : return ObjectRef(broker(), handle(object()->get(i), broker()->isolate()));
2513 : }
2514 15098 : return ObjectRef(broker(), data()->AsFixedArray()->Get(i));
2515 : }
2516 :
2517 7211 : bool FixedDoubleArrayRef::is_the_hole(int i) const {
2518 7211 : if (broker()->mode() == JSHeapBroker::kDisabled) {
2519 : AllowHandleDereference allow_handle_dereference;
2520 : return object()->is_the_hole(i);
2521 : }
2522 14422 : return data()->AsFixedDoubleArray()->Get(i).is_hole_nan();
2523 : }
2524 :
2525 7112 : double FixedDoubleArrayRef::get_scalar(int i) const {
2526 7112 : if (broker()->mode() == JSHeapBroker::kDisabled) {
2527 : AllowHandleDereference allow_handle_dereference;
2528 : return object()->get_scalar(i);
2529 : }
2530 14224 : CHECK(!data()->AsFixedDoubleArray()->Get(i).is_hole_nan());
2531 7112 : return data()->AsFixedDoubleArray()->Get(i).get_scalar();
2532 : }
2533 :
2534 : #define IF_BROKER_DISABLED_ACCESS_HANDLE_C(holder, name) \
2535 : if (broker()->mode() == JSHeapBroker::kDisabled) { \
2536 : AllowHandleAllocation handle_allocation; \
2537 : AllowHandleDereference allow_handle_dereference; \
2538 : return object()->name(); \
2539 : }
2540 :
2541 : #define IF_BROKER_DISABLED_ACCESS_HANDLE(holder, result, name) \
2542 : if (broker()->mode() == JSHeapBroker::kDisabled) { \
2543 : AllowHandleAllocation handle_allocation; \
2544 : AllowHandleDereference allow_handle_dereference; \
2545 : return result##Ref(broker(), \
2546 : handle(object()->name(), broker()->isolate())); \
2547 : }
2548 :
2549 : // Macros for definining a const getter that, depending on the broker mode,
2550 : // either looks into the handle or into the serialized data.
2551 : #define BIMODAL_ACCESSOR(holder, result, name) \
2552 : result##Ref holder##Ref::name() const { \
2553 : IF_BROKER_DISABLED_ACCESS_HANDLE(holder, result, name); \
2554 : return result##Ref(broker(), ObjectRef::data()->As##holder()->name()); \
2555 : }
2556 :
2557 : // Like above except that the result type is not an XYZRef.
2558 : #define BIMODAL_ACCESSOR_C(holder, result, name) \
2559 : result holder##Ref::name() const { \
2560 : IF_BROKER_DISABLED_ACCESS_HANDLE_C(holder, name); \
2561 : return ObjectRef::data()->As##holder()->name(); \
2562 : }
2563 :
2564 : // Like above but for BitFields.
2565 : #define BIMODAL_ACCESSOR_B(holder, field, name, BitField) \
2566 : typename BitField::FieldType holder##Ref::name() const { \
2567 : IF_BROKER_DISABLED_ACCESS_HANDLE_C(holder, name); \
2568 : return BitField::decode(ObjectRef::data()->As##holder()->field()); \
2569 : }
2570 :
2571 37692 : BIMODAL_ACCESSOR(AllocationSite, Object, nested_site)
2572 1611 : BIMODAL_ACCESSOR_C(AllocationSite, bool, CanInlineCall)
2573 23355 : BIMODAL_ACCESSOR_C(AllocationSite, bool, PointsToLiteral)
2574 9018 : BIMODAL_ACCESSOR_C(AllocationSite, ElementsKind, GetElementsKind)
2575 15116 : BIMODAL_ACCESSOR_C(AllocationSite, AllocationType, GetAllocationType)
2576 :
2577 1515 : BIMODAL_ACCESSOR_C(BytecodeArray, int, register_count)
2578 :
2579 75783 : BIMODAL_ACCESSOR(Cell, Object, value)
2580 :
2581 203850022 : BIMODAL_ACCESSOR(HeapObject, Map, map)
2582 :
2583 12729 : BIMODAL_ACCESSOR(JSArray, Object, length)
2584 :
2585 648 : BIMODAL_ACCESSOR(JSBoundFunction, Object, bound_target_function)
2586 477 : BIMODAL_ACCESSOR(JSBoundFunction, Object, bound_this)
2587 648 : BIMODAL_ACCESSOR(JSBoundFunction, FixedArray, bound_arguments)
2588 :
2589 848 : BIMODAL_ACCESSOR_C(JSDataView, size_t, byte_length)
2590 424 : BIMODAL_ACCESSOR_C(JSDataView, size_t, byte_offset)
2591 :
2592 232 : BIMODAL_ACCESSOR_C(JSFunction, bool, has_feedback_vector)
2593 21809 : BIMODAL_ACCESSOR_C(JSFunction, bool, has_initial_map)
2594 4560 : BIMODAL_ACCESSOR_C(JSFunction, bool, has_prototype)
2595 4458 : BIMODAL_ACCESSOR_C(JSFunction, bool, PrototypeRequiresRuntimeLookup)
2596 4797 : BIMODAL_ACCESSOR(JSFunction, Context, context)
2597 1002285 : BIMODAL_ACCESSOR(JSFunction, NativeContext, native_context)
2598 89943 : BIMODAL_ACCESSOR(JSFunction, Map, initial_map)
2599 5396 : BIMODAL_ACCESSOR(JSFunction, Object, prototype)
2600 1667877 : BIMODAL_ACCESSOR(JSFunction, SharedFunctionInfo, shared)
2601 348 : BIMODAL_ACCESSOR(JSFunction, FeedbackVector, feedback_vector)
2602 :
2603 8420 : BIMODAL_ACCESSOR_C(JSTypedArray, bool, is_on_heap)
2604 2692 : BIMODAL_ACCESSOR_C(JSTypedArray, size_t, length)
2605 4038 : BIMODAL_ACCESSOR(JSTypedArray, HeapObject, buffer)
2606 :
2607 2168435 : BIMODAL_ACCESSOR_B(Map, bit_field2, elements_kind, Map::ElementsKindBits)
2608 0 : BIMODAL_ACCESSOR_B(Map, bit_field2, is_extensible, Map::IsExtensibleBit)
2609 0 : BIMODAL_ACCESSOR_B(Map, bit_field3, is_deprecated, Map::IsDeprecatedBit)
2610 410 : BIMODAL_ACCESSOR_B(Map, bit_field3, is_dictionary_map, Map::IsDictionaryMapBit)
2611 28004 : BIMODAL_ACCESSOR_B(Map, bit_field3, NumberOfOwnDescriptors,
2612 : Map::NumberOfOwnDescriptorsBits)
2613 296 : BIMODAL_ACCESSOR_B(Map, bit_field3, has_hidden_prototype,
2614 : Map::HasHiddenPrototypeBit)
2615 185986 : BIMODAL_ACCESSOR_B(Map, bit_field3, is_migration_target,
2616 : Map::IsMigrationTargetBit)
2617 157862 : BIMODAL_ACCESSOR_B(Map, bit_field, has_prototype_slot, Map::HasPrototypeSlotBit)
2618 108736 : BIMODAL_ACCESSOR_B(Map, bit_field, is_access_check_needed,
2619 : Map::IsAccessCheckNeededBit)
2620 66872856 : BIMODAL_ACCESSOR_B(Map, bit_field, is_callable, Map::IsCallableBit)
2621 105270 : BIMODAL_ACCESSOR_B(Map, bit_field, has_indexed_interceptor,
2622 : Map::HasIndexedInterceptorBit)
2623 49164 : BIMODAL_ACCESSOR_B(Map, bit_field, is_constructor, Map::IsConstructorBit)
2624 66845120 : BIMODAL_ACCESSOR_B(Map, bit_field, is_undetectable, Map::IsUndetectableBit)
2625 143496 : BIMODAL_ACCESSOR_C(Map, int, instance_size)
2626 6885 : BIMODAL_ACCESSOR_C(Map, int, NextFreePropertyIndex)
2627 65955 : BIMODAL_ACCESSOR_C(Map, int, UnusedPropertyFields)
2628 307062 : BIMODAL_ACCESSOR(Map, HeapObject, prototype)
2629 102147358 : BIMODAL_ACCESSOR_C(Map, InstanceType, instance_type)
2630 28726 : BIMODAL_ACCESSOR(Map, Object, GetConstructor)
2631 87940 : BIMODAL_ACCESSOR(Map, HeapObject, GetBackPointer)
2632 :
2633 : #define DEF_NATIVE_CONTEXT_ACCESSOR(type, name) \
2634 : BIMODAL_ACCESSOR(NativeContext, type, name)
2635 465984 : BROKER_NATIVE_CONTEXT_FIELDS(DEF_NATIVE_CONTEXT_ACCESSOR)
2636 : #undef DEF_NATIVE_CONTEXT_ACCESSOR
2637 :
2638 645786 : BIMODAL_ACCESSOR(PropertyCell, Object, value)
2639 1131798 : BIMODAL_ACCESSOR_C(PropertyCell, PropertyDetails, property_details)
2640 :
2641 384 : BIMODAL_ACCESSOR(FunctionTemplateInfo, Object, call_code)
2642 :
2643 384 : BIMODAL_ACCESSOR(CallHandlerInfo, Object, data)
2644 :
2645 280965 : BIMODAL_ACCESSOR_C(SharedFunctionInfo, int, builtin_id)
2646 437983 : BIMODAL_ACCESSOR(SharedFunctionInfo, BytecodeArray, GetBytecodeArray)
2647 : #define DEF_SFI_ACCESSOR(type, name) \
2648 : BIMODAL_ACCESSOR_C(SharedFunctionInfo, type, name)
2649 3438125 : BROKER_SFI_FIELDS(DEF_SFI_ACCESSOR)
2650 : #undef DEF_SFI_ACCESSOR
2651 :
2652 164225 : BIMODAL_ACCESSOR_C(String, int, length)
2653 :
2654 1346 : void* JSTypedArrayRef::elements_external_pointer() const {
2655 1346 : if (broker()->mode() == JSHeapBroker::kDisabled) {
2656 : AllowHandleDereference allow_handle_dereference;
2657 : return FixedTypedArrayBase::cast(object()->elements())->external_pointer();
2658 : }
2659 0 : return data()->AsJSTypedArray()->elements_external_pointer();
2660 : }
2661 :
2662 32 : bool MapRef::IsInobjectSlackTrackingInProgress() const {
2663 32 : IF_BROKER_DISABLED_ACCESS_HANDLE_C(Map, IsInobjectSlackTrackingInProgress);
2664 32 : return Map::ConstructionCounterBits::decode(data()->AsMap()->bit_field3()) !=
2665 32 : Map::kNoSlackTracking;
2666 : }
2667 :
2668 8123 : int MapRef::constructor_function_index() const {
2669 8123 : IF_BROKER_DISABLED_ACCESS_HANDLE_C(Map, GetConstructorFunctionIndex);
2670 0 : CHECK(IsPrimitiveMap());
2671 0 : return data()->AsMap()->constructor_function_index();
2672 : }
2673 :
2674 232152 : bool MapRef::is_stable() const {
2675 232152 : IF_BROKER_DISABLED_ACCESS_HANDLE_C(Map, is_stable);
2676 27386 : return !Map::IsUnstableBit::decode(data()->AsMap()->bit_field3());
2677 : }
2678 :
2679 22030 : bool MapRef::CanBeDeprecated() const {
2680 44060 : IF_BROKER_DISABLED_ACCESS_HANDLE_C(Map, CanBeDeprecated);
2681 0 : CHECK_GT(NumberOfOwnDescriptors(), 0);
2682 0 : return data()->AsMap()->can_be_deprecated();
2683 : }
2684 :
2685 164472 : bool MapRef::CanTransition() const {
2686 164472 : IF_BROKER_DISABLED_ACCESS_HANDLE_C(Map, CanTransition);
2687 43 : return data()->AsMap()->can_transition();
2688 : }
2689 :
2690 40982 : int MapRef::GetInObjectPropertiesStartInWords() const {
2691 40982 : IF_BROKER_DISABLED_ACCESS_HANDLE_C(Map, GetInObjectPropertiesStartInWords);
2692 81962 : return data()->AsMap()->in_object_properties_start_in_words();
2693 : }
2694 :
2695 79217 : int MapRef::GetInObjectProperties() const {
2696 81656 : IF_BROKER_DISABLED_ACCESS_HANDLE_C(Map, GetInObjectProperties);
2697 153556 : return data()->AsMap()->in_object_properties();
2698 : }
2699 :
2700 9400 : int ScopeInfoRef::ContextLength() const {
2701 9400 : IF_BROKER_DISABLED_ACCESS_HANDLE_C(ScopeInfo, ContextLength);
2702 9400 : return data()->AsScopeInfo()->context_length();
2703 : }
2704 :
2705 0 : bool StringRef::IsExternalString() const {
2706 0 : IF_BROKER_DISABLED_ACCESS_HANDLE_C(String, IsExternalString);
2707 0 : return data()->AsString()->is_external_string();
2708 : }
2709 :
2710 128 : Address CallHandlerInfoRef::callback() const {
2711 128 : if (broker()->mode() == JSHeapBroker::kDisabled) {
2712 : return v8::ToCData<Address>(object()->callback());
2713 : }
2714 0 : return HeapObjectRef::data()->AsCallHandlerInfo()->callback();
2715 : }
2716 :
2717 0 : bool StringRef::IsSeqString() const {
2718 0 : IF_BROKER_DISABLED_ACCESS_HANDLE_C(String, IsSeqString);
2719 0 : return data()->AsString()->is_seq_string();
2720 : }
2721 :
2722 32152 : MapRef NativeContextRef::GetFunctionMapFromIndex(int index) const {
2723 : DCHECK_GE(index, Context::FIRST_FUNCTION_MAP_INDEX);
2724 : DCHECK_LE(index, Context::LAST_FUNCTION_MAP_INDEX);
2725 32152 : if (broker()->mode() == JSHeapBroker::kDisabled) {
2726 0 : return get(index).AsMap();
2727 : }
2728 32152 : return MapRef(broker(), data()->AsNativeContext()->function_maps().at(
2729 96456 : index - Context::FIRST_FUNCTION_MAP_INDEX));
2730 : }
2731 :
2732 2118 : MapRef NativeContextRef::GetInitialJSArrayMap(ElementsKind kind) const {
2733 2118 : switch (kind) {
2734 : case PACKED_SMI_ELEMENTS:
2735 910 : return js_array_packed_smi_elements_map();
2736 : case HOLEY_SMI_ELEMENTS:
2737 46 : return js_array_holey_smi_elements_map();
2738 : case PACKED_DOUBLE_ELEMENTS:
2739 42 : return js_array_packed_double_elements_map();
2740 : case HOLEY_DOUBLE_ELEMENTS:
2741 354 : return js_array_holey_double_elements_map();
2742 : case PACKED_ELEMENTS:
2743 430 : return js_array_packed_elements_map();
2744 : case HOLEY_ELEMENTS:
2745 336 : return js_array_holey_elements_map();
2746 : default:
2747 0 : UNREACHABLE();
2748 : }
2749 : }
2750 :
2751 8123 : base::Optional<JSFunctionRef> NativeContextRef::GetConstructorFunction(
2752 : const MapRef& map) const {
2753 8123 : CHECK(map.IsPrimitiveMap());
2754 8123 : switch (map.constructor_function_index()) {
2755 : case Map::kNoConstructorFunctionIndex:
2756 : return base::nullopt;
2757 : case Context::BIGINT_FUNCTION_INDEX:
2758 0 : return bigint_function();
2759 : case Context::BOOLEAN_FUNCTION_INDEX:
2760 1054 : return boolean_function();
2761 : case Context::NUMBER_FUNCTION_INDEX:
2762 2768 : return number_function();
2763 : case Context::STRING_FUNCTION_INDEX:
2764 12354 : return string_function();
2765 : case Context::SYMBOL_FUNCTION_INDEX:
2766 70 : return symbol_function();
2767 : default:
2768 0 : UNREACHABLE();
2769 : }
2770 : }
2771 :
2772 159 : bool ObjectRef::IsNullOrUndefined() const {
2773 159 : if (IsSmi()) return false;
2774 159 : OddballType type = AsHeapObject().map().oddball_type();
2775 159 : return type == OddballType::kNull || type == OddballType::kUndefined;
2776 : }
2777 :
2778 120580 : bool ObjectRef::BooleanValue() const {
2779 120580 : if (broker()->mode() == JSHeapBroker::kDisabled) {
2780 : AllowHandleDereference allow_handle_dereference;
2781 9613 : return object()->BooleanValue(broker()->isolate());
2782 : }
2783 110968 : return IsSmi() ? (AsSmi() != 0) : data()->AsHeapObject()->boolean_value();
2784 : }
2785 :
2786 1086 : Maybe<double> ObjectRef::OddballToNumber() const {
2787 1086 : OddballType type = AsHeapObject().map().oddball_type();
2788 :
2789 1086 : switch (type) {
2790 : case OddballType::kBoolean: {
2791 : ObjectRef true_ref(broker(),
2792 494 : broker()->isolate()->factory()->true_value());
2793 494 : return this->equals(true_ref) ? Just(1.0) : Just(0.0);
2794 : break;
2795 : }
2796 : case OddballType::kUndefined: {
2797 : return Just(std::numeric_limits<double>::quiet_NaN());
2798 : break;
2799 : }
2800 : case OddballType::kNull: {
2801 : return Just(0.0);
2802 : break;
2803 : }
2804 : default: {
2805 : return Nothing<double>();
2806 : break;
2807 : }
2808 : }
2809 : }
2810 :
2811 1565 : base::Optional<ObjectRef> ObjectRef::GetOwnConstantElement(
2812 : uint32_t index, bool serialize) const {
2813 1565 : if (broker()->mode() == JSHeapBroker::kDisabled) {
2814 73 : return (IsJSObject() || IsString())
2815 : ? GetOwnElementFromHeap(broker(), object(), index, true)
2816 3106 : : base::nullopt;
2817 : }
2818 : ObjectData* element = nullptr;
2819 9 : if (IsJSObject()) {
2820 : element =
2821 18 : data()->AsJSObject()->GetOwnConstantElement(broker(), index, serialize);
2822 0 : } else if (IsString()) {
2823 0 : element = data()->AsString()->GetCharAsString(broker(), index, serialize);
2824 : }
2825 9 : if (element == nullptr) return base::nullopt;
2826 : return ObjectRef(broker(), element);
2827 : }
2828 :
2829 1038 : base::Optional<ObjectRef> JSArrayRef::GetOwnCowElement(uint32_t index,
2830 : bool serialize) const {
2831 1038 : if (broker()->mode() == JSHeapBroker::kDisabled) {
2832 1038 : if (!object()->elements()->IsCowArray()) return base::nullopt;
2833 92 : return GetOwnElementFromHeap(broker(), object(), index, false);
2834 : }
2835 :
2836 0 : if (serialize) {
2837 0 : data()->AsJSObject()->SerializeElements(broker());
2838 0 : } else if (!data()->AsJSObject()->serialized_elements()) {
2839 0 : TRACE(broker(), "'elements' on data " << this);
2840 : return base::nullopt;
2841 : }
2842 0 : if (!elements().map().IsFixedCowArrayMap()) return base::nullopt;
2843 :
2844 : ObjectData* element =
2845 0 : data()->AsJSArray()->GetOwnElement(broker(), index, serialize);
2846 0 : if (element == nullptr) return base::nullopt;
2847 : return ObjectRef(broker(), element);
2848 : }
2849 :
2850 2723081 : double HeapNumberRef::value() const {
2851 2723081 : IF_BROKER_DISABLED_ACCESS_HANDLE_C(HeapNumber, value);
2852 146 : return data()->AsHeapNumber()->value();
2853 : }
2854 :
2855 0 : double MutableHeapNumberRef::value() const {
2856 0 : IF_BROKER_DISABLED_ACCESS_HANDLE_C(MutableHeapNumber, value);
2857 0 : return data()->AsMutableHeapNumber()->value();
2858 : }
2859 :
2860 138 : CellRef ModuleRef::GetCell(int cell_index) const {
2861 138 : if (broker()->mode() == JSHeapBroker::kDisabled) {
2862 : AllowHandleAllocation handle_allocation;
2863 : AllowHandleDereference allow_handle_dereference;
2864 : return CellRef(broker(),
2865 0 : handle(object()->GetCell(cell_index), broker()->isolate()));
2866 : }
2867 276 : return CellRef(broker(), data()->AsModule()->GetCell(cell_index));
2868 : }
2869 :
2870 72479944 : ObjectRef::ObjectRef(JSHeapBroker* broker, Handle<Object> object)
2871 72479944 : : broker_(broker) {
2872 72479944 : switch (broker->mode()) {
2873 : case JSHeapBroker::kSerialized:
2874 51583409 : data_ = broker->GetData(object);
2875 51583409 : break;
2876 : case JSHeapBroker::kSerializing:
2877 8872048 : data_ = broker->GetOrCreateData(object);
2878 8872042 : break;
2879 : case JSHeapBroker::kDisabled: {
2880 : RefsMap::Entry* entry =
2881 12024947 : broker->refs_->LookupOrInsert(object.address(), broker->zone());
2882 12024947 : ObjectData** storage = &(entry->value);
2883 12024947 : if (*storage == nullptr) {
2884 : AllowHandleDereference handle_dereference;
2885 : entry->value = new (broker->zone())
2886 : ObjectData(broker, storage, object,
2887 5947662 : object->IsSmi() ? kSmi : kUnserializedHeapObject);
2888 : }
2889 12024945 : data_ = *storage;
2890 12024945 : break;
2891 : }
2892 : case JSHeapBroker::kRetired:
2893 0 : UNREACHABLE();
2894 : }
2895 72480046 : CHECK_WITH_MSG(data_ != nullptr, "Object is not known to the heap broker");
2896 72480046 : }
2897 :
2898 : namespace {
2899 2716803 : OddballType GetOddballType(Isolate* isolate, Map map) {
2900 2716803 : if (map->instance_type() != ODDBALL_TYPE) {
2901 : return OddballType::kNone;
2902 : }
2903 : ReadOnlyRoots roots(isolate);
2904 592795 : if (map == roots.undefined_map()) {
2905 : return OddballType::kUndefined;
2906 : }
2907 554785 : if (map == roots.null_map()) {
2908 : return OddballType::kNull;
2909 : }
2910 554607 : if (map == roots.boolean_map()) {
2911 : return OddballType::kBoolean;
2912 : }
2913 540728 : if (map == roots.the_hole_map()) {
2914 : return OddballType::kHole;
2915 : }
2916 540049 : if (map == roots.uninitialized_map()) {
2917 : return OddballType::kUninitialized;
2918 : }
2919 : DCHECK(map == roots.termination_exception_map() ||
2920 : map == roots.arguments_marker_map() ||
2921 : map == roots.optimized_out_map() || map == roots.stale_register_map());
2922 0 : return OddballType::kOther;
2923 : }
2924 : } // namespace
2925 :
2926 19424809 : HeapObjectType HeapObjectRef::GetHeapObjectType() const {
2927 19424809 : if (broker()->mode() == JSHeapBroker::kDisabled) {
2928 : AllowHandleDereference handle_dereference;
2929 : Map map = Handle<HeapObject>::cast(object())->map();
2930 : HeapObjectType::Flags flags(0);
2931 2716803 : if (map->is_undetectable()) flags |= HeapObjectType::kUndetectable;
2932 2716803 : if (map->is_callable()) flags |= HeapObjectType::kCallable;
2933 : return HeapObjectType(map->instance_type(), flags,
2934 5433606 : GetOddballType(broker()->isolate(), map));
2935 : }
2936 : HeapObjectType::Flags flags(0);
2937 16708006 : if (map().is_undetectable()) flags |= HeapObjectType::kUndetectable;
2938 16707976 : if (map().is_callable()) flags |= HeapObjectType::kCallable;
2939 16707954 : return HeapObjectType(map().instance_type(), flags, map().oddball_type());
2940 : }
2941 12337 : base::Optional<JSObjectRef> AllocationSiteRef::boilerplate() const {
2942 12337 : if (broker()->mode() == JSHeapBroker::kDisabled) {
2943 : AllowHandleAllocation handle_allocation;
2944 : AllowHandleDereference allow_handle_dereference;
2945 : return JSObjectRef(broker(),
2946 0 : handle(object()->boilerplate(), broker()->isolate()));
2947 : }
2948 12337 : JSObjectData* boilerplate = data()->AsAllocationSite()->boilerplate();
2949 12337 : if (boilerplate) {
2950 : return JSObjectRef(broker(), boilerplate);
2951 : } else {
2952 : return base::nullopt;
2953 : }
2954 : }
2955 :
2956 10525 : ElementsKind JSObjectRef::GetElementsKind() const {
2957 10525 : return map().elements_kind();
2958 : }
2959 :
2960 7709 : FixedArrayBaseRef JSObjectRef::elements() const {
2961 7709 : if (broker()->mode() == JSHeapBroker::kDisabled) {
2962 : AllowHandleAllocation handle_allocation;
2963 : AllowHandleDereference allow_handle_dereference;
2964 : return FixedArrayBaseRef(broker(),
2965 92 : handle(object()->elements(), broker()->isolate()));
2966 : }
2967 15234 : return FixedArrayBaseRef(broker(), data()->AsJSObject()->elements());
2968 : }
2969 :
2970 289920 : int FixedArrayBaseRef::length() const {
2971 289920 : IF_BROKER_DISABLED_ACCESS_HANDLE_C(FixedArrayBase, length);
2972 14216 : return data()->AsFixedArrayBase()->length();
2973 : }
2974 :
2975 7549 : ObjectData* FixedArrayData::Get(int i) const {
2976 7549 : CHECK_LT(i, static_cast<int>(contents_.size()));
2977 15098 : CHECK_NOT_NULL(contents_[i]);
2978 7549 : return contents_[i];
2979 : }
2980 :
2981 21435 : Float64 FixedDoubleArrayData::Get(int i) const {
2982 21435 : CHECK_LT(i, static_cast<int>(contents_.size()));
2983 42870 : return contents_[i];
2984 : }
2985 :
2986 53205 : void FeedbackVectorRef::SerializeSlots() {
2987 53205 : data()->AsFeedbackVector()->SerializeSlots(broker());
2988 53205 : }
2989 :
2990 0 : bool NameRef::IsUniqueName() const {
2991 : // Must match Name::IsUniqueName.
2992 0 : return IsInternalizedString() || IsSymbol();
2993 : }
2994 :
2995 576 : ObjectRef JSRegExpRef::data() const {
2996 576 : IF_BROKER_DISABLED_ACCESS_HANDLE(JSRegExp, Object, data);
2997 1152 : return ObjectRef(broker(), ObjectRef::data()->AsJSRegExp()->data());
2998 : }
2999 :
3000 576 : ObjectRef JSRegExpRef::flags() const {
3001 576 : IF_BROKER_DISABLED_ACCESS_HANDLE(JSRegExp, Object, flags);
3002 1152 : return ObjectRef(broker(), ObjectRef::data()->AsJSRegExp()->flags());
3003 : }
3004 :
3005 576 : ObjectRef JSRegExpRef::last_index() const {
3006 576 : IF_BROKER_DISABLED_ACCESS_HANDLE(JSRegExp, Object, last_index);
3007 1152 : return ObjectRef(broker(), ObjectRef::data()->AsJSRegExp()->last_index());
3008 : }
3009 :
3010 576 : ObjectRef JSRegExpRef::raw_properties_or_hash() const {
3011 576 : IF_BROKER_DISABLED_ACCESS_HANDLE(JSRegExp, Object, raw_properties_or_hash);
3012 : return ObjectRef(broker(),
3013 1152 : ObjectRef::data()->AsJSRegExp()->raw_properties_or_hash());
3014 : }
3015 :
3016 576 : ObjectRef JSRegExpRef::source() const {
3017 576 : IF_BROKER_DISABLED_ACCESS_HANDLE(JSRegExp, Object, source);
3018 1152 : return ObjectRef(broker(), ObjectRef::data()->AsJSRegExp()->source());
3019 : }
3020 :
3021 921499 : Handle<Object> ObjectRef::object() const { return data_->object(); }
3022 :
3023 : #define DEF_OBJECT_GETTER(T) \
3024 : Handle<T> T##Ref::object() const { \
3025 : return Handle<T>(reinterpret_cast<Address*>(data_->object().address())); \
3026 : }
3027 41611993 : HEAP_BROKER_OBJECT_LIST(DEF_OBJECT_GETTER)
3028 : #undef DEF_OBJECT_GETTER
3029 :
3030 441743878 : JSHeapBroker* ObjectRef::broker() const { return broker_; }
3031 :
3032 216588772 : ObjectData* ObjectRef::data() const {
3033 216588772 : switch (broker()->mode()) {
3034 : case JSHeapBroker::kDisabled:
3035 22348508 : CHECK_NE(data_->kind(), kSerializedHeapObject);
3036 : return data_;
3037 : case JSHeapBroker::kSerializing:
3038 : case JSHeapBroker::kSerialized:
3039 194240264 : CHECK_NE(data_->kind(), kUnserializedHeapObject);
3040 : return data_;
3041 : case JSHeapBroker::kRetired:
3042 0 : UNREACHABLE();
3043 : }
3044 0 : }
3045 :
3046 0 : Reduction NoChangeBecauseOfMissingData(JSHeapBroker* broker,
3047 : const char* function, int line) {
3048 0 : TRACE_MISSING(broker, "data in function " << function << " at line " << line);
3049 0 : return AdvancedReducer::NoChange();
3050 : }
3051 :
3052 464120 : NativeContextData::NativeContextData(JSHeapBroker* broker, ObjectData** storage,
3053 : Handle<NativeContext> object)
3054 928236 : : ContextData(broker, storage, object), function_maps_(broker->zone()) {}
3055 :
3056 464111 : void NativeContextData::Serialize(JSHeapBroker* broker) {
3057 464111 : if (serialized_) return;
3058 464111 : serialized_ = true;
3059 :
3060 464111 : TraceScope tracer(broker, this, "NativeContextData::Serialize");
3061 : Handle<NativeContext> context = Handle<NativeContext>::cast(object());
3062 :
3063 : #define SERIALIZE_MEMBER(type, name) \
3064 : DCHECK_NULL(name##_); \
3065 : name##_ = broker->GetOrCreateData(context->name())->As##type(); \
3066 : if (name##_->IsJSFunction()) name##_->AsJSFunction()->Serialize(broker); \
3067 : if (name##_->IsMap()) name##_->AsMap()->SerializeConstructor(broker);
3068 14387513 : BROKER_COMPULSORY_NATIVE_CONTEXT_FIELDS(SERIALIZE_MEMBER)
3069 464114 : if (!broker->isolate()->bootstrapper()->IsActive()) {
3070 2780658 : BROKER_OPTIONAL_NATIVE_CONTEXT_FIELDS(SERIALIZE_MEMBER)
3071 : }
3072 : #undef SERIALIZE_MEMBER
3073 :
3074 464114 : bound_function_with_constructor_map_->SerializePrototype(broker);
3075 464113 : bound_function_without_constructor_map_->SerializePrototype(broker);
3076 :
3077 : DCHECK(function_maps_.empty());
3078 : int const first = Context::FIRST_FUNCTION_MAP_INDEX;
3079 : int const last = Context::LAST_FUNCTION_MAP_INDEX;
3080 464113 : function_maps_.reserve(last + 1 - first);
3081 22741460 : for (int i = first; i <= last; ++i) {
3082 33416019 : function_maps_.push_back(broker->GetOrCreateData(context->get(i))->AsMap());
3083 : }
3084 : }
3085 :
3086 1341523 : void JSFunctionRef::Serialize() {
3087 1341523 : if (broker()->mode() == JSHeapBroker::kDisabled) return;
3088 1040768 : CHECK_EQ(broker()->mode(), JSHeapBroker::kSerializing);
3089 1040768 : data()->AsJSFunction()->Serialize(broker());
3090 : }
3091 :
3092 116 : bool JSFunctionRef::serialized() const {
3093 116 : CHECK_NE(broker()->mode(), JSHeapBroker::kDisabled);
3094 116 : return data()->AsJSFunction()->serialized();
3095 : }
3096 :
3097 98058 : bool JSFunctionRef::IsSerializedForCompilation() const {
3098 98058 : if (broker()->mode() == JSHeapBroker::kDisabled) {
3099 97942 : return handle(object()->shared(), broker()->isolate())->HasBytecodeArray();
3100 : }
3101 :
3102 : // We get a crash if we try to access the shared() getter without
3103 : // checking for `serialized` first. Also it's possible to have a
3104 : // JSFunctionRef without a feedback vector.
3105 232 : return serialized() && has_feedback_vector() &&
3106 232 : shared().IsSerializedForCompilation(feedback_vector());
3107 : }
3108 :
3109 162 : void SharedFunctionInfoRef::SetSerializedForCompilation(
3110 : FeedbackVectorRef feedback) {
3111 162 : CHECK_EQ(broker()->mode(), JSHeapBroker::kSerializing);
3112 162 : data()->AsSharedFunctionInfo()->SetSerializedForCompilation(broker(),
3113 162 : feedback);
3114 162 : }
3115 :
3116 416 : bool SharedFunctionInfoRef::IsSerializedForCompilation(
3117 : FeedbackVectorRef feedback) const {
3118 416 : CHECK_NE(broker()->mode(), JSHeapBroker::kDisabled);
3119 832 : return data()->AsSharedFunctionInfo()->IsSerializedForCompilation(feedback);
3120 : }
3121 :
3122 1141481 : void JSObjectRef::SerializeObjectCreateMap() {
3123 1141481 : if (broker()->mode() == JSHeapBroker::kDisabled) return;
3124 1141481 : CHECK_EQ(broker()->mode(), JSHeapBroker::kSerializing);
3125 1141481 : data()->AsJSObject()->SerializeObjectCreateMap(broker());
3126 : }
3127 :
3128 182767 : void MapRef::SerializeOwnDescriptors() {
3129 182767 : if (broker()->mode() == JSHeapBroker::kDisabled) return;
3130 16 : CHECK_EQ(broker()->mode(), JSHeapBroker::kSerializing);
3131 16 : data()->AsMap()->SerializeOwnDescriptors(broker());
3132 : }
3133 :
3134 21985 : void MapRef::SerializeBackPointer() {
3135 21985 : if (broker()->mode() == JSHeapBroker::kDisabled) return;
3136 0 : CHECK_EQ(broker()->mode(), JSHeapBroker::kSerializing);
3137 0 : data()->AsMap()->SerializeBackPointer(broker());
3138 : }
3139 :
3140 92684 : void MapRef::SerializePrototype() {
3141 92684 : if (broker()->mode() == JSHeapBroker::kDisabled) return;
3142 5 : CHECK_EQ(broker()->mode(), JSHeapBroker::kSerializing);
3143 5 : data()->AsMap()->SerializePrototype(broker());
3144 : }
3145 :
3146 5 : bool MapRef::serialized_prototype() const {
3147 5 : CHECK_NE(broker()->mode(), JSHeapBroker::kDisabled);
3148 5 : return data()->AsMap()->serialized_prototype();
3149 : }
3150 :
3151 170 : void ModuleRef::Serialize() {
3152 170 : if (broker()->mode() == JSHeapBroker::kDisabled) return;
3153 170 : CHECK_EQ(broker()->mode(), JSHeapBroker::kSerializing);
3154 170 : data()->AsModule()->Serialize(broker());
3155 : }
3156 :
3157 1358167 : void ContextRef::SerializeContextChain() {
3158 1358167 : if (broker()->mode() == JSHeapBroker::kDisabled) return;
3159 1084248 : CHECK_EQ(broker()->mode(), JSHeapBroker::kSerializing);
3160 1084248 : data()->AsContext()->SerializeContextChain(broker());
3161 : }
3162 :
3163 27740 : void ContextRef::SerializeSlot(int index) {
3164 27740 : if (broker()->mode() == JSHeapBroker::kDisabled) return;
3165 16 : CHECK_EQ(broker()->mode(), JSHeapBroker::kSerializing);
3166 16 : data()->AsContext()->SerializeSlot(broker(), index);
3167 : }
3168 :
3169 464112 : void NativeContextRef::Serialize() {
3170 464112 : if (broker()->mode() == JSHeapBroker::kDisabled) return;
3171 464112 : CHECK_EQ(broker()->mode(), JSHeapBroker::kSerializing);
3172 464112 : data()->AsNativeContext()->Serialize(broker());
3173 : }
3174 :
3175 1346 : void JSTypedArrayRef::Serialize() {
3176 1346 : if (broker()->mode() == JSHeapBroker::kDisabled) return;
3177 0 : CHECK_EQ(broker()->mode(), JSHeapBroker::kSerializing);
3178 0 : data()->AsJSTypedArray()->Serialize(broker());
3179 : }
3180 :
3181 0 : bool JSTypedArrayRef::serialized() const {
3182 0 : CHECK_NE(broker()->mode(), JSHeapBroker::kDisabled);
3183 0 : return data()->AsJSTypedArray()->serialized();
3184 : }
3185 :
3186 216 : void JSBoundFunctionRef::Serialize() {
3187 216 : if (broker()->mode() == JSHeapBroker::kDisabled) return;
3188 0 : CHECK_EQ(broker()->mode(), JSHeapBroker::kSerializing);
3189 0 : data()->AsJSBoundFunction()->Serialize(broker());
3190 : }
3191 :
3192 194305 : void PropertyCellRef::Serialize() {
3193 194305 : if (broker()->mode() == JSHeapBroker::kDisabled) return;
3194 0 : CHECK_EQ(broker()->mode(), JSHeapBroker::kSerializing);
3195 0 : data()->AsPropertyCell()->Serialize(broker());
3196 : }
3197 :
3198 128 : void FunctionTemplateInfoRef::Serialize() {
3199 128 : if (broker()->mode() == JSHeapBroker::kDisabled) return;
3200 0 : CHECK_EQ(broker()->mode(), JSHeapBroker::kSerializing);
3201 0 : data()->AsFunctionTemplateInfo()->Serialize(broker());
3202 : }
3203 :
3204 246 : base::Optional<PropertyCellRef> JSGlobalProxyRef::GetPropertyCell(
3205 : NameRef const& name, bool serialize) const {
3206 246 : if (broker()->mode() == JSHeapBroker::kDisabled) {
3207 246 : return GetPropertyCellFromHeap(broker(), name.object());
3208 : }
3209 : PropertyCellData* property_cell_data =
3210 0 : data()->AsJSGlobalProxy()->GetPropertyCell(
3211 0 : broker(), name.data()->AsName(), serialize);
3212 0 : if (property_cell_data == nullptr) return base::nullopt;
3213 : return PropertyCellRef(broker(), property_cell_data);
3214 : }
3215 :
3216 54381 : bool CanInlineElementAccess(MapRef const& map) {
3217 54381 : if (!map.IsJSObjectMap()) return false;
3218 52740 : if (map.is_access_check_needed()) return false;
3219 52635 : if (map.has_indexed_interceptor()) return false;
3220 52627 : ElementsKind const elements_kind = map.elements_kind();
3221 52627 : if (IsFastElementsKind(elements_kind)) return true;
3222 16254 : if (IsFixedTypedArrayElementsKind(elements_kind) &&
3223 16254 : elements_kind != BIGUINT64_ELEMENTS &&
3224 : elements_kind != BIGINT64_ELEMENTS) {
3225 : return true;
3226 : }
3227 2368 : return false;
3228 : }
3229 :
3230 0 : GlobalAccessFeedback::GlobalAccessFeedback(PropertyCellRef cell)
3231 : : ProcessedFeedback(kGlobalAccess),
3232 : cell_or_context_(cell),
3233 194305 : index_and_immutable_(0 /* doesn't matter */) {}
3234 :
3235 0 : GlobalAccessFeedback::GlobalAccessFeedback(ContextRef script_context,
3236 : int slot_index, bool immutable)
3237 : : ProcessedFeedback(kGlobalAccess),
3238 : cell_or_context_(script_context),
3239 109 : index_and_immutable_(FeedbackNexus::SlotIndexBits::encode(slot_index) |
3240 218 : FeedbackNexus::ImmutabilityBit::encode(immutable)) {
3241 : DCHECK_EQ(this->slot_index(), slot_index);
3242 : DCHECK_EQ(this->immutable(), immutable);
3243 0 : }
3244 :
3245 388719 : bool GlobalAccessFeedback::IsPropertyCell() const {
3246 777656 : return cell_or_context_.IsPropertyCell();
3247 : }
3248 194305 : PropertyCellRef GlobalAccessFeedback::property_cell() const {
3249 : DCHECK(IsPropertyCell());
3250 194305 : return cell_or_context_.AsPropertyCell();
3251 : }
3252 109 : ContextRef GlobalAccessFeedback::script_context() const {
3253 : DCHECK(IsScriptContextSlot());
3254 109 : return cell_or_context_.AsContext();
3255 : }
3256 109 : int GlobalAccessFeedback::slot_index() const {
3257 109 : CHECK(IsScriptContextSlot());
3258 218 : return FeedbackNexus::SlotIndexBits::decode(index_and_immutable_);
3259 : }
3260 109 : bool GlobalAccessFeedback::immutable() const {
3261 109 : CHECK(IsScriptContextSlot());
3262 218 : return FeedbackNexus::ImmutabilityBit::decode(index_and_immutable_);
3263 : }
3264 :
3265 0 : base::Optional<ObjectRef> GlobalAccessFeedback::GetConstantHint() const {
3266 0 : if (IsScriptContextSlot()) {
3267 0 : if (immutable()) return script_context().get(slot_index());
3268 : } else {
3269 0 : return property_cell().value();
3270 : }
3271 0 : return {};
3272 : }
3273 :
3274 0 : ElementAccessFeedback::ElementAccessFeedback(Zone* zone)
3275 : : ProcessedFeedback(kElementAccess),
3276 : receiver_maps(zone),
3277 0 : transitions(zone) {}
3278 :
3279 14996 : ElementAccessFeedback::MapIterator::MapIterator(
3280 : ElementAccessFeedback const& processed, JSHeapBroker* broker)
3281 14996 : : processed_(processed), broker_(broker) {
3282 29992 : CHECK_LT(processed.receiver_maps.size(),
3283 : std::numeric_limits<size_t>::max() - processed.transitions.size());
3284 14996 : }
3285 :
3286 30226 : bool ElementAccessFeedback::MapIterator::done() const {
3287 61900 : return index_ >=
3288 123800 : processed_.receiver_maps.size() + processed_.transitions.size();
3289 : }
3290 :
3291 15230 : void ElementAccessFeedback::MapIterator::advance() { index_++; }
3292 :
3293 31674 : MapRef ElementAccessFeedback::MapIterator::current() const {
3294 31674 : CHECK(!done());
3295 : size_t receiver_maps_size = processed_.receiver_maps.size();
3296 : Handle<Map> map;
3297 31674 : if (index_ < receiver_maps_size) {
3298 30572 : map = processed_.receiver_maps[index_];
3299 : } else {
3300 2204 : map = processed_.transitions[index_ - receiver_maps_size].first;
3301 : }
3302 63348 : return MapRef(broker_, map);
3303 : }
3304 :
3305 14996 : ElementAccessFeedback::MapIterator ElementAccessFeedback::all_maps(
3306 : JSHeapBroker* broker) const {
3307 14996 : return MapIterator(*this, broker);
3308 : }
3309 :
3310 41 : FeedbackSource::FeedbackSource(FeedbackNexus const& nexus)
3311 41 : : vector(nexus.vector_handle()), slot(nexus.slot()) {}
3312 :
3313 950361 : FeedbackSource::FeedbackSource(VectorSlotPair const& pair)
3314 950361 : : vector(pair.vector()), slot(pair.slot()) {}
3315 :
3316 72 : void JSHeapBroker::SetFeedback(FeedbackSource const& source,
3317 : ProcessedFeedback const* feedback) {
3318 72 : auto insertion = feedback_.insert({source, feedback});
3319 72 : CHECK(insertion.second);
3320 72 : }
3321 :
3322 84 : bool JSHeapBroker::HasFeedback(FeedbackSource const& source) const {
3323 84 : return feedback_.find(source) != feedback_.end();
3324 : }
3325 :
3326 63 : ProcessedFeedback const* JSHeapBroker::GetFeedback(
3327 : FeedbackSource const& source) const {
3328 : auto it = feedback_.find(source);
3329 63 : CHECK_NE(it, feedback_.end());
3330 63 : return it->second;
3331 : }
3332 :
3333 8 : ElementAccessFeedback const* JSHeapBroker::GetElementAccessFeedback(
3334 : FeedbackSource const& source) const {
3335 8 : ProcessedFeedback const* feedback = GetFeedback(source);
3336 8 : if (feedback == nullptr) return nullptr;
3337 0 : CHECK_EQ(feedback->kind(), ProcessedFeedback::kElementAccess);
3338 : return static_cast<ElementAccessFeedback const*>(feedback);
3339 : }
3340 :
3341 55 : GlobalAccessFeedback const* JSHeapBroker::GetGlobalAccessFeedback(
3342 : FeedbackSource const& source) const {
3343 55 : ProcessedFeedback const* feedback = GetFeedback(source);
3344 55 : if (feedback == nullptr) return nullptr;
3345 0 : CHECK_EQ(feedback->kind(), ProcessedFeedback::kGlobalAccess);
3346 : return static_cast<GlobalAccessFeedback const*>(feedback);
3347 : }
3348 :
3349 23552 : ElementAccessFeedback const* JSHeapBroker::ProcessFeedbackMapsForElementAccess(
3350 : MapHandles const& maps) {
3351 : // Collect possible transition targets.
3352 : MapHandles possible_transition_targets;
3353 23552 : possible_transition_targets.reserve(maps.size());
3354 50484 : for (Handle<Map> map : maps) {
3355 79000 : if (CanInlineElementAccess(MapRef(this, map)) &&
3356 45225 : IsFastElementsKind(map->elements_kind()) &&
3357 : GetInitialFastElementsKind() != map->elements_kind()) {
3358 13163 : possible_transition_targets.push_back(map);
3359 : }
3360 : }
3361 :
3362 23552 : if (maps.empty()) return nullptr;
3363 :
3364 : ElementAccessFeedback* result = new (zone()) ElementAccessFeedback(zone());
3365 :
3366 : // Separate the actual receiver maps and the possible transition sources.
3367 50468 : for (Handle<Map> map : maps) {
3368 : // Don't generate elements kind transitions from stable maps.
3369 : Map transition_target = map->is_stable()
3370 : ? Map()
3371 : : map->FindElementsKindTransitionedMap(
3372 42885 : isolate(), possible_transition_targets);
3373 26932 : if (transition_target.is_null()) {
3374 25301 : result->receiver_maps.push_back(map);
3375 : } else {
3376 1631 : result->transitions.emplace_back(map,
3377 3262 : handle(transition_target, isolate()));
3378 : }
3379 : }
3380 :
3381 : #ifdef ENABLE_SLOW_DCHECKS
3382 : // No transition sources appear in {receiver_maps}.
3383 : // All transition targets appear in {receiver_maps}.
3384 : for (auto& transition : result->transitions) {
3385 : CHECK(std::none_of(
3386 : result->receiver_maps.cbegin(), result->receiver_maps.cend(),
3387 : [&](Handle<Map> map) { return map.equals(transition.first); }));
3388 : CHECK(std::any_of(
3389 : result->receiver_maps.cbegin(), result->receiver_maps.cend(),
3390 : [&](Handle<Map> map) { return map.equals(transition.second); }));
3391 : }
3392 : #endif
3393 23536 : CHECK(!result->receiver_maps.empty());
3394 :
3395 : return result;
3396 : }
3397 :
3398 950357 : GlobalAccessFeedback const* JSHeapBroker::ProcessFeedbackForGlobalAccess(
3399 : FeedbackSource const& source) {
3400 : FeedbackNexus nexus(source.vector, source.slot);
3401 : DCHECK(nexus.kind() == FeedbackSlotKind::kLoadGlobalInsideTypeof ||
3402 : nexus.kind() == FeedbackSlotKind::kLoadGlobalNotInsideTypeof ||
3403 : nexus.kind() == FeedbackSlotKind::kStoreGlobalSloppy ||
3404 : nexus.kind() == FeedbackSlotKind::kStoreGlobalStrict);
3405 1144895 : if (nexus.ic_state() != MONOMORPHIC || nexus.GetFeedback()->IsCleared()) {
3406 : return nullptr;
3407 : }
3408 :
3409 388828 : Handle<Object> feedback_value(nexus.GetFeedback()->GetHeapObjectOrSmi(),
3410 : isolate());
3411 :
3412 194414 : if (feedback_value->IsSmi()) {
3413 : // The wanted name belongs to a script-scope variable and the feedback tells
3414 : // us where to find its value.
3415 109 : int number = feedback_value->Number();
3416 : int const script_context_index =
3417 218 : FeedbackNexus::ContextIndexBits::decode(number);
3418 109 : int const context_slot_index = FeedbackNexus::SlotIndexBits::decode(number);
3419 : bool const immutable = FeedbackNexus::ImmutabilityBit::decode(number);
3420 : Handle<Context> context = ScriptContextTable::GetContext(
3421 218 : isolate(), native_context().script_context_table().object(),
3422 109 : script_context_index);
3423 : {
3424 : ObjectRef contents(this,
3425 109 : handle(context->get(context_slot_index), isolate()));
3426 218 : CHECK(!contents.equals(
3427 : ObjectRef(this, isolate()->factory()->the_hole_value())));
3428 : }
3429 : ContextRef context_ref(this, context);
3430 109 : if (immutable) {
3431 31 : context_ref.SerializeSlot(context_slot_index);
3432 : }
3433 : return new (zone())
3434 109 : GlobalAccessFeedback(context_ref, context_slot_index, immutable);
3435 : }
3436 :
3437 194305 : CHECK(feedback_value->IsPropertyCell());
3438 : // The wanted name belongs (or did belong) to a property on the global
3439 : // object and the feedback is the cell holding its value.
3440 : PropertyCellRef cell(this, Handle<PropertyCell>::cast(feedback_value));
3441 194305 : cell.Serialize();
3442 194305 : return new (zone()) GlobalAccessFeedback(cell);
3443 : }
3444 :
3445 0 : std::ostream& operator<<(std::ostream& os, const ObjectRef& ref) {
3446 0 : return os << ref.data();
3447 : }
3448 :
3449 : #undef BIMODAL_ACCESSOR
3450 : #undef BIMODAL_ACCESSOR_B
3451 : #undef BIMODAL_ACCESSOR_C
3452 : #undef IF_BROKER_DISABLED_ACCESS_HANDLE
3453 : #undef IF_BROKER_DISABLED_ACCESS_HANDLE_C
3454 : #undef TRACE
3455 : #undef TRACE_MISSING
3456 :
3457 : } // namespace compiler
3458 : } // namespace internal
3459 121996 : } // namespace v8
|