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 : #ifndef V8_COMPILER_JS_HEAP_BROKER_H_
6 : #define V8_COMPILER_JS_HEAP_BROKER_H_
7 :
8 : #include "src/base/compiler-specific.h"
9 : #include "src/base/optional.h"
10 : #include "src/compiler/refs-map.h"
11 : #include "src/feedback-vector.h"
12 : #include "src/function-kind.h"
13 : #include "src/globals.h"
14 : #include "src/handles.h"
15 : #include "src/objects.h"
16 : #include "src/objects/instance-type.h"
17 : #include "src/ostreams.h"
18 : #include "src/zone/zone-containers.h"
19 :
20 : namespace v8 {
21 : namespace internal {
22 :
23 : class BytecodeArray;
24 : class CallHandlerInfo;
25 : class FixedDoubleArray;
26 : class FunctionTemplateInfo;
27 : class HeapNumber;
28 : class InternalizedString;
29 : class JSBoundFunction;
30 : class JSDataView;
31 : class JSGlobalProxy;
32 : class JSRegExp;
33 : class JSTypedArray;
34 : class NativeContext;
35 : class ScriptContextTable;
36 : class VectorSlotPair;
37 :
38 : namespace compiler {
39 :
40 : enum class OddballType : uint8_t {
41 : kNone, // Not an Oddball.
42 : kBoolean, // True or False.
43 : kUndefined,
44 : kNull,
45 : kHole,
46 : kUninitialized,
47 : kOther // Oddball, but none of the above.
48 : };
49 :
50 : // This list is sorted such that subtypes appear before their supertypes.
51 : // DO NOT VIOLATE THIS PROPERTY!
52 : #define HEAP_BROKER_OBJECT_LIST(V) \
53 : /* Subtypes of JSObject */ \
54 : V(JSArray) \
55 : V(JSBoundFunction) \
56 : V(JSDataView) \
57 : V(JSFunction) \
58 : V(JSGlobalProxy) \
59 : V(JSRegExp) \
60 : V(JSTypedArray) \
61 : /* Subtypes of Context */ \
62 : V(NativeContext) \
63 : /* Subtypes of FixedArray */ \
64 : V(Context) \
65 : V(ScopeInfo) \
66 : V(ScriptContextTable) \
67 : /* Subtypes of FixedArrayBase */ \
68 : V(BytecodeArray) \
69 : V(FixedArray) \
70 : V(FixedDoubleArray) \
71 : /* Subtypes of Name */ \
72 : V(InternalizedString) \
73 : V(String) \
74 : V(Symbol) \
75 : /* Subtypes of HeapObject */ \
76 : V(AllocationSite) \
77 : V(CallHandlerInfo) \
78 : V(Cell) \
79 : V(Code) \
80 : V(DescriptorArray) \
81 : V(FeedbackVector) \
82 : V(FixedArrayBase) \
83 : V(FunctionTemplateInfo) \
84 : V(HeapNumber) \
85 : V(JSObject) \
86 : V(Map) \
87 : V(Module) \
88 : V(MutableHeapNumber) \
89 : V(Name) \
90 : V(PropertyCell) \
91 : V(SharedFunctionInfo) \
92 : /* Subtypes of Object */ \
93 : V(HeapObject)
94 :
95 : class CompilationDependencies;
96 : class JSHeapBroker;
97 : class ObjectData;
98 : class PerIsolateCompilerCache;
99 : #define FORWARD_DECL(Name) class Name##Ref;
100 : HEAP_BROKER_OBJECT_LIST(FORWARD_DECL)
101 : #undef FORWARD_DECL
102 :
103 : class V8_EXPORT_PRIVATE ObjectRef {
104 : public:
105 : ObjectRef(JSHeapBroker* broker, Handle<Object> object);
106 : ObjectRef(JSHeapBroker* broker, ObjectData* data)
107 466767 : : data_(data), broker_(broker) {
108 86063807 : CHECK_NOT_NULL(data_);
109 : }
110 :
111 : Handle<Object> object() const;
112 :
113 : bool equals(const ObjectRef& other) const;
114 :
115 : bool IsSmi() const;
116 : int AsSmi() const;
117 :
118 : #define HEAP_IS_METHOD_DECL(Name) bool Is##Name() const;
119 : HEAP_BROKER_OBJECT_LIST(HEAP_IS_METHOD_DECL)
120 : #undef HEAP_IS_METHOD_DECL
121 :
122 : #define HEAP_AS_METHOD_DECL(Name) Name##Ref As##Name() const;
123 : HEAP_BROKER_OBJECT_LIST(HEAP_AS_METHOD_DECL)
124 : #undef HEAP_AS_METHOD_DECL
125 :
126 : bool IsNullOrUndefined() const;
127 :
128 : bool BooleanValue() const;
129 : Maybe<double> OddballToNumber() const;
130 :
131 : // Return the element at key {index} if {index} is known to be an own data
132 : // property of the object that is non-writable and non-configurable.
133 : base::Optional<ObjectRef> GetOwnConstantElement(uint32_t index,
134 : bool serialize = false) const;
135 :
136 : Isolate* isolate() const;
137 :
138 : protected:
139 : JSHeapBroker* broker() const;
140 : ObjectData* data() const;
141 : ObjectData* data_; // Should be used only by object() getters.
142 :
143 : private:
144 : friend class JSArrayData;
145 : friend class JSGlobalProxyRef;
146 : friend class JSGlobalProxyData;
147 : friend class JSObjectData;
148 : friend class StringData;
149 :
150 : friend std::ostream& operator<<(std::ostream& os, const ObjectRef& ref);
151 :
152 : JSHeapBroker* broker_;
153 : };
154 :
155 : std::ostream& operator<<(std::ostream& os, const ObjectRef& ref);
156 :
157 : // Temporary class that carries information from a Map. We'd like to remove
158 : // this class and use MapRef instead, but we can't as long as we support the
159 : // kDisabled broker mode. That's because obtaining the MapRef via
160 : // HeapObjectRef::map() requires a HandleScope when the broker is disabled.
161 : // During OptimizeGraph we generally don't have a HandleScope, however. There
162 : // are two places where we therefore use GetHeapObjectType() instead. Both that
163 : // function and this class should eventually be removed.
164 : class HeapObjectType {
165 : public:
166 : enum Flag : uint8_t { kUndetectable = 1 << 0, kCallable = 1 << 1 };
167 :
168 : using Flags = base::Flags<Flag>;
169 :
170 : HeapObjectType(InstanceType instance_type, Flags flags,
171 : OddballType oddball_type)
172 : : instance_type_(instance_type),
173 : oddball_type_(oddball_type),
174 : flags_(flags) {
175 : DCHECK_EQ(instance_type == ODDBALL_TYPE,
176 : oddball_type != OddballType::kNone);
177 : }
178 :
179 : OddballType oddball_type() const { return oddball_type_; }
180 : InstanceType instance_type() const { return instance_type_; }
181 : Flags flags() const { return flags_; }
182 :
183 : bool is_callable() const { return flags_ & kCallable; }
184 : bool is_undetectable() const { return flags_ & kUndetectable; }
185 :
186 : private:
187 : InstanceType const instance_type_;
188 : OddballType const oddball_type_;
189 : Flags const flags_;
190 : };
191 :
192 : class HeapObjectRef : public ObjectRef {
193 : public:
194 53541977 : using ObjectRef::ObjectRef;
195 : Handle<HeapObject> object() const;
196 :
197 : MapRef map() const;
198 :
199 : // See the comment on the HeapObjectType class.
200 : HeapObjectType GetHeapObjectType() const;
201 : };
202 :
203 : class PropertyCellRef : public HeapObjectRef {
204 : public:
205 : using HeapObjectRef::HeapObjectRef;
206 : Handle<PropertyCell> object() const;
207 :
208 : PropertyDetails property_details() const;
209 :
210 : void Serialize();
211 : ObjectRef value() const;
212 : };
213 :
214 : class JSObjectRef : public HeapObjectRef {
215 : public:
216 : using HeapObjectRef::HeapObjectRef;
217 : Handle<JSObject> object() const;
218 :
219 : double RawFastDoublePropertyAt(FieldIndex index) const;
220 : ObjectRef RawFastPropertyAt(FieldIndex index) const;
221 :
222 : FixedArrayBaseRef elements() const;
223 : void EnsureElementsTenured();
224 : ElementsKind GetElementsKind() const;
225 :
226 : void SerializeObjectCreateMap();
227 : base::Optional<MapRef> GetObjectCreateMap() const;
228 : };
229 :
230 : class JSDataViewRef : public JSObjectRef {
231 : public:
232 : using JSObjectRef::JSObjectRef;
233 : Handle<JSDataView> object() const;
234 :
235 : size_t byte_length() const;
236 : size_t byte_offset() const;
237 : };
238 :
239 : class JSBoundFunctionRef : public JSObjectRef {
240 : public:
241 : using JSObjectRef::JSObjectRef;
242 : Handle<JSBoundFunction> object() const;
243 :
244 : void Serialize();
245 :
246 : // The following are available only after calling Serialize().
247 : ObjectRef bound_target_function() const;
248 : ObjectRef bound_this() const;
249 : FixedArrayRef bound_arguments() const;
250 : };
251 :
252 : class V8_EXPORT_PRIVATE JSFunctionRef : public JSObjectRef {
253 : public:
254 : using JSObjectRef::JSObjectRef;
255 : Handle<JSFunction> object() const;
256 :
257 : bool has_feedback_vector() const;
258 : bool has_initial_map() const;
259 : bool has_prototype() const;
260 : bool PrototypeRequiresRuntimeLookup() const;
261 :
262 : void Serialize();
263 : bool serialized() const;
264 :
265 : // The following are available only after calling Serialize().
266 : ObjectRef prototype() const;
267 : MapRef initial_map() const;
268 : ContextRef context() const;
269 : NativeContextRef native_context() const;
270 : SharedFunctionInfoRef shared() const;
271 : FeedbackVectorRef feedback_vector() const;
272 : int InitialMapInstanceSizeWithMinSlack() const;
273 :
274 : bool IsSerializedForCompilation() const;
275 : };
276 :
277 : class JSRegExpRef : public JSObjectRef {
278 : public:
279 : using JSObjectRef::JSObjectRef;
280 : Handle<JSRegExp> object() const;
281 :
282 : ObjectRef raw_properties_or_hash() const;
283 : ObjectRef data() const;
284 : ObjectRef source() const;
285 : ObjectRef flags() const;
286 : ObjectRef last_index() const;
287 : };
288 :
289 : class HeapNumberRef : public HeapObjectRef {
290 : public:
291 : using HeapObjectRef::HeapObjectRef;
292 : Handle<HeapNumber> object() const;
293 :
294 : double value() const;
295 : };
296 :
297 : class MutableHeapNumberRef : public HeapObjectRef {
298 : public:
299 : using HeapObjectRef::HeapObjectRef;
300 : Handle<MutableHeapNumber> object() const;
301 :
302 : double value() const;
303 : };
304 :
305 : class ContextRef : public HeapObjectRef {
306 : public:
307 : using HeapObjectRef::HeapObjectRef;
308 : Handle<Context> object() const;
309 :
310 : void SerializeContextChain();
311 : ContextRef previous() const;
312 :
313 : void SerializeSlot(int index);
314 : ObjectRef get(int index) const;
315 : };
316 :
317 : #define BROKER_COMPULSORY_NATIVE_CONTEXT_FIELDS(V) \
318 : V(JSFunction, array_function) \
319 : V(JSFunction, boolean_function) \
320 : V(JSFunction, bigint_function) \
321 : V(JSFunction, number_function) \
322 : V(JSFunction, object_function) \
323 : V(JSFunction, promise_function) \
324 : V(JSFunction, promise_then) \
325 : V(JSFunction, string_function) \
326 : V(JSFunction, symbol_function) \
327 : V(JSGlobalProxy, global_proxy_object) \
328 : V(JSObject, promise_prototype) \
329 : V(Map, bound_function_with_constructor_map) \
330 : V(Map, bound_function_without_constructor_map) \
331 : V(Map, fast_aliased_arguments_map) \
332 : V(Map, initial_array_iterator_map) \
333 : V(Map, initial_string_iterator_map) \
334 : V(Map, iterator_result_map) \
335 : V(Map, js_array_holey_double_elements_map) \
336 : V(Map, js_array_holey_elements_map) \
337 : V(Map, js_array_holey_smi_elements_map) \
338 : V(Map, js_array_packed_double_elements_map) \
339 : V(Map, js_array_packed_elements_map) \
340 : V(Map, js_array_packed_smi_elements_map) \
341 : V(Map, sloppy_arguments_map) \
342 : V(Map, slow_object_with_null_prototype_map) \
343 : V(Map, strict_arguments_map) \
344 : V(ScriptContextTable, script_context_table) \
345 : V(SharedFunctionInfo, promise_capability_default_reject_shared_fun) \
346 : V(SharedFunctionInfo, promise_catch_finally_shared_fun) \
347 : V(SharedFunctionInfo, promise_then_finally_shared_fun) \
348 : V(SharedFunctionInfo, promise_capability_default_resolve_shared_fun)
349 :
350 : // Those are set by Bootstrapper::ExportFromRuntime, which may not yet have
351 : // happened when Turbofan is invoked via --always-opt.
352 : #define BROKER_OPTIONAL_NATIVE_CONTEXT_FIELDS(V) \
353 : V(Map, async_function_object_map) \
354 : V(Map, map_key_iterator_map) \
355 : V(Map, map_key_value_iterator_map) \
356 : V(Map, map_value_iterator_map) \
357 : V(Map, set_key_value_iterator_map) \
358 : V(Map, set_value_iterator_map)
359 :
360 : #define BROKER_NATIVE_CONTEXT_FIELDS(V) \
361 : BROKER_COMPULSORY_NATIVE_CONTEXT_FIELDS(V) \
362 : BROKER_OPTIONAL_NATIVE_CONTEXT_FIELDS(V)
363 :
364 : class NativeContextRef : public ContextRef {
365 : public:
366 : using ContextRef::ContextRef;
367 : Handle<NativeContext> object() const;
368 :
369 : void Serialize();
370 :
371 : #define DECL_ACCESSOR(type, name) type##Ref name() const;
372 : BROKER_NATIVE_CONTEXT_FIELDS(DECL_ACCESSOR)
373 : #undef DECL_ACCESSOR
374 :
375 : MapRef GetFunctionMapFromIndex(int index) const;
376 : MapRef GetInitialJSArrayMap(ElementsKind kind) const;
377 : base::Optional<JSFunctionRef> GetConstructorFunction(const MapRef& map) const;
378 : };
379 :
380 : class NameRef : public HeapObjectRef {
381 : public:
382 : using HeapObjectRef::HeapObjectRef;
383 : Handle<Name> object() const;
384 :
385 : bool IsUniqueName() const;
386 : };
387 :
388 : class ScriptContextTableRef : public HeapObjectRef {
389 : public:
390 : using HeapObjectRef::HeapObjectRef;
391 : Handle<ScriptContextTable> object() const;
392 :
393 : struct LookupResult {
394 : ContextRef context;
395 : bool immutable;
396 : int index;
397 : };
398 :
399 : base::Optional<LookupResult> lookup(const NameRef& name) const;
400 : };
401 :
402 : class DescriptorArrayRef : public HeapObjectRef {
403 : public:
404 : using HeapObjectRef::HeapObjectRef;
405 : Handle<DescriptorArray> object() const;
406 : };
407 :
408 : class FeedbackVectorRef : public HeapObjectRef {
409 : public:
410 : using HeapObjectRef::HeapObjectRef;
411 : Handle<FeedbackVector> object() const;
412 :
413 : ObjectRef get(FeedbackSlot slot) const;
414 :
415 : void SerializeSlots();
416 : };
417 :
418 : class FunctionTemplateInfoRef : public HeapObjectRef {
419 : public:
420 : using HeapObjectRef::HeapObjectRef;
421 : Handle<FunctionTemplateInfo> object() const;
422 :
423 : void Serialize();
424 : ObjectRef call_code() const;
425 : };
426 :
427 : class CallHandlerInfoRef : public HeapObjectRef {
428 : public:
429 : using HeapObjectRef::HeapObjectRef;
430 : Handle<CallHandlerInfo> object() const;
431 :
432 : Address callback() const;
433 :
434 : void Serialize();
435 : ObjectRef data() const;
436 : };
437 :
438 : class AllocationSiteRef : public HeapObjectRef {
439 : public:
440 : using HeapObjectRef::HeapObjectRef;
441 : Handle<AllocationSite> object() const;
442 :
443 : bool PointsToLiteral() const;
444 : AllocationType GetAllocationType() const;
445 : ObjectRef nested_site() const;
446 :
447 : // {IsFastLiteral} determines whether the given array or object literal
448 : // boilerplate satisfies all limits to be considered for fast deep-copying
449 : // and computes the total size of all objects that are part of the graph.
450 : //
451 : // If PointsToLiteral() is false, then IsFastLiteral() is also false.
452 : bool IsFastLiteral() const;
453 : // We only serialize boilerplate if IsFastLiteral is true.
454 : base::Optional<JSObjectRef> boilerplate() const;
455 :
456 : ElementsKind GetElementsKind() const;
457 : bool CanInlineCall() const;
458 : };
459 :
460 : class V8_EXPORT_PRIVATE MapRef : public HeapObjectRef {
461 : public:
462 : using HeapObjectRef::HeapObjectRef;
463 : Handle<Map> object() const;
464 :
465 : int instance_size() const;
466 : InstanceType instance_type() const;
467 : int GetInObjectProperties() const;
468 : int GetInObjectPropertiesStartInWords() const;
469 : int NumberOfOwnDescriptors() const;
470 : int GetInObjectPropertyOffset(int index) const;
471 : int constructor_function_index() const;
472 : int NextFreePropertyIndex() const;
473 : int UnusedPropertyFields() const;
474 : ElementsKind elements_kind() const;
475 : bool is_stable() const;
476 : bool is_extensible() const;
477 : bool is_constructor() const;
478 : bool has_prototype_slot() const;
479 : bool is_access_check_needed() const;
480 : bool is_deprecated() const;
481 : bool CanBeDeprecated() const;
482 : bool CanTransition() const;
483 : bool IsInobjectSlackTrackingInProgress() const;
484 : bool is_dictionary_map() const;
485 : bool IsFixedCowArrayMap() const;
486 : bool IsPrimitiveMap() const;
487 : bool is_undetectable() const;
488 : bool is_callable() const;
489 : bool has_indexed_interceptor() const;
490 : bool has_hidden_prototype() const;
491 : bool is_migration_target() const;
492 : bool supports_fast_array_iteration() const;
493 : bool supports_fast_array_resize() const;
494 : bool IsMapOfCurrentGlobalProxy() const;
495 :
496 : OddballType oddball_type() const;
497 :
498 : #define DEF_TESTER(Type, ...) bool Is##Type##Map() const;
499 : INSTANCE_TYPE_CHECKERS(DEF_TESTER)
500 : #undef DEF_TESTER
501 :
502 : void SerializeBackPointer();
503 : HeapObjectRef GetBackPointer() const;
504 :
505 : void SerializePrototype();
506 : bool serialized_prototype() const;
507 : HeapObjectRef prototype() const;
508 :
509 : void SerializeForElementLoad();
510 :
511 : void SerializeForElementStore();
512 : bool HasOnlyStablePrototypesWithFastElements(
513 : ZoneVector<MapRef>* prototype_maps);
514 :
515 : // Concerning the underlying instance_descriptors:
516 : void SerializeOwnDescriptors();
517 : MapRef FindFieldOwner(int descriptor_index) const;
518 : PropertyDetails GetPropertyDetails(int descriptor_index) const;
519 : NameRef GetPropertyKey(int descriptor_index) const;
520 : FieldIndex GetFieldIndexFor(int descriptor_index) const;
521 : ObjectRef GetFieldType(int descriptor_index) const;
522 : bool IsUnboxedDoubleField(int descriptor_index) const;
523 :
524 : // Available after calling JSFunctionRef::Serialize on a function that has
525 : // this map as initial map.
526 : ObjectRef GetConstructor() const;
527 : base::Optional<MapRef> AsElementsKind(ElementsKind kind) const;
528 : };
529 :
530 : class FixedArrayBaseRef : public HeapObjectRef {
531 : public:
532 : using HeapObjectRef::HeapObjectRef;
533 : Handle<FixedArrayBase> object() const;
534 :
535 : int length() const;
536 : };
537 :
538 : class FixedArrayRef : public FixedArrayBaseRef {
539 : public:
540 : using FixedArrayBaseRef::FixedArrayBaseRef;
541 : Handle<FixedArray> object() const;
542 :
543 : ObjectRef get(int i) const;
544 : };
545 :
546 : class FixedDoubleArrayRef : public FixedArrayBaseRef {
547 : public:
548 : using FixedArrayBaseRef::FixedArrayBaseRef;
549 : Handle<FixedDoubleArray> object() const;
550 :
551 : double get_scalar(int i) const;
552 : bool is_the_hole(int i) const;
553 : };
554 :
555 : class BytecodeArrayRef : public FixedArrayBaseRef {
556 : public:
557 : using FixedArrayBaseRef::FixedArrayBaseRef;
558 : Handle<BytecodeArray> object() const;
559 :
560 : int register_count() const;
561 : };
562 :
563 : class JSArrayRef : public JSObjectRef {
564 : public:
565 : using JSObjectRef::JSObjectRef;
566 : Handle<JSArray> object() const;
567 :
568 : ObjectRef length() const;
569 :
570 : // Return the element at key {index} if the array has a copy-on-write elements
571 : // storage and {index} is known to be an own data property.
572 : base::Optional<ObjectRef> GetOwnCowElement(uint32_t index,
573 : bool serialize = false) const;
574 : };
575 :
576 : class ScopeInfoRef : public HeapObjectRef {
577 : public:
578 : using HeapObjectRef::HeapObjectRef;
579 : Handle<ScopeInfo> object() const;
580 :
581 : int ContextLength() const;
582 : };
583 :
584 : #define BROKER_SFI_FIELDS(V) \
585 : V(int, internal_formal_parameter_count) \
586 : V(bool, has_duplicate_parameters) \
587 : V(int, function_map_index) \
588 : V(FunctionKind, kind) \
589 : V(LanguageMode, language_mode) \
590 : V(bool, native) \
591 : V(bool, HasBreakInfo) \
592 : V(bool, HasBuiltinId) \
593 : V(bool, construct_as_builtin) \
594 : V(bool, HasBytecodeArray) \
595 : V(bool, is_safe_to_skip_arguments_adaptor) \
596 : V(bool, IsInlineable)
597 :
598 : class V8_EXPORT_PRIVATE SharedFunctionInfoRef : public HeapObjectRef {
599 : public:
600 : using HeapObjectRef::HeapObjectRef;
601 : Handle<SharedFunctionInfo> object() const;
602 :
603 : int builtin_id() const;
604 : BytecodeArrayRef GetBytecodeArray() const;
605 :
606 : #define DECL_ACCESSOR(type, name) type name() const;
607 : BROKER_SFI_FIELDS(DECL_ACCESSOR)
608 : #undef DECL_ACCESSOR
609 :
610 : bool IsSerializedForCompilation(FeedbackVectorRef feedback) const;
611 : void SetSerializedForCompilation(FeedbackVectorRef feedback);
612 : };
613 :
614 : class StringRef : public NameRef {
615 : public:
616 : using NameRef::NameRef;
617 : Handle<String> object() const;
618 :
619 : int length() const;
620 : uint16_t GetFirstChar();
621 : base::Optional<double> ToNumber();
622 : bool IsSeqString() const;
623 : bool IsExternalString() const;
624 : };
625 :
626 : class SymbolRef : public NameRef {
627 : public:
628 : using NameRef::NameRef;
629 : Handle<Symbol> object() const;
630 : };
631 :
632 : class JSTypedArrayRef : public JSObjectRef {
633 : public:
634 : using JSObjectRef::JSObjectRef;
635 : Handle<JSTypedArray> object() const;
636 :
637 : bool is_on_heap() const;
638 : size_t length() const;
639 : void* elements_external_pointer() const;
640 :
641 : void Serialize();
642 : bool serialized() const;
643 :
644 : HeapObjectRef buffer() const;
645 : };
646 :
647 : class ModuleRef : public HeapObjectRef {
648 : public:
649 : using HeapObjectRef::HeapObjectRef;
650 : Handle<Module> object() const;
651 :
652 : void Serialize();
653 :
654 : CellRef GetCell(int cell_index) const;
655 : };
656 :
657 : class CellRef : public HeapObjectRef {
658 : public:
659 : using HeapObjectRef::HeapObjectRef;
660 : Handle<Cell> object() const;
661 :
662 : ObjectRef value() const;
663 : };
664 :
665 : class JSGlobalProxyRef : public JSObjectRef {
666 : public:
667 : using JSObjectRef::JSObjectRef;
668 : Handle<JSGlobalProxy> object() const;
669 :
670 : // If {serialize} is false:
671 : // If the property is known to exist as a property cell (on the global
672 : // object), return that property cell. Otherwise (not known to exist as a
673 : // property cell or known not to exist as a property cell) return nothing.
674 : // If {serialize} is true:
675 : // Like above but potentially access the heap and serialize the necessary
676 : // information.
677 : base::Optional<PropertyCellRef> GetPropertyCell(NameRef const& name,
678 : bool serialize = false) const;
679 : };
680 :
681 : class CodeRef : public HeapObjectRef {
682 : public:
683 : using HeapObjectRef::HeapObjectRef;
684 : Handle<Code> object() const;
685 : };
686 :
687 : class InternalizedStringRef : public StringRef {
688 : public:
689 : using StringRef::StringRef;
690 : Handle<InternalizedString> object() const;
691 : };
692 :
693 : class ProcessedFeedback : public ZoneObject {
694 : public:
695 : enum Kind { kElementAccess, kGlobalAccess };
696 0 : Kind kind() const { return kind_; }
697 :
698 : protected:
699 218019 : explicit ProcessedFeedback(Kind kind) : kind_(kind) {}
700 :
701 : private:
702 : Kind const kind_;
703 : };
704 :
705 : class GlobalAccessFeedback : public ProcessedFeedback {
706 : public:
707 : explicit GlobalAccessFeedback(PropertyCellRef cell);
708 : GlobalAccessFeedback(ContextRef script_context, int slot_index,
709 : bool immutable);
710 :
711 : bool IsPropertyCell() const;
712 : PropertyCellRef property_cell() const;
713 :
714 194438 : bool IsScriptContextSlot() const { return !IsPropertyCell(); }
715 : ContextRef script_context() const;
716 : int slot_index() const;
717 : bool immutable() const;
718 :
719 : base::Optional<ObjectRef> GetConstantHint() const;
720 :
721 : private:
722 : ObjectRef const cell_or_context_;
723 : int const index_and_immutable_;
724 : };
725 :
726 : class ElementAccessFeedback : public ProcessedFeedback {
727 : public:
728 : explicit ElementAccessFeedback(Zone* zone);
729 :
730 : // No transition sources appear in {receiver_maps}.
731 : // All transition targets appear in {receiver_maps}.
732 : ZoneVector<Handle<Map>> receiver_maps;
733 : ZoneVector<std::pair<Handle<Map>, Handle<Map>>> transitions;
734 :
735 : class MapIterator {
736 : public:
737 : bool done() const;
738 : void advance();
739 : MapRef current() const;
740 :
741 : private:
742 : friend class ElementAccessFeedback;
743 :
744 : explicit MapIterator(ElementAccessFeedback const& processed,
745 : JSHeapBroker* broker);
746 :
747 : ElementAccessFeedback const& processed_;
748 : JSHeapBroker* const broker_;
749 : size_t index_ = 0;
750 : };
751 :
752 : // Iterator over all maps: first {receiver_maps}, then transition sources.
753 : MapIterator all_maps(JSHeapBroker* broker) const;
754 : };
755 :
756 : struct FeedbackSource {
757 : FeedbackSource(Handle<FeedbackVector> vector_, FeedbackSlot slot_)
758 51 : : vector(vector_), slot(slot_) {}
759 : explicit FeedbackSource(FeedbackNexus const& nexus);
760 : explicit FeedbackSource(VectorSlotPair const& pair);
761 :
762 : Handle<FeedbackVector> const vector;
763 : FeedbackSlot const slot;
764 :
765 : struct Hash {
766 219 : size_t operator()(FeedbackSource const& source) const {
767 219 : return base::hash_combine(source.vector.address(), source.slot);
768 : }
769 : };
770 :
771 : struct Equal {
772 : bool operator()(FeedbackSource const& lhs,
773 : FeedbackSource const& rhs) const {
774 150 : return lhs.vector.equals(rhs.vector) && lhs.slot == rhs.slot;
775 : }
776 : };
777 : };
778 :
779 7962 : class V8_EXPORT_PRIVATE JSHeapBroker : public NON_EXPORTED_BASE(ZoneObject) {
780 : public:
781 : JSHeapBroker(Isolate* isolate, Zone* broker_zone);
782 :
783 : void SetNativeContextRef();
784 : void SerializeStandardObjects();
785 :
786 : Isolate* isolate() const { return isolate_; }
787 : Zone* zone() const { return current_zone_; }
788 2015536 : NativeContextRef native_context() const { return native_context_.value(); }
789 : PerIsolateCompilerCache* compiler_cache() const { return compiler_cache_; }
790 :
791 : enum BrokerMode { kDisabled, kSerializing, kSerialized, kRetired };
792 : BrokerMode mode() const { return mode_; }
793 : void StartSerializing();
794 : void StopSerializing();
795 : void Retire();
796 : bool SerializingAllowed() const;
797 :
798 : // Returns nullptr iff handle unknown.
799 : ObjectData* GetData(Handle<Object>) const;
800 : // Never returns nullptr.
801 : ObjectData* GetOrCreateData(Handle<Object>);
802 : // Like the previous but wraps argument in handle first (for convenience).
803 : ObjectData* GetOrCreateData(Object);
804 :
805 : // Check if {object} is any native context's %ArrayPrototype% or
806 : // %ObjectPrototype%.
807 : bool IsArrayOrObjectPrototype(const JSObjectRef& object) const;
808 :
809 : bool HasFeedback(FeedbackSource const& source) const;
810 : // The processed {feedback} can be {nullptr}, indicating that the original
811 : // feedback didn't contain information relevant for Turbofan.
812 : void SetFeedback(FeedbackSource const& source,
813 : ProcessedFeedback const* feedback);
814 : ProcessedFeedback const* GetFeedback(FeedbackSource const& source) const;
815 :
816 : // Convenience wrappers around GetFeedback.
817 : ElementAccessFeedback const* GetElementAccessFeedback(
818 : FeedbackSource const& source) const;
819 : GlobalAccessFeedback const* GetGlobalAccessFeedback(
820 : FeedbackSource const& source) const;
821 :
822 : // TODO(neis): Move these into serializer when we're always in the background.
823 : ElementAccessFeedback const* ProcessFeedbackMapsForElementAccess(
824 : MapHandles const& maps);
825 : GlobalAccessFeedback const* ProcessFeedbackForGlobalAccess(
826 : FeedbackSource const& source);
827 :
828 : std::ostream& Trace();
829 : void IncrementTracingIndentation();
830 : void DecrementTracingIndentation();
831 :
832 : private:
833 : friend class HeapObjectRef;
834 : friend class ObjectRef;
835 : friend class ObjectData;
836 :
837 : void SerializeShareableObjects();
838 : void CollectArrayAndObjectPrototypes();
839 :
840 : Isolate* const isolate_;
841 : Zone* const broker_zone_;
842 : Zone* current_zone_;
843 : base::Optional<NativeContextRef> native_context_;
844 : RefsMap* refs_;
845 : ZoneUnorderedSet<Handle<JSObject>, Handle<JSObject>::hash,
846 : Handle<JSObject>::equal_to>
847 : array_and_object_prototypes_;
848 : BrokerMode mode_ = kDisabled;
849 : StdoutStream trace_out_;
850 : unsigned trace_indentation_ = 0;
851 : PerIsolateCompilerCache* compiler_cache_;
852 : ZoneUnorderedMap<FeedbackSource, ProcessedFeedback const*,
853 : FeedbackSource::Hash, FeedbackSource::Equal>
854 : feedback_;
855 :
856 : static const size_t kMinimalRefsBucketCount = 8; // must be power of 2
857 : static const size_t kInitialRefsBucketCount = 1024; // must be power of 2
858 : };
859 :
860 : #define ASSIGN_RETURN_NO_CHANGE_IF_DATA_MISSING(something_var, \
861 : optionally_something) \
862 : auto optionally_something_ = optionally_something; \
863 : if (!optionally_something_) \
864 : return NoChangeBecauseOfMissingData(broker(), __FUNCTION__, __LINE__); \
865 : something_var = *optionally_something_;
866 :
867 : class Reduction;
868 : Reduction NoChangeBecauseOfMissingData(JSHeapBroker* broker,
869 : const char* function, int line);
870 :
871 : // Miscellaneous definitions that should be moved elsewhere once concurrent
872 : // compilation is finished.
873 : bool CanInlineElementAccess(MapRef const& map);
874 :
875 : #define TRACE_BROKER(broker, x) \
876 : do { \
877 : if (FLAG_trace_heap_broker_verbose) broker->Trace() << x << '\n'; \
878 : } while (false)
879 :
880 : #define TRACE_BROKER_MISSING(broker, x) \
881 : do { \
882 : if (FLAG_trace_heap_broker) \
883 : broker->Trace() << __FUNCTION__ << ": missing " << x << '\n'; \
884 : } while (false)
885 :
886 : } // namespace compiler
887 : } // namespace internal
888 : } // namespace v8
889 :
890 : #endif // V8_COMPILER_JS_HEAP_BROKER_H_
|