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 cast(Object * fixed_array)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) instance_id()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 Clone(Isolate * isolate,Handle<WasmCompiledModule> module)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