• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/globals.h"
11 #include "src/objects.h"
12 #include "src/zone/zone-containers.h"
13 
14 namespace v8 {
15 namespace internal {
16 namespace compiler {
17 
18 enum class OddballType : uint8_t {
19   kNone,     // Not an Oddball.
20   kBoolean,  // True or False.
21   kUndefined,
22   kNull,
23   kHole,
24   kUninitialized,
25   kOther  // Oddball, but none of the above.
26 };
27 
28 // TODO(neis): Get rid of the HeapObjectType class.
29 class HeapObjectType {
30  public:
31   enum Flag : uint8_t { kUndetectable = 1 << 0, kCallable = 1 << 1 };
32 
33   typedef base::Flags<Flag> Flags;
34 
HeapObjectType(InstanceType instance_type,Flags flags,OddballType oddball_type)35   HeapObjectType(InstanceType instance_type, Flags flags,
36                  OddballType oddball_type)
37       : instance_type_(instance_type),
38         oddball_type_(oddball_type),
39         flags_(flags) {
40     DCHECK_EQ(instance_type == ODDBALL_TYPE,
41               oddball_type != OddballType::kNone);
42   }
43 
oddball_type()44   OddballType oddball_type() const { return oddball_type_; }
instance_type()45   InstanceType instance_type() const { return instance_type_; }
flags()46   Flags flags() const { return flags_; }
47 
is_callable()48   bool is_callable() const { return flags_ & kCallable; }
is_undetectable()49   bool is_undetectable() const { return flags_ & kUndetectable; }
50 
51  private:
52   InstanceType const instance_type_;
53   OddballType const oddball_type_;
54   Flags const flags_;
55 };
56 
57 // This list is sorted such that subtypes appear before their supertypes.
58 // DO NOT VIOLATE THIS PROPERTY!
59 #define HEAP_BROKER_OBJECT_LIST(V) \
60   /* Subtypes of JSObject */       \
61   V(JSArray)                       \
62   V(JSFunction)                    \
63   V(JSGlobalProxy)                 \
64   V(JSRegExp)                      \
65   /* Subtypes of Context */        \
66   V(NativeContext)                 \
67   /* Subtypes of FixedArrayBase */ \
68   V(BytecodeArray)                 \
69   V(FixedArray)                    \
70   V(FixedDoubleArray)              \
71   /* Subtypes of Name */           \
72   V(InternalizedString)            \
73   V(String)                        \
74   /* Subtypes of HeapObject */     \
75   V(AllocationSite)                \
76   V(Cell)                          \
77   V(Code)                          \
78   V(FeedbackVector)                \
79   V(Map)                           \
80   V(Module)                        \
81   V(ScopeInfo)                     \
82   V(ScriptContextTable)            \
83   V(SharedFunctionInfo)            \
84   V(Context)                       \
85   V(FixedArrayBase)                \
86   V(HeapNumber)                    \
87   V(JSObject)                      \
88   V(MutableHeapNumber)             \
89   V(Name)                          \
90   V(PropertyCell)                  \
91   /* Subtypes of Object */         \
92   V(HeapObject)
93 
94 class CompilationDependencies;
95 class JSHeapBroker;
96 class ObjectData;
97 #define FORWARD_DECL(Name) class Name##Ref;
HEAP_BROKER_OBJECT_LIST(FORWARD_DECL)98 HEAP_BROKER_OBJECT_LIST(FORWARD_DECL)
99 #undef FORWARD_DECL
100 
101 class ObjectRef {
102  public:
103   ObjectRef(JSHeapBroker* broker, Handle<Object> object);
104   explicit ObjectRef(ObjectData* data) : data_(data) { CHECK_NOT_NULL(data_); }
105 
106   bool equals(const ObjectRef& other) const;
107 
108   Handle<Object> object() const;
109   // TODO(neis): Remove eventually.
110   template <typename T>
111   Handle<T> object() const {
112     AllowHandleDereference handle_dereference;
113     return Handle<T>::cast(object());
114   }
115 
116   OddballType oddball_type() const;
117 
118   bool IsSmi() const;
119   int AsSmi() const;
120 
121 #define HEAP_IS_METHOD_DECL(Name) bool Is##Name() const;
122   HEAP_BROKER_OBJECT_LIST(HEAP_IS_METHOD_DECL)
123 #undef HEAP_IS_METHOD_DECL
124 
125 #define HEAP_AS_METHOD_DECL(Name) Name##Ref As##Name() const;
126   HEAP_BROKER_OBJECT_LIST(HEAP_AS_METHOD_DECL)
127 #undef HEAP_AS_METHOD_DECL
128 
129   StringRef TypeOf() const;
130   bool BooleanValue();
131   double OddballToNumber() const;
132 
133   Isolate* isolate() const;
134 
135  protected:
136   JSHeapBroker* broker() const;
137   ObjectData* data() const;
138 
139  private:
140   ObjectData* data_;
141 };
142 
143 class HeapObjectRef : public ObjectRef {
144  public:
145   using ObjectRef::ObjectRef;
146 
147   HeapObjectType type() const;
148   MapRef map() const;
149   base::Optional<MapRef> TryGetObjectCreateMap() const;
150   bool IsSeqString() const;
151   bool IsExternalString() const;
152 };
153 
154 class PropertyCellRef : public HeapObjectRef {
155  public:
156   using HeapObjectRef::HeapObjectRef;
157 
158   ObjectRef value() const;
159   PropertyDetails property_details() const;
160 };
161 
162 class JSObjectRef : public HeapObjectRef {
163  public:
164   using HeapObjectRef::HeapObjectRef;
165 
166   bool IsUnboxedDoubleField(FieldIndex index) const;
167   double RawFastDoublePropertyAt(FieldIndex index) const;
168   ObjectRef RawFastPropertyAt(FieldIndex index) const;
169 
170   FixedArrayBaseRef elements() const;
171   void EnsureElementsTenured();
172   ElementsKind GetElementsKind() const;
173 };
174 
175 class JSFunctionRef : public JSObjectRef {
176  public:
177   using JSObjectRef::JSObjectRef;
178 
179   bool IsConstructor() const;
180   bool has_initial_map() const;
181   MapRef initial_map() const;
182   bool has_prototype() const;
183   ObjectRef prototype() const;
184   bool PrototypeRequiresRuntimeLookup() const;
185   JSGlobalProxyRef global_proxy() const;
186   int InitialMapInstanceSizeWithMinSlack() const;
187   SharedFunctionInfoRef shared() const;
188 };
189 
190 class JSRegExpRef : public JSObjectRef {
191  public:
192   using JSObjectRef::JSObjectRef;
193 
194   ObjectRef raw_properties_or_hash() const;
195   ObjectRef data() const;
196   ObjectRef source() const;
197   ObjectRef flags() const;
198   ObjectRef last_index() const;
199 };
200 
201 class HeapNumberRef : public HeapObjectRef {
202  public:
203   using HeapObjectRef::HeapObjectRef;
204 
205   double value() const;
206 };
207 
208 class MutableHeapNumberRef : public HeapObjectRef {
209  public:
210   using HeapObjectRef::HeapObjectRef;
211 
212   double value() const;
213 };
214 
215 class ContextRef : public HeapObjectRef {
216  public:
217   using HeapObjectRef::HeapObjectRef;
218 
219   base::Optional<ContextRef> previous() const;
220   ObjectRef get(int index) const;
221 };
222 
223 #define BROKER_NATIVE_CONTEXT_FIELDS(V)       \
224   V(JSFunction, array_function)               \
225   V(JSFunction, object_function)              \
226   V(JSFunction, promise_function)             \
227   V(Map, fast_aliased_arguments_map)          \
228   V(Map, initial_array_iterator_map)          \
229   V(Map, iterator_result_map)                 \
230   V(Map, js_array_holey_double_elements_map)  \
231   V(Map, js_array_holey_elements_map)         \
232   V(Map, js_array_holey_smi_elements_map)     \
233   V(Map, js_array_packed_double_elements_map) \
234   V(Map, js_array_packed_elements_map)        \
235   V(Map, js_array_packed_smi_elements_map)    \
236   V(Map, map_key_iterator_map)                \
237   V(Map, map_key_value_iterator_map)          \
238   V(Map, map_value_iterator_map)              \
239   V(Map, set_key_value_iterator_map)          \
240   V(Map, set_value_iterator_map)              \
241   V(Map, sloppy_arguments_map)                \
242   V(Map, strict_arguments_map)                \
243   V(Map, string_iterator_map)                 \
244   V(ScriptContextTable, script_context_table)
245 
246 class NativeContextRef : public ContextRef {
247  public:
248   using ContextRef::ContextRef;
249 
250 #define DECL_ACCESSOR(type, name) type##Ref name() const;
251   BROKER_NATIVE_CONTEXT_FIELDS(DECL_ACCESSOR)
252 #undef DECL_ACCESSOR
253 
254   MapRef GetFunctionMapFromIndex(int index) const;
255   MapRef GetInitialJSArrayMap(ElementsKind kind) const;
256 };
257 
258 class NameRef : public HeapObjectRef {
259  public:
260   using HeapObjectRef::HeapObjectRef;
261 };
262 
263 class ScriptContextTableRef : public HeapObjectRef {
264  public:
265   using HeapObjectRef::HeapObjectRef;
266 
267   struct LookupResult {
268     ContextRef context;
269     bool immutable;
270     int index;
271   };
272 
273   base::Optional<LookupResult> lookup(const NameRef& name) const;
274 };
275 
276 class FeedbackVectorRef : public HeapObjectRef {
277  public:
278   using HeapObjectRef::HeapObjectRef;
279 
280   ObjectRef get(FeedbackSlot slot) const;
281 };
282 
283 class AllocationSiteRef : public HeapObjectRef {
284  public:
285   using HeapObjectRef::HeapObjectRef;
286 
287   bool PointsToLiteral() const;
288   PretenureFlag GetPretenureMode() const;
289   ObjectRef nested_site() const;
290 
291   // {IsFastLiteral} determines whether the given array or object literal
292   // boilerplate satisfies all limits to be considered for fast deep-copying
293   // and computes the total size of all objects that are part of the graph.
294   //
295   // If PointsToLiteral() is false, then IsFastLiteral() is also false.
296   bool IsFastLiteral() const;
297   // We only serialize boilerplate if IsFastLiteral is true.
298   base::Optional<JSObjectRef> boilerplate() const;
299 
300   ElementsKind GetElementsKind() const;
301   bool CanInlineCall() const;
302 };
303 
304 class MapRef : public HeapObjectRef {
305  public:
306   using HeapObjectRef::HeapObjectRef;
307 
308   int instance_size() const;
309   InstanceType instance_type() const;
310   int GetInObjectProperties() const;
311   int GetInObjectPropertiesStartInWords() const;
312   int NumberOfOwnDescriptors() const;
313   int GetInObjectPropertyOffset(int index) const;
314   ElementsKind elements_kind() const;
315   bool is_stable() const;
316   bool has_prototype_slot() const;
317   bool is_deprecated() const;
318   bool CanBeDeprecated() const;
319   bool CanTransition() const;
320   bool IsInobjectSlackTrackingInProgress() const;
321   bool is_dictionary_map() const;
322   bool IsJSArrayMap() const;
323   bool IsFixedCowArrayMap() const;
324 
325   ObjectRef constructor_or_backpointer() const;
326 
327   base::Optional<MapRef> AsElementsKind(ElementsKind kind) const;
328 
329   // Concerning the underlying instance_descriptors:
330   MapRef FindFieldOwner(int descriptor) const;
331   PropertyDetails GetPropertyDetails(int i) const;
332   NameRef GetPropertyKey(int i) const;
333   FieldIndex GetFieldIndexFor(int i) const;
334   ObjectRef GetFieldType(int descriptor) const;
335 };
336 
337 class FixedArrayBaseRef : public HeapObjectRef {
338  public:
339   using HeapObjectRef::HeapObjectRef;
340 
341   int length() const;
342 };
343 
344 class FixedArrayRef : public FixedArrayBaseRef {
345  public:
346   using FixedArrayBaseRef::FixedArrayBaseRef;
347 
348   ObjectRef get(int i) const;
349   bool is_the_hole(int i) const;
350 };
351 
352 class FixedDoubleArrayRef : public FixedArrayBaseRef {
353  public:
354   using FixedArrayBaseRef::FixedArrayBaseRef;
355 
356   double get_scalar(int i) const;
357   bool is_the_hole(int i) const;
358 };
359 
360 class BytecodeArrayRef : public FixedArrayBaseRef {
361  public:
362   using FixedArrayBaseRef::FixedArrayBaseRef;
363 
364   int register_count() const;
365 };
366 
367 class JSArrayRef : public JSObjectRef {
368  public:
369   using JSObjectRef::JSObjectRef;
370 
371   ObjectRef length() const;
372 };
373 
374 class ScopeInfoRef : public HeapObjectRef {
375  public:
376   using HeapObjectRef::HeapObjectRef;
377 
378   int ContextLength() const;
379 };
380 
381 #define BROKER_SFI_FIELDS(V)                \
382   V(int, internal_formal_parameter_count)   \
383   V(bool, has_duplicate_parameters)         \
384   V(int, function_map_index)                \
385   V(FunctionKind, kind)                     \
386   V(LanguageMode, language_mode)            \
387   V(bool, native)                           \
388   V(bool, HasBreakInfo)                     \
389   V(bool, HasBuiltinFunctionId)             \
390   V(bool, HasBuiltinId)                     \
391   V(BuiltinFunctionId, builtin_function_id) \
392   V(bool, construct_as_builtin)             \
393   V(bool, HasBytecodeArray)
394 
395 class SharedFunctionInfoRef : public HeapObjectRef {
396  public:
397   using HeapObjectRef::HeapObjectRef;
398 
399   int builtin_id() const;
400   BytecodeArrayRef GetBytecodeArray() const;
401 #define DECL_ACCESSOR(type, name) type name() const;
402   BROKER_SFI_FIELDS(DECL_ACCESSOR)
403 #undef DECL_ACCSESOR
404 };
405 
406 class StringRef : public NameRef {
407  public:
408   using NameRef::NameRef;
409 
410   int length() const;
411   uint16_t GetFirstChar();
412   base::Optional<double> ToNumber();
413 };
414 
415 class ModuleRef : public HeapObjectRef {
416  public:
417   using HeapObjectRef::HeapObjectRef;
418 
419   CellRef GetCell(int cell_index);
420 };
421 
422 class CellRef : public HeapObjectRef {
423  public:
424   using HeapObjectRef::HeapObjectRef;
425 };
426 
427 class JSGlobalProxyRef : public JSObjectRef {
428  public:
429   using JSObjectRef::JSObjectRef;
430 };
431 
432 class CodeRef : public HeapObjectRef {
433  public:
434   using HeapObjectRef::HeapObjectRef;
435 };
436 
437 class InternalizedStringRef : public StringRef {
438  public:
439   using StringRef::StringRef;
440 };
441 
NON_EXPORTED_BASE(ZoneObject)442 class V8_EXPORT_PRIVATE JSHeapBroker : public NON_EXPORTED_BASE(ZoneObject) {
443  public:
444   JSHeapBroker(Isolate* isolate, Zone* zone);
445   void SerializeStandardObjects();
446 
447   HeapObjectType HeapObjectTypeFromMap(Handle<Map> map) const {
448     AllowHandleDereference handle_dereference;
449     return HeapObjectTypeFromMap(*map);
450   }
451 
452   Isolate* isolate() const { return isolate_; }
453   Zone* zone() const { return zone_; }
454 
455   enum BrokerMode { kDisabled, kSerializing, kSerialized };
456   BrokerMode mode() const { return mode_; }
457   void StopSerializing() {
458     CHECK_EQ(mode_, kSerializing);
459     mode_ = kSerialized;
460   }
461   bool SerializingAllowed() const;
462 
463   // Returns nullptr iff handle unknown.
464   ObjectData* GetData(Handle<Object>) const;
465   // Never returns nullptr.
466   ObjectData* GetOrCreateData(Handle<Object>);
467 
468   void Trace(const char* format, ...) const;
469 
470  private:
471   friend class HeapObjectRef;
472   friend class ObjectRef;
473   friend class ObjectData;
474 
475   // TODO(neis): Remove eventually.
476   HeapObjectType HeapObjectTypeFromMap(Map* map) const;
477 
478   void AddData(Handle<Object> object, ObjectData* data);
479 
480   Isolate* const isolate_;
481   Zone* const zone_;
482   ZoneUnorderedMap<Address, ObjectData*> refs_;
483   BrokerMode mode_;
484 };
485 
486 #define ASSIGN_RETURN_NO_CHANGE_IF_DATA_MISSING(something_var,          \
487                                                 optionally_something)   \
488   auto optionally_something_ = optionally_something;                    \
489   if (!optionally_something_)                                           \
490     return NoChangeBecauseOfMissingData(js_heap_broker(), __FUNCTION__, \
491                                         __LINE__);                      \
492   something_var = *optionally_something_;
493 
494 class Reduction;
495 Reduction NoChangeBecauseOfMissingData(JSHeapBroker* broker,
496                                        const char* function, int line);
497 
498 }  // namespace compiler
499 }  // namespace internal
500 }  // namespace v8
501 
502 #endif  // V8_COMPILER_JS_HEAP_BROKER_H_
503