Home | History | Annotate | Download | only in compiler
      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 
     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 
     44   OddballType oddball_type() const { return oddball_type_; }
     45   InstanceType instance_type() const { return instance_type_; }
     46   Flags flags() const { return flags_; }
     47 
     48   bool is_callable() const { return flags_ & kCallable; }
     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;
     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 
    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