V8 API Reference, 7.2.502.16 (for Deno 0.2.4)
js-heap-broker.h
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/globals.h"
12 #include "src/handles.h"
13 #include "src/objects.h"
14 #include "src/objects/builtin-function-id.h"
15 #include "src/objects/instance-type.h"
16 #include "src/zone/zone-containers.h"
17 
18 namespace v8 {
19 namespace internal {
20 
21 class BytecodeArray;
22 class FixedDoubleArray;
23 class InternalizedString;
24 class JSBoundFunction;
25 class JSDataView;
26 class JSGlobalProxy;
27 class JSRegExp;
28 class JSTypedArray;
29 class NativeContext;
30 class ScriptContextTable;
31 
32 namespace compiler {
33 
34 enum class OddballType : uint8_t {
35  kNone, // Not an Oddball.
36  kBoolean, // True or False.
37  kUndefined,
38  kNull,
39  kHole,
40  kUninitialized,
41  kOther // Oddball, but none of the above.
42 };
43 
44 // This list is sorted such that subtypes appear before their supertypes.
45 // DO NOT VIOLATE THIS PROPERTY!
46 #define HEAP_BROKER_OBJECT_LIST(V) \
47  /* Subtypes of JSObject */ \
48  V(JSArray) \
49  V(JSBoundFunction) \
50  V(JSDataView) \
51  V(JSFunction) \
52  V(JSGlobalProxy) \
53  V(JSRegExp) \
54  V(JSTypedArray) \
55  /* Subtypes of Context */ \
56  V(NativeContext) \
57  /* Subtypes of FixedArray */ \
58  V(Context) \
59  V(ScopeInfo) \
60  V(ScriptContextTable) \
61  /* Subtypes of FixedArrayBase */ \
62  V(BytecodeArray) \
63  V(FixedArray) \
64  V(FixedDoubleArray) \
65  /* Subtypes of Name */ \
66  V(InternalizedString) \
67  V(String) \
68  /* Subtypes of HeapObject */ \
69  V(AllocationSite) \
70  V(Cell) \
71  V(Code) \
72  V(DescriptorArray) \
73  V(FeedbackVector) \
74  V(FixedArrayBase) \
75  V(HeapNumber) \
76  V(JSObject) \
77  V(Map) \
78  V(Module) \
79  V(MutableHeapNumber) \
80  V(Name) \
81  V(PropertyCell) \
82  V(SharedFunctionInfo) \
83  /* Subtypes of Object */ \
84  V(HeapObject)
85 
86 class CompilationDependencies;
87 class JSHeapBroker;
88 class ObjectData;
89 class PerIsolateCompilerCache;
90 #define FORWARD_DECL(Name) class Name##Ref;
91 HEAP_BROKER_OBJECT_LIST(FORWARD_DECL)
92 #undef FORWARD_DECL
93 
94 class ObjectRef {
95  public:
96  ObjectRef(JSHeapBroker* broker, Handle<Object> object);
97  ObjectRef(JSHeapBroker* broker, ObjectData* data)
98  : data_(data), broker_(broker) {
99  CHECK_NOT_NULL(data_);
100  }
101 
102  Handle<Object> object() const;
103 
104  bool equals(const ObjectRef& other) const;
105 
106  bool IsSmi() const;
107  int AsSmi() const;
108 
109 #define HEAP_IS_METHOD_DECL(Name) bool Is##Name() const;
110  HEAP_BROKER_OBJECT_LIST(HEAP_IS_METHOD_DECL)
111 #undef HEAP_IS_METHOD_DECL
112 
113 #define HEAP_AS_METHOD_DECL(Name) Name##Ref As##Name() const;
114  HEAP_BROKER_OBJECT_LIST(HEAP_AS_METHOD_DECL)
115 #undef HEAP_AS_METHOD_DECL
116 
117  bool IsNullOrUndefined() const;
118 
119  bool BooleanValue() const;
120  double OddballToNumber() const;
121 
122  Isolate* isolate() const;
123 
124  protected:
125  JSHeapBroker* broker() const;
126  ObjectData* data() const;
127  ObjectData* data_; // Should be used only by object() getters.
128 
129  private:
130  JSHeapBroker* broker_;
131 };
132 
133 // Temporary class that carries information from a Map. We'd like to remove
134 // this class and use MapRef instead, but we can't as long as we support the
135 // kDisabled broker mode. That's because obtaining the MapRef via
136 // HeapObjectRef::map() requires a HandleScope when the broker is disabled.
137 // During OptimizeGraph we generally don't have a HandleScope, however. There
138 // are two places where we therefore use GetHeapObjectType() instead. Both that
139 // function and this class should eventually be removed.
141  public:
142  enum Flag : uint8_t { kUndetectable = 1 << 0, kCallable = 1 << 1 };
143 
144  typedef base::Flags<Flag> Flags;
145 
146  HeapObjectType(InstanceType instance_type, Flags flags,
147  OddballType oddball_type)
148  : instance_type_(instance_type),
149  oddball_type_(oddball_type),
150  flags_(flags) {
151  DCHECK_EQ(instance_type == ODDBALL_TYPE,
152  oddball_type != OddballType::kNone);
153  }
154 
155  OddballType oddball_type() const { return oddball_type_; }
156  InstanceType instance_type() const { return instance_type_; }
157  Flags flags() const { return flags_; }
158 
159  bool is_callable() const { return flags_ & kCallable; }
160  bool is_undetectable() const { return flags_ & kUndetectable; }
161 
162  private:
163  InstanceType const instance_type_;
164  OddballType const oddball_type_;
165  Flags const flags_;
166 };
167 
168 class HeapObjectRef : public ObjectRef {
169  public:
170  using ObjectRef::ObjectRef;
171  Handle<HeapObject> object() const;
172 
173  MapRef map() const;
174 
175  // See the comment on the HeapObjectType class.
176  HeapObjectType GetHeapObjectType() const;
177 };
178 
180  public:
181  using HeapObjectRef::HeapObjectRef;
182  Handle<PropertyCell> object() const;
183 
184  PropertyDetails property_details() const;
185  ObjectRef value() const;
186 };
187 
188 class JSObjectRef : public HeapObjectRef {
189  public:
190  using HeapObjectRef::HeapObjectRef;
191  Handle<JSObject> object() const;
192 
193  double RawFastDoublePropertyAt(FieldIndex index) const;
194  ObjectRef RawFastPropertyAt(FieldIndex index) const;
195 
196  FixedArrayBaseRef elements() const;
197  void EnsureElementsTenured();
198  ElementsKind GetElementsKind() const;
199 
200  void SerializeObjectCreateMap();
201  base::Optional<MapRef> GetObjectCreateMap() const;
202 };
203 
204 class JSDataViewRef : public JSObjectRef {
205  public:
206  using JSObjectRef::JSObjectRef;
207  Handle<JSDataView> object() const;
208 
209  size_t byte_length() const;
210  size_t byte_offset() const;
211 };
212 
214  public:
215  using JSObjectRef::JSObjectRef;
216  Handle<JSBoundFunction> object() const;
217 
218  void Serialize();
219 
220  // The following are available only after calling Serialize().
221  ObjectRef bound_target_function() const;
222  ObjectRef bound_this() const;
223  FixedArrayRef bound_arguments() const;
224 };
225 
226 class JSFunctionRef : public JSObjectRef {
227  public:
228  using JSObjectRef::JSObjectRef;
229  Handle<JSFunction> object() const;
230 
231  bool has_initial_map() const;
232  bool has_prototype() const;
233  bool PrototypeRequiresRuntimeLookup() const;
234 
235  void Serialize();
236 
237  // The following are available only after calling Serialize().
238  ObjectRef prototype() const;
239  MapRef initial_map() const;
240  ContextRef context() const;
241  NativeContextRef native_context() const;
242  SharedFunctionInfoRef shared() const;
243  int InitialMapInstanceSizeWithMinSlack() const;
244 };
245 
246 class JSRegExpRef : public JSObjectRef {
247  public:
248  using JSObjectRef::JSObjectRef;
249  Handle<JSRegExp> object() const;
250 
251  ObjectRef raw_properties_or_hash() const;
252  ObjectRef data() const;
253  ObjectRef source() const;
254  ObjectRef flags() const;
255  ObjectRef last_index() const;
256 };
257 
258 class HeapNumberRef : public HeapObjectRef {
259  public:
260  using HeapObjectRef::HeapObjectRef;
261  Handle<HeapNumber> object() const;
262 
263  double value() const;
264 };
265 
267  public:
268  using HeapObjectRef::HeapObjectRef;
269  Handle<MutableHeapNumber> object() const;
270 
271  double value() const;
272 };
273 
274 class ContextRef : public HeapObjectRef {
275  public:
276  using HeapObjectRef::HeapObjectRef;
277  Handle<Context> object() const;
278 
279  void Serialize();
280  ContextRef previous() const;
281  ObjectRef get(int index) const;
282 };
283 
284 #define BROKER_COMPULSORY_NATIVE_CONTEXT_FIELDS(V) \
285  V(JSFunction, array_function) \
286  V(JSFunction, boolean_function) \
287  V(JSFunction, bigint_function) \
288  V(JSFunction, number_function) \
289  V(JSFunction, object_function) \
290  V(JSFunction, promise_function) \
291  V(JSFunction, promise_then) \
292  V(JSFunction, string_function) \
293  V(JSFunction, symbol_function) \
294  V(JSGlobalProxy, global_proxy_object) \
295  V(JSObject, promise_prototype) \
296  V(Map, bound_function_with_constructor_map) \
297  V(Map, bound_function_without_constructor_map) \
298  V(Map, fast_aliased_arguments_map) \
299  V(Map, initial_array_iterator_map) \
300  V(Map, initial_string_iterator_map) \
301  V(Map, iterator_result_map) \
302  V(Map, js_array_holey_double_elements_map) \
303  V(Map, js_array_holey_elements_map) \
304  V(Map, js_array_holey_smi_elements_map) \
305  V(Map, js_array_packed_double_elements_map) \
306  V(Map, js_array_packed_elements_map) \
307  V(Map, js_array_packed_smi_elements_map) \
308  V(Map, sloppy_arguments_map) \
309  V(Map, slow_object_with_null_prototype_map) \
310  V(Map, strict_arguments_map) \
311  V(ScriptContextTable, script_context_table) \
312  V(SharedFunctionInfo, promise_capability_default_reject_shared_fun) \
313  V(SharedFunctionInfo, promise_catch_finally_shared_fun) \
314  V(SharedFunctionInfo, promise_then_finally_shared_fun) \
315  V(SharedFunctionInfo, promise_capability_default_resolve_shared_fun)
316 
317 // Those are set by Bootstrapper::ExportFromRuntime, which may not yet have
318 // happened when Turbofan is invoked via --always-opt.
319 #define BROKER_OPTIONAL_NATIVE_CONTEXT_FIELDS(V) \
320  V(Map, async_function_object_map) \
321  V(Map, map_key_iterator_map) \
322  V(Map, map_key_value_iterator_map) \
323  V(Map, map_value_iterator_map) \
324  V(Map, set_key_value_iterator_map) \
325  V(Map, set_value_iterator_map)
326 
327 #define BROKER_NATIVE_CONTEXT_FIELDS(V) \
328  BROKER_COMPULSORY_NATIVE_CONTEXT_FIELDS(V) \
329  BROKER_OPTIONAL_NATIVE_CONTEXT_FIELDS(V)
330 
331 class NativeContextRef : public ContextRef {
332  public:
333  using ContextRef::ContextRef;
334  Handle<NativeContext> object() const;
335 
336  void Serialize();
337 
338 #define DECL_ACCESSOR(type, name) type##Ref name() const;
339  BROKER_NATIVE_CONTEXT_FIELDS(DECL_ACCESSOR)
340 #undef DECL_ACCESSOR
341 
342  MapRef GetFunctionMapFromIndex(int index) const;
343  MapRef GetInitialJSArrayMap(ElementsKind kind) const;
344  base::Optional<JSFunctionRef> GetConstructorFunction(const MapRef& map) const;
345 };
346 
347 class NameRef : public HeapObjectRef {
348  public:
349  using HeapObjectRef::HeapObjectRef;
350  Handle<Name> object() const;
351 };
352 
354  public:
355  using HeapObjectRef::HeapObjectRef;
356  Handle<ScriptContextTable> object() const;
357 
358  struct LookupResult {
359  ContextRef context;
360  bool immutable;
361  int index;
362  };
363 
364  base::Optional<LookupResult> lookup(const NameRef& name) const;
365 };
366 
368  public:
369  using HeapObjectRef::HeapObjectRef;
370  Handle<DescriptorArray> object() const;
371 };
372 
374  public:
375  using HeapObjectRef::HeapObjectRef;
376  Handle<FeedbackVector> object() const;
377 
378  ObjectRef get(FeedbackSlot slot) const;
379 
380  void SerializeSlots();
381 };
382 
384  public:
385  using HeapObjectRef::HeapObjectRef;
386  Handle<AllocationSite> object() const;
387 
388  bool PointsToLiteral() const;
389  PretenureFlag GetPretenureMode() const;
390  ObjectRef nested_site() const;
391 
392  // {IsFastLiteral} determines whether the given array or object literal
393  // boilerplate satisfies all limits to be considered for fast deep-copying
394  // and computes the total size of all objects that are part of the graph.
395  //
396  // If PointsToLiteral() is false, then IsFastLiteral() is also false.
397  bool IsFastLiteral() const;
398  // We only serialize boilerplate if IsFastLiteral is true.
399  base::Optional<JSObjectRef> boilerplate() const;
400 
401  ElementsKind GetElementsKind() const;
402  bool CanInlineCall() const;
403 };
404 
405 class MapRef : public HeapObjectRef {
406  public:
407  using HeapObjectRef::HeapObjectRef;
408  Handle<Map> object() const;
409 
410  int instance_size() const;
411  InstanceType instance_type() const;
412  int GetInObjectProperties() const;
413  int GetInObjectPropertiesStartInWords() const;
414  int NumberOfOwnDescriptors() const;
415  int GetInObjectPropertyOffset(int index) const;
416  int constructor_function_index() const;
417  ElementsKind elements_kind() const;
418  bool is_stable() const;
419  bool is_extensible() const;
420  bool is_constructor() const;
421  bool has_prototype_slot() const;
422  bool is_access_check_needed() const;
423  bool is_deprecated() const;
424  bool CanBeDeprecated() const;
425  bool CanTransition() const;
426  bool IsInobjectSlackTrackingInProgress() const;
427  bool is_dictionary_map() const;
428  bool IsFixedCowArrayMap() const;
429  bool IsPrimitiveMap() const;
430  bool is_undetectable() const;
431  bool is_callable() const;
432  bool has_hidden_prototype() const;
433 
434 #define DEF_TESTER(Type, ...) bool Is##Type##Map() const;
435  INSTANCE_TYPE_CHECKERS(DEF_TESTER)
436 #undef DEF_TESTER
437 
438  ObjectRef GetConstructor() const;
439 
440  void SerializePrototype();
441  ObjectRef prototype() const;
442 
443  OddballType oddball_type() const;
444 
445  base::Optional<MapRef> AsElementsKind(ElementsKind kind) const;
446 
447  // Concerning the underlying instance_descriptors:
448  void SerializeOwnDescriptors();
449  MapRef FindFieldOwner(int descriptor_index) const;
450  PropertyDetails GetPropertyDetails(int descriptor_index) const;
451  NameRef GetPropertyKey(int descriptor_index) const;
452  FieldIndex GetFieldIndexFor(int descriptor_index) const;
453  ObjectRef GetFieldType(int descriptor_index) const;
454  bool IsUnboxedDoubleField(int descriptor_index) const;
455 };
456 
458  public:
459  using HeapObjectRef::HeapObjectRef;
460  Handle<FixedArrayBase> object() const;
461 
462  int length() const;
463 };
464 
466  public:
467  using FixedArrayBaseRef::FixedArrayBaseRef;
468  Handle<FixedArray> object() const;
469 
470  ObjectRef get(int i) const;
471 };
472 
474  public:
475  using FixedArrayBaseRef::FixedArrayBaseRef;
476  Handle<FixedDoubleArray> object() const;
477 
478  double get_scalar(int i) const;
479  bool is_the_hole(int i) const;
480 };
481 
483  public:
484  using FixedArrayBaseRef::FixedArrayBaseRef;
485  Handle<BytecodeArray> object() const;
486 
487  int register_count() const;
488 };
489 
490 class JSArrayRef : public JSObjectRef {
491  public:
492  using JSObjectRef::JSObjectRef;
493  Handle<JSArray> object() const;
494 
495  ObjectRef length() const;
496 };
497 
498 class ScopeInfoRef : public HeapObjectRef {
499  public:
500  using HeapObjectRef::HeapObjectRef;
501  Handle<ScopeInfo> object() const;
502 
503  int ContextLength() const;
504 };
505 
506 #define BROKER_SFI_FIELDS(V) \
507  V(int, internal_formal_parameter_count) \
508  V(bool, has_duplicate_parameters) \
509  V(int, function_map_index) \
510  V(FunctionKind, kind) \
511  V(LanguageMode, language_mode) \
512  V(bool, native) \
513  V(bool, HasBreakInfo) \
514  V(bool, HasBuiltinFunctionId) \
515  V(bool, HasBuiltinId) \
516  V(BuiltinFunctionId, builtin_function_id) \
517  V(bool, construct_as_builtin) \
518  V(bool, HasBytecodeArray)
519 
521  public:
522  using HeapObjectRef::HeapObjectRef;
523  Handle<SharedFunctionInfo> object() const;
524 
525  int builtin_id() const;
526  BytecodeArrayRef GetBytecodeArray() const;
527 #define DECL_ACCESSOR(type, name) type name() const;
528  BROKER_SFI_FIELDS(DECL_ACCESSOR)
529 #undef DECL_ACCESSOR
530 };
531 
532 class StringRef : public NameRef {
533  public:
534  using NameRef::NameRef;
535  Handle<String> object() const;
536 
537  int length() const;
538  uint16_t GetFirstChar();
539  base::Optional<double> ToNumber();
540  bool IsSeqString() const;
541  bool IsExternalString() const;
542 };
543 
544 class JSTypedArrayRef : public JSObjectRef {
545  public:
546  using JSObjectRef::JSObjectRef;
547  Handle<JSTypedArray> object() const;
548 
549  bool is_on_heap() const;
550  size_t length_value() const;
551  void* elements_external_pointer() const;
552 
553  void Serialize();
554 
555  HeapObjectRef buffer() const;
556 };
557 
558 class ModuleRef : public HeapObjectRef {
559  public:
560  using HeapObjectRef::HeapObjectRef;
561  Handle<Module> object() const;
562 
563  void Serialize();
564 
565  CellRef GetCell(int cell_index) const;
566 };
567 
568 class CellRef : public HeapObjectRef {
569  public:
570  using HeapObjectRef::HeapObjectRef;
571  Handle<Cell> object() const;
572 
573  ObjectRef value() const;
574 };
575 
577  public:
578  using JSObjectRef::JSObjectRef;
579  Handle<JSGlobalProxy> object() const;
580 };
581 
582 class CodeRef : public HeapObjectRef {
583  public:
584  using HeapObjectRef::HeapObjectRef;
585  Handle<Code> object() const;
586 };
587 
589  public:
590  using StringRef::StringRef;
591  Handle<InternalizedString> object() const;
592 };
593 
594 class V8_EXPORT_PRIVATE JSHeapBroker : public NON_EXPORTED_BASE(ZoneObject) {
595  public:
596  JSHeapBroker(Isolate* isolate, Zone* broker_zone);
597  void SetNativeContextRef();
598  void SerializeStandardObjects();
599 
600  Isolate* isolate() const { return isolate_; }
601  Zone* zone() const { return current_zone_; }
602  NativeContextRef native_context() const { return native_context_.value(); }
603  PerIsolateCompilerCache* compiler_cache() const { return compiler_cache_; }
604 
605  enum BrokerMode { kDisabled, kSerializing, kSerialized, kRetired };
606  BrokerMode mode() const { return mode_; }
607  void StartSerializing();
608  void StopSerializing();
609  void Retire();
610  bool SerializingAllowed() const;
611 
612  // Returns nullptr iff handle unknown.
613  ObjectData* GetData(Handle<Object>) const;
614  // Never returns nullptr.
615  ObjectData* GetOrCreateData(Handle<Object>);
616  // Like the previous but wraps argument in handle first (for convenience).
617  ObjectData* GetOrCreateData(Object*);
618 
619  // Check if {object} is any native context's %ArrayPrototype% or
620  // %ObjectPrototype%.
621  bool IsArrayOrObjectPrototype(const JSObjectRef& object) const;
622 
623  void Trace(const char* format, ...) const;
624  void IncrementTracingIndentation();
625  void DecrementTracingIndentation();
626 
627  private:
628  friend class HeapObjectRef;
629  friend class ObjectRef;
630  friend class ObjectData;
631 
632  void SerializeShareableObjects();
633  void CollectArrayAndObjectPrototypes();
634 
635  Isolate* const isolate_;
636  Zone* const broker_zone_;
637  Zone* current_zone_;
638  base::Optional<NativeContextRef> native_context_;
639  RefsMap* refs_;
642  array_and_object_prototypes_;
643 
644  BrokerMode mode_ = kDisabled;
645  unsigned tracing_indentation_ = 0;
646  PerIsolateCompilerCache* compiler_cache_;
647 
648  static const size_t kMinimalRefsBucketCount = 8; // must be power of 2
649  static const size_t kInitialRefsBucketCount = 1024; // must be power of 2
650 };
651 
652 #define ASSIGN_RETURN_NO_CHANGE_IF_DATA_MISSING(something_var, \
653  optionally_something) \
654  auto optionally_something_ = optionally_something; \
655  if (!optionally_something_) \
656  return NoChangeBecauseOfMissingData(broker(), __FUNCTION__, __LINE__); \
657  something_var = *optionally_something_;
658 
659 class Reduction;
660 Reduction NoChangeBecauseOfMissingData(JSHeapBroker* broker,
661  const char* function, int line);
662 
663 } // namespace compiler
664 } // namespace internal
665 } // namespace v8
666 
667 #endif // V8_COMPILER_JS_HEAP_BROKER_H_
Definition: libplatform.h:13