Home | History | Annotate | Download | only in wasm
      1 // Copyright 2016 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_WASM_OBJECTS_H_
      6 #define V8_WASM_OBJECTS_H_
      7 
      8 #include "src/objects-inl.h"
      9 #include "src/wasm/managed.h"
     10 
     11 namespace v8 {
     12 namespace internal {
     13 namespace wasm {
     14 struct WasmModule;
     15 }
     16 
     17 class WasmCompiledModule;
     18 class WasmDebugInfo;
     19 class WasmInstanceObject;
     20 
     21 #define DECLARE_CASTS(name)             \
     22   static bool Is##name(Object* object); \
     23   static name* cast(Object* object)
     24 
     25 #define DECLARE_ACCESSORS(name, type) \
     26   type* get_##name();                 \
     27   void set_##name(type* value)
     28 
     29 #define DECLARE_OPTIONAL_ACCESSORS(name, type) \
     30   bool has_##name();                           \
     31   type* get_##name();                          \
     32   void set_##name(type* value)
     33 
     34 // Representation of a WebAssembly.Module JavaScript-level object.
     35 class WasmModuleObject : public JSObject {
     36  public:
     37   // TODO(titzer): add the brand as an internal field instead of a property.
     38   enum Fields { kCompiledModule, kFieldCount };
     39 
     40   DECLARE_CASTS(WasmModuleObject);
     41 
     42   WasmCompiledModule* compiled_module();
     43   wasm::WasmModule* module();
     44   int num_functions();
     45   bool is_asm_js();
     46   int GetAsmWasmSourcePosition(int func_index, int byte_offset);
     47   WasmDebugInfo* debug_info();
     48   void set_debug_info(WasmDebugInfo* debug_info);
     49   MaybeHandle<String> GetFunctionName(Isolate* isolate, int func_index);
     50 
     51   static Handle<WasmModuleObject> New(
     52       Isolate* isolate, Handle<WasmCompiledModule> compiled_module);
     53 };
     54 
     55 // Representation of a WebAssembly.Table JavaScript-level object.
     56 class WasmTableObject : public JSObject {
     57  public:
     58   // TODO(titzer): add the brand as an internal field instead of a property.
     59   enum Fields { kFunctions, kMaximum, kDispatchTables, kFieldCount };
     60 
     61   DECLARE_CASTS(WasmTableObject);
     62   DECLARE_ACCESSORS(functions, FixedArray);
     63 
     64   FixedArray* get_dispatch_tables();
     65   uint32_t current_length();
     66   uint32_t maximum_length();
     67 
     68   static Handle<WasmTableObject> New(Isolate* isolate, uint32_t initial,
     69                                      uint32_t maximum,
     70                                      Handle<FixedArray>* js_functions);
     71   static bool Grow(Handle<WasmTableObject> table, uint32_t count);
     72   static Handle<FixedArray> AddDispatchTable(
     73       Isolate* isolate, Handle<WasmTableObject> table,
     74       Handle<WasmInstanceObject> instance, int table_index,
     75       Handle<FixedArray> dispatch_table);
     76 };
     77 
     78 // Representation of a WebAssembly.Memory JavaScript-level object.
     79 class WasmMemoryObject : public JSObject {
     80  public:
     81   // TODO(titzer): add the brand as an internal field instead of a property.
     82   enum Fields : uint8_t { kArrayBuffer, kMaximum, kInstance, kFieldCount };
     83 
     84   DECLARE_CASTS(WasmMemoryObject);
     85   DECLARE_ACCESSORS(buffer, JSArrayBuffer);
     86 
     87   void AddInstance(WasmInstanceObject* object);
     88   uint32_t current_pages();
     89   int32_t maximum_pages();  // returns < 0 if there is no maximum
     90 
     91   static Handle<WasmMemoryObject> New(Isolate* isolate,
     92                                       Handle<JSArrayBuffer> buffer,
     93                                       int maximum);
     94 
     95   static bool Grow(Handle<WasmMemoryObject> memory, uint32_t count);
     96 };
     97 
     98 // Representation of a WebAssembly.Instance JavaScript-level object.
     99 class WasmInstanceObject : public JSObject {
    100  public:
    101   // TODO(titzer): add the brand as an internal field instead of a property.
    102   enum Fields {
    103     kCompiledModule,
    104     kMemoryObject,
    105     kMemoryArrayBuffer,
    106     kGlobalsArrayBuffer,
    107     kDebugInfo,
    108     kFieldCount
    109   };
    110 
    111   DECLARE_CASTS(WasmInstanceObject);
    112 
    113   DECLARE_ACCESSORS(compiled_module, WasmCompiledModule);
    114   DECLARE_OPTIONAL_ACCESSORS(globals_buffer, JSArrayBuffer);
    115   DECLARE_OPTIONAL_ACCESSORS(memory_buffer, JSArrayBuffer);
    116   DECLARE_OPTIONAL_ACCESSORS(memory_object, WasmMemoryObject);
    117   DECLARE_OPTIONAL_ACCESSORS(debug_info, WasmDebugInfo);
    118 
    119   WasmModuleObject* module_object();
    120   wasm::WasmModule* module();
    121 
    122   static Handle<WasmInstanceObject> New(
    123       Isolate* isolate, Handle<WasmCompiledModule> compiled_module);
    124 };
    125 
    126 // Representation of an exported WASM function.
    127 class WasmExportedFunction : public JSFunction {
    128  public:
    129   enum Fields { kInstance, kIndex, kFieldCount };
    130 
    131   DECLARE_CASTS(WasmExportedFunction);
    132 
    133   WasmInstanceObject* instance();
    134   int function_index();
    135 
    136   static Handle<WasmExportedFunction> New(Isolate* isolate,
    137                                           Handle<WasmInstanceObject> instance,
    138                                           Handle<String> name,
    139                                           Handle<Code> export_wrapper,
    140                                           int arity, int func_index);
    141 };
    142 
    143 class WasmCompiledModule : public FixedArray {
    144  public:
    145   enum Fields { kFieldCount };
    146 
    147   static WasmCompiledModule* cast(Object* fixed_array) {
    148     SLOW_DCHECK(IsWasmCompiledModule(fixed_array));
    149     return reinterpret_cast<WasmCompiledModule*>(fixed_array);
    150   }
    151 
    152 #define WCM_OBJECT_OR_WEAK(TYPE, NAME, ID)                           \
    153   Handle<TYPE> NAME() const { return handle(ptr_to_##NAME()); }      \
    154                                                                      \
    155   MaybeHandle<TYPE> maybe_##NAME() const {                           \
    156     if (has_##NAME()) return NAME();                                 \
    157     return MaybeHandle<TYPE>();                                      \
    158   }                                                                  \
    159                                                                      \
    160   TYPE* ptr_to_##NAME() const {                                      \
    161     Object* obj = get(ID);                                           \
    162     if (!obj->Is##TYPE()) return nullptr;                            \
    163     return TYPE::cast(obj);                                          \
    164   }                                                                  \
    165                                                                      \
    166   void set_##NAME(Handle<TYPE> value) { set_ptr_to_##NAME(*value); } \
    167                                                                      \
    168   void set_ptr_to_##NAME(TYPE* value) { set(ID, value); }            \
    169                                                                      \
    170   bool has_##NAME() const { return get(ID)->Is##TYPE(); }            \
    171                                                                      \
    172   void reset_##NAME() { set_undefined(ID); }
    173 
    174 #define WCM_OBJECT(TYPE, NAME) WCM_OBJECT_OR_WEAK(TYPE, NAME, kID_##NAME)
    175 
    176 #define WCM_SMALL_NUMBER(TYPE, NAME)                               \
    177   TYPE NAME() const {                                              \
    178     return static_cast<TYPE>(Smi::cast(get(kID_##NAME))->value()); \
    179   }                                                                \
    180   void set_##NAME(TYPE value) { set(kID_##NAME, Smi::FromInt(value)); }
    181 
    182 #define WCM_WEAK_LINK(TYPE, NAME)                        \
    183   WCM_OBJECT_OR_WEAK(WeakCell, weak_##NAME, kID_##NAME); \
    184                                                          \
    185   Handle<TYPE> NAME() const {                            \
    186     return handle(TYPE::cast(weak_##NAME()->value()));   \
    187   }
    188 
    189 #define CORE_WCM_PROPERTY_TABLE(MACRO)                \
    190   MACRO(OBJECT, FixedArray, code_table)               \
    191   MACRO(OBJECT, Foreign, module_wrapper)              \
    192   /* For debugging: */                                \
    193   MACRO(OBJECT, SeqOneByteString, module_bytes)       \
    194   MACRO(OBJECT, Script, script)                       \
    195   MACRO(OBJECT, ByteArray, asm_js_offset_tables)      \
    196   /* End of debugging stuff */                        \
    197   MACRO(OBJECT, FixedArray, function_tables)          \
    198   MACRO(OBJECT, FixedArray, empty_function_tables)    \
    199   MACRO(OBJECT, JSArrayBuffer, memory)                \
    200   MACRO(SMALL_NUMBER, uint32_t, min_mem_pages)        \
    201   MACRO(SMALL_NUMBER, uint32_t, max_mem_pages)        \
    202   MACRO(WEAK_LINK, WasmCompiledModule, next_instance) \
    203   MACRO(WEAK_LINK, WasmCompiledModule, prev_instance) \
    204   MACRO(WEAK_LINK, JSObject, owning_instance)         \
    205   MACRO(WEAK_LINK, JSObject, wasm_module)
    206 
    207 #if DEBUG
    208 #define DEBUG_ONLY_TABLE(MACRO) MACRO(SMALL_NUMBER, uint32_t, instance_id)
    209 #else
    210 #define DEBUG_ONLY_TABLE(IGNORE)
    211   uint32_t instance_id() const { return -1; }
    212 #endif
    213 
    214 #define WCM_PROPERTY_TABLE(MACRO) \
    215   CORE_WCM_PROPERTY_TABLE(MACRO)  \
    216   DEBUG_ONLY_TABLE(MACRO)
    217 
    218  private:
    219   enum PropertyIndices {
    220 #define INDICES(IGNORE1, IGNORE2, NAME) kID_##NAME,
    221     WCM_PROPERTY_TABLE(INDICES) Count
    222 #undef INDICES
    223   };
    224 
    225  public:
    226   static Handle<WasmCompiledModule> New(
    227       Isolate* isolate, Handle<Managed<wasm::WasmModule>> module_wrapper);
    228 
    229   static Handle<WasmCompiledModule> Clone(Isolate* isolate,
    230                                           Handle<WasmCompiledModule> module) {
    231     Handle<WasmCompiledModule> ret = Handle<WasmCompiledModule>::cast(
    232         isolate->factory()->CopyFixedArray(module));
    233     ret->InitId();
    234     ret->reset_weak_owning_instance();
    235     ret->reset_weak_next_instance();
    236     ret->reset_weak_prev_instance();
    237     return ret;
    238   }
    239 
    240   uint32_t mem_size() const;
    241   uint32_t default_mem_size() const;
    242 
    243   wasm::WasmModule* module() const;
    244 
    245 #define DECLARATION(KIND, TYPE, NAME) WCM_##KIND(TYPE, NAME)
    246   WCM_PROPERTY_TABLE(DECLARATION)
    247 #undef DECLARATION
    248 
    249   static bool IsWasmCompiledModule(Object* obj);
    250 
    251   void PrintInstancesChain();
    252 
    253   static void RecreateModuleWrapper(Isolate* isolate,
    254                                     Handle<FixedArray> compiled_module);
    255 
    256   // Extract a function name from the given wasm instance.
    257   // Returns a null handle if the function is unnamed or the name is not a valid
    258   // UTF-8 string.
    259   static MaybeHandle<String> GetFunctionName(
    260       Handle<WasmCompiledModule> compiled_module, uint32_t func_index);
    261 
    262  private:
    263   void InitId();
    264 
    265   DISALLOW_IMPLICIT_CONSTRUCTORS(WasmCompiledModule);
    266 };
    267 
    268 class WasmDebugInfo : public FixedArray {
    269  public:
    270   enum class Fields { kFieldCount };
    271 
    272   static Handle<WasmDebugInfo> New(Handle<JSObject> wasm);
    273 
    274   static bool IsDebugInfo(Object* object);
    275   static WasmDebugInfo* cast(Object* object);
    276 
    277   JSObject* wasm_instance();
    278 
    279   bool SetBreakPoint(int byte_offset);
    280 
    281   // Get the Script for the specified function.
    282   static Script* GetFunctionScript(Handle<WasmDebugInfo> debug_info,
    283                                    int func_index);
    284 
    285   // Disassemble the specified function from this module.
    286   static Handle<String> DisassembleFunction(Handle<WasmDebugInfo> debug_info,
    287                                             int func_index);
    288 
    289   // Get the offset table for the specified function, mapping from byte offsets
    290   // to position in the disassembly.
    291   // Returns an array with three entries per instruction: byte offset, line and
    292   // column.
    293   static Handle<FixedArray> GetFunctionOffsetTable(
    294       Handle<WasmDebugInfo> debug_info, int func_index);
    295 
    296   // Get the asm.js source position from a byte offset.
    297   // Must only be called if the associated wasm object was created from asm.js.
    298   static int GetAsmJsSourcePosition(Handle<WasmDebugInfo> debug_info,
    299                                     int func_index, int byte_offset);
    300 };
    301 
    302 #undef DECLARE_ACCESSORS
    303 #undef DECLARE_OPTIONAL_ACCESSORS
    304 
    305 }  // namespace internal
    306 }  // namespace v8
    307 
    308 #endif  // V8_WASM_OBJECTS_H_
    309