Line data Source code
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/debug/debug.h"
9 : #include "src/debug/interface-types.h"
10 : #include "src/objects.h"
11 : #include "src/trap-handler/trap-handler.h"
12 : #include "src/wasm/wasm-limits.h"
13 :
14 : namespace v8 {
15 : namespace internal {
16 : namespace wasm {
17 : class InterpretedFrame;
18 : struct WasmModule;
19 : }
20 :
21 : class WasmCompiledModule;
22 : class WasmDebugInfo;
23 : class WasmInstanceObject;
24 : class WasmInstanceWrapper;
25 :
26 : #define DECLARE_CASTS(name) \
27 : static bool Is##name(Object* object); \
28 : static name* cast(Object* object)
29 :
30 : #define DECLARE_GETTER(name, type) type* name()
31 :
32 : #define DECLARE_ACCESSORS(name, type) \
33 : void set_##name(type* value); \
34 : DECLARE_GETTER(name, type)
35 :
36 : #define DECLARE_OPTIONAL_ACCESSORS(name, type) \
37 : bool has_##name(); \
38 : DECLARE_ACCESSORS(name, type)
39 :
40 : #define DECLARE_OPTIONAL_GETTER(name, type) \
41 : bool has_##name(); \
42 : DECLARE_GETTER(name, type)
43 :
44 : // Representation of a WebAssembly.Module JavaScript-level object.
45 : class WasmModuleObject : public JSObject {
46 : public:
47 : // If a second field is added, we need a kWrapperTracerHeader field as well.
48 : // TODO(titzer): add the brand as an embedder field instead of a property.
49 : enum Fields { kCompiledModule, kFieldCount };
50 :
51 : DECLARE_CASTS(WasmModuleObject);
52 :
53 : WasmCompiledModule* compiled_module();
54 :
55 : static Handle<WasmModuleObject> New(
56 : Isolate* isolate, Handle<WasmCompiledModule> compiled_module);
57 : };
58 :
59 : // Representation of a WebAssembly.Table JavaScript-level object.
60 : class WasmTableObject : public JSObject {
61 : public:
62 : // The 0-th field is used by the Blink Wrapper Tracer.
63 : // TODO(titzer): add the brand as an embedder field instead of a property.
64 : enum Fields {
65 : kWrapperTracerHeader,
66 : kFunctions,
67 : kMaximum,
68 : kDispatchTables,
69 : kFieldCount
70 : };
71 :
72 : DECLARE_CASTS(WasmTableObject);
73 : DECLARE_ACCESSORS(functions, FixedArray);
74 :
75 : FixedArray* dispatch_tables();
76 : uint32_t current_length();
77 : bool has_maximum_length();
78 : int64_t maximum_length(); // Returns < 0 if no maximum.
79 :
80 : static Handle<WasmTableObject> New(Isolate* isolate, uint32_t initial,
81 : int64_t maximum,
82 : Handle<FixedArray>* js_functions);
83 : static void Grow(Isolate* isolate, Handle<WasmTableObject> table,
84 : uint32_t count);
85 : static Handle<FixedArray> AddDispatchTable(
86 : Isolate* isolate, Handle<WasmTableObject> table,
87 : Handle<WasmInstanceObject> instance, int table_index,
88 : Handle<FixedArray> function_table, Handle<FixedArray> signature_table);
89 : };
90 :
91 : // Representation of a WebAssembly.Memory JavaScript-level object.
92 : class WasmMemoryObject : public JSObject {
93 : public:
94 : // The 0-th field is used by the Blink Wrapper Tracer.
95 : // TODO(titzer): add the brand as an embedder field instead of a property.
96 : enum Fields : uint8_t {
97 : kWrapperTracerHeader,
98 : kArrayBuffer,
99 : kMaximum,
100 : kInstancesLink,
101 : kFieldCount
102 : };
103 :
104 : DECLARE_CASTS(WasmMemoryObject);
105 : DECLARE_OPTIONAL_ACCESSORS(buffer, JSArrayBuffer);
106 : DECLARE_OPTIONAL_ACCESSORS(instances_link, WasmInstanceWrapper);
107 :
108 : void AddInstance(Isolate* isolate, Handle<WasmInstanceObject> object);
109 : void ResetInstancesLink(Isolate* isolate);
110 : uint32_t current_pages();
111 : bool has_maximum_pages();
112 : int32_t maximum_pages(); // Returns < 0 if there is no maximum.
113 :
114 : static Handle<WasmMemoryObject> New(Isolate* isolate,
115 : Handle<JSArrayBuffer> buffer,
116 : int32_t maximum);
117 :
118 : static int32_t Grow(Isolate*, Handle<WasmMemoryObject>, uint32_t pages);
119 : };
120 :
121 : // Representation of a WebAssembly.Instance JavaScript-level object.
122 : class WasmInstanceObject : public JSObject {
123 : public:
124 : // The 0-th field is used by the Blink Wrapper Tracer.
125 : // TODO(titzer): add the brand as an embedder field instead of a property.
126 : enum Fields {
127 : kWrapperTracerHeader,
128 : kCompiledModule,
129 : kMemoryObject,
130 : kMemoryArrayBuffer,
131 : kGlobalsArrayBuffer,
132 : kDebugInfo,
133 : kWasmMemInstanceWrapper,
134 : kFieldCount
135 : };
136 :
137 : DECLARE_CASTS(WasmInstanceObject);
138 :
139 : DECLARE_ACCESSORS(compiled_module, WasmCompiledModule);
140 : DECLARE_OPTIONAL_ACCESSORS(globals_buffer, JSArrayBuffer);
141 : DECLARE_OPTIONAL_ACCESSORS(memory_buffer, JSArrayBuffer);
142 : DECLARE_OPTIONAL_ACCESSORS(memory_object, WasmMemoryObject);
143 : DECLARE_OPTIONAL_ACCESSORS(debug_info, WasmDebugInfo);
144 : DECLARE_OPTIONAL_ACCESSORS(instance_wrapper, WasmInstanceWrapper);
145 :
146 : WasmModuleObject* module_object();
147 : wasm::WasmModule* module();
148 :
149 : // Get the debug info associated with the given wasm object.
150 : // If no debug info exists yet, it is created automatically.
151 : static Handle<WasmDebugInfo> GetOrCreateDebugInfo(Handle<WasmInstanceObject>);
152 :
153 : static Handle<WasmInstanceObject> New(Isolate*, Handle<WasmCompiledModule>);
154 :
155 : int32_t GetMemorySize();
156 :
157 : static int32_t GrowMemory(Isolate*, Handle<WasmInstanceObject>,
158 : uint32_t pages);
159 :
160 : uint32_t GetMaxMemoryPages();
161 : };
162 :
163 : // Representation of an exported WASM function.
164 : class WasmExportedFunction : public JSFunction {
165 : public:
166 : // The 0-th field is used by the Blink Wrapper Tracer.
167 : enum Fields { kWrapperTracerHeader, kInstance, kIndex, kFieldCount };
168 :
169 : DECLARE_CASTS(WasmExportedFunction);
170 :
171 : WasmInstanceObject* instance();
172 : int function_index();
173 :
174 : static Handle<WasmExportedFunction> New(Isolate* isolate,
175 : Handle<WasmInstanceObject> instance,
176 : MaybeHandle<String> maybe_name,
177 : int func_index, int arity,
178 : Handle<Code> export_wrapper);
179 : };
180 :
181 : // Information shared by all WasmCompiledModule objects for the same module.
182 : class WasmSharedModuleData : public FixedArray {
183 : // The 0-th field is used by the Blink Wrapper Tracer.
184 : enum Fields {
185 : kWrapperTracerHeader,
186 : kModuleWrapper,
187 : kModuleBytes,
188 : kScript,
189 : kAsmJsOffsetTable,
190 : kBreakPointInfos,
191 : kLazyCompilationOrchestrator,
192 : kFieldCount
193 : };
194 :
195 : public:
196 : DECLARE_CASTS(WasmSharedModuleData);
197 :
198 : DECLARE_GETTER(module, wasm::WasmModule);
199 : DECLARE_OPTIONAL_ACCESSORS(module_bytes, SeqOneByteString);
200 : DECLARE_GETTER(script, Script);
201 : DECLARE_OPTIONAL_ACCESSORS(asm_js_offset_table, ByteArray);
202 : DECLARE_OPTIONAL_GETTER(breakpoint_infos, FixedArray);
203 :
204 : static Handle<WasmSharedModuleData> New(
205 : Isolate* isolate, Handle<Foreign> module_wrapper,
206 : Handle<SeqOneByteString> module_bytes, Handle<Script> script,
207 : Handle<ByteArray> asm_js_offset_table);
208 :
209 : // Check whether this module was generated from asm.js source.
210 : bool is_asm_js();
211 :
212 : static void ReinitializeAfterDeserialization(Isolate*,
213 : Handle<WasmSharedModuleData>);
214 :
215 : static void AddBreakpoint(Handle<WasmSharedModuleData>, int position,
216 : Handle<Object> break_point_object);
217 :
218 : static void SetBreakpointsOnNewInstance(Handle<WasmSharedModuleData>,
219 : Handle<WasmInstanceObject>);
220 :
221 : static void PrepareForLazyCompilation(Handle<WasmSharedModuleData>);
222 :
223 : private:
224 : DECLARE_OPTIONAL_GETTER(lazy_compilation_orchestrator, Foreign);
225 : friend class WasmCompiledModule;
226 : };
227 :
228 : // This represents the set of wasm compiled functions, together
229 : // with all the information necessary for re-specializing them.
230 : //
231 : // We specialize wasm functions to their instance by embedding:
232 : // - raw interior pointers into the backing store of the array buffer
233 : // used as memory of a particular WebAssembly.Instance object.
234 : // - bounds check limits, computed at compile time, relative to the
235 : // size of the memory.
236 : // - the objects representing the function tables and signature tables
237 : // - raw pointer to the globals buffer.
238 : //
239 : // Even without instantiating, we need values for all of these parameters.
240 : // We need to track these values to be able to create new instances and
241 : // to be able to serialize/deserialize.
242 : // The design decisions for how we track these values is not too immediate,
243 : // and it deserves a summary. The "tricky" ones are: memory, globals, and
244 : // the tables (signature and functions).
245 : // The first 2 (memory & globals) are embedded as raw pointers to native
246 : // buffers. All we need to track them is the start addresses and, in the
247 : // case of memory, the size. We model all of them as HeapNumbers, because
248 : // we need to store size_t values (for addresses), and potentially full
249 : // 32 bit unsigned values for the size. Smis are 31 bits.
250 : // For tables, we need to hold a reference to the JS Heap object, because
251 : // we embed them as objects, and they may move.
252 : class WasmCompiledModule : public FixedArray {
253 : public:
254 : enum Fields { kFieldCount };
255 :
256 : static WasmCompiledModule* cast(Object* fixed_array) {
257 : SLOW_DCHECK(IsWasmCompiledModule(fixed_array));
258 : return reinterpret_cast<WasmCompiledModule*>(fixed_array);
259 : }
260 :
261 : #define WCM_OBJECT_OR_WEAK(TYPE, NAME, ID, TYPE_CHECK, SETTER_MODIFIER) \
262 : public: \
263 : Handle<TYPE> NAME() const { return handle(ptr_to_##NAME()); } \
264 : \
265 : MaybeHandle<TYPE> maybe_##NAME() const { \
266 : if (has_##NAME()) return NAME(); \
267 : return MaybeHandle<TYPE>(); \
268 : } \
269 : \
270 : TYPE* maybe_ptr_to_##NAME() const { \
271 : Object* obj = get(ID); \
272 : if (!(TYPE_CHECK)) return nullptr; \
273 : return TYPE::cast(obj); \
274 : } \
275 : \
276 : TYPE* ptr_to_##NAME() const { \
277 : Object* obj = get(ID); \
278 : DCHECK(TYPE_CHECK); \
279 : return TYPE::cast(obj); \
280 : } \
281 : \
282 : bool has_##NAME() const { \
283 : Object* obj = get(ID); \
284 : return TYPE_CHECK; \
285 : } \
286 : \
287 : void reset_##NAME() { set_undefined(ID); } \
288 : \
289 : SETTER_MODIFIER: \
290 : void set_##NAME(Handle<TYPE> value) { set_ptr_to_##NAME(*value); } \
291 : void set_ptr_to_##NAME(TYPE* value) { set(ID, value); }
292 :
293 : #define WCM_OBJECT(TYPE, NAME) \
294 : WCM_OBJECT_OR_WEAK(TYPE, NAME, kID_##NAME, obj->Is##TYPE(), public)
295 :
296 : #define WCM_CONST_OBJECT(TYPE, NAME) \
297 : WCM_OBJECT_OR_WEAK(TYPE, NAME, kID_##NAME, obj->Is##TYPE(), private)
298 :
299 : #define WCM_WASM_OBJECT(TYPE, NAME) \
300 : WCM_OBJECT_OR_WEAK(TYPE, NAME, kID_##NAME, TYPE::Is##TYPE(obj), private)
301 :
302 : #define WCM_SMALL_CONST_NUMBER(TYPE, NAME) \
303 : public: \
304 : TYPE NAME() const { \
305 : return static_cast<TYPE>(Smi::cast(get(kID_##NAME))->value()); \
306 : } \
307 : \
308 : private: \
309 : void set_##NAME(TYPE value) { set(kID_##NAME, Smi::FromInt(value)); }
310 :
311 : #define WCM_WEAK_LINK(TYPE, NAME) \
312 : WCM_OBJECT_OR_WEAK(WeakCell, weak_##NAME, kID_##NAME, obj->IsWeakCell(), \
313 : public) \
314 : \
315 : public: \
316 : Handle<TYPE> NAME() const { \
317 : return handle(TYPE::cast(weak_##NAME()->value())); \
318 : }
319 :
320 : #define WCM_LARGE_NUMBER(TYPE, NAME) \
321 : public: \
322 : TYPE NAME() const { \
323 : Object* value = get(kID_##NAME); \
324 : DCHECK(value->IsMutableHeapNumber()); \
325 : return static_cast<TYPE>(HeapNumber::cast(value)->value()); \
326 : } \
327 : \
328 : void set_##NAME(TYPE value) { \
329 : Object* number = get(kID_##NAME); \
330 : DCHECK(number->IsMutableHeapNumber()); \
331 : HeapNumber::cast(number)->set_value(static_cast<double>(value)); \
332 : } \
333 : \
334 : static void recreate_##NAME(Handle<WasmCompiledModule> obj, \
335 : Factory* factory, TYPE init_val) { \
336 : Handle<HeapNumber> number = factory->NewHeapNumber( \
337 : static_cast<double>(init_val), MutableMode::MUTABLE, TENURED); \
338 : obj->set(kID_##NAME, *number); \
339 : } \
340 : bool has_##NAME() const { return get(kID_##NAME)->IsMutableHeapNumber(); }
341 :
342 : // Add values here if they are required for creating new instances or
343 : // for deserialization, and if they are serializable.
344 : // By default, instance values go to WasmInstanceObject, however, if
345 : // we embed the generated code with a value, then we track that value here.
346 : #define CORE_WCM_PROPERTY_TABLE(MACRO) \
347 : MACRO(WASM_OBJECT, WasmSharedModuleData, shared) \
348 : MACRO(OBJECT, Context, native_context) \
349 : MACRO(SMALL_CONST_NUMBER, uint32_t, num_imported_functions) \
350 : MACRO(CONST_OBJECT, FixedArray, code_table) \
351 : MACRO(OBJECT, FixedArray, weak_exported_functions) \
352 : MACRO(OBJECT, FixedArray, function_tables) \
353 : MACRO(OBJECT, FixedArray, signature_tables) \
354 : MACRO(CONST_OBJECT, FixedArray, empty_function_tables) \
355 : MACRO(LARGE_NUMBER, size_t, embedded_mem_start) \
356 : MACRO(LARGE_NUMBER, size_t, globals_start) \
357 : MACRO(LARGE_NUMBER, uint32_t, embedded_mem_size) \
358 : MACRO(SMALL_CONST_NUMBER, uint32_t, min_mem_pages) \
359 : MACRO(WEAK_LINK, WasmCompiledModule, next_instance) \
360 : MACRO(WEAK_LINK, WasmCompiledModule, prev_instance) \
361 : MACRO(WEAK_LINK, JSObject, owning_instance) \
362 : MACRO(WEAK_LINK, WasmModuleObject, wasm_module)
363 :
364 : #if DEBUG
365 : #define DEBUG_ONLY_TABLE(MACRO) MACRO(SMALL_CONST_NUMBER, uint32_t, instance_id)
366 : #else
367 : #define DEBUG_ONLY_TABLE(IGNORE)
368 :
369 : public:
370 : uint32_t instance_id() const { return static_cast<uint32_t>(-1); }
371 : #endif
372 :
373 : #define WCM_PROPERTY_TABLE(MACRO) \
374 : CORE_WCM_PROPERTY_TABLE(MACRO) \
375 : DEBUG_ONLY_TABLE(MACRO)
376 :
377 : private:
378 : enum PropertyIndices {
379 : #define INDICES(IGNORE1, IGNORE2, NAME) kID_##NAME,
380 : WCM_PROPERTY_TABLE(INDICES) Count
381 : #undef INDICES
382 : };
383 :
384 : public:
385 : static Handle<WasmCompiledModule> New(
386 : Isolate* isolate, Handle<WasmSharedModuleData> shared,
387 : Handle<FixedArray> code_table,
388 : MaybeHandle<FixedArray> maybe_empty_function_tables,
389 : MaybeHandle<FixedArray> maybe_signature_tables);
390 :
391 : static Handle<WasmCompiledModule> Clone(Isolate* isolate,
392 : Handle<WasmCompiledModule> module);
393 : static void Reset(Isolate* isolate, WasmCompiledModule* module);
394 :
395 11449 : Address GetEmbeddedMemStartOrNull() const {
396 : DisallowHeapAllocation no_gc;
397 11449 : if (has_embedded_mem_start()) {
398 5693 : return reinterpret_cast<Address>(embedded_mem_start());
399 : }
400 : return nullptr;
401 : }
402 :
403 4013 : Address GetGlobalsStartOrNull() const {
404 : DisallowHeapAllocation no_gc;
405 4013 : if (has_globals_start()) {
406 1443 : return reinterpret_cast<Address>(globals_start());
407 : }
408 : return nullptr;
409 : }
410 :
411 : uint32_t mem_size() const;
412 : uint32_t default_mem_size() const;
413 :
414 : void ResetSpecializationMemInfoIfNeeded();
415 : static void SetSpecializationMemInfoFrom(
416 : Factory* factory, Handle<WasmCompiledModule> compiled_module,
417 : Handle<JSArrayBuffer> buffer);
418 : static void SetGlobalsStartAddressFrom(
419 : Factory* factory, Handle<WasmCompiledModule> compiled_module,
420 : Handle<JSArrayBuffer> buffer);
421 :
422 : #define DECLARATION(KIND, TYPE, NAME) WCM_##KIND(TYPE, NAME)
423 5008934 : WCM_PROPERTY_TABLE(DECLARATION)
424 : #undef DECLARATION
425 :
426 : public:
427 : // Allow to call method on WasmSharedModuleData also on this object.
428 : #define FORWARD_SHARED(type, name) \
429 : type name() { return shared()->name(); }
430 529838 : FORWARD_SHARED(SeqOneByteString*, module_bytes)
431 617202 : FORWARD_SHARED(wasm::WasmModule*, module)
432 78990 : FORWARD_SHARED(Script*, script)
433 149106 : FORWARD_SHARED(bool, is_asm_js)
434 : #undef FORWARD_SHARED
435 :
436 : static bool IsWasmCompiledModule(Object* obj);
437 :
438 : void PrintInstancesChain();
439 :
440 : static void ReinitializeAfterDeserialization(Isolate*,
441 : Handle<WasmCompiledModule>);
442 :
443 : // Get the function name of the function identified by the given index.
444 : // Returns a null handle if the function is unnamed or the name is not a valid
445 : // UTF-8 string.
446 : static MaybeHandle<String> GetFunctionNameOrNull(
447 : Isolate* isolate, Handle<WasmCompiledModule> compiled_module,
448 : uint32_t func_index);
449 :
450 : // Get the function name of the function identified by the given index.
451 : // Returns "<WASM UNNAMED>" if the function is unnamed or the name is not a
452 : // valid UTF-8 string.
453 : static Handle<String> GetFunctionName(
454 : Isolate* isolate, Handle<WasmCompiledModule> compiled_module,
455 : uint32_t func_index);
456 :
457 : // Get the raw bytes of the function name of the function identified by the
458 : // given index.
459 : // Meant to be used for debugging or frame printing.
460 : // Does not allocate, hence gc-safe.
461 : Vector<const uint8_t> GetRawFunctionName(uint32_t func_index);
462 :
463 : // Return the byte offset of the function identified by the given index.
464 : // The offset will be relative to the start of the module bytes.
465 : // Returns -1 if the function index is invalid.
466 : int GetFunctionOffset(uint32_t func_index);
467 :
468 : // Returns the function containing the given byte offset.
469 : // Returns -1 if the byte offset is not contained in any function of this
470 : // module.
471 : int GetContainingFunction(uint32_t byte_offset);
472 :
473 : // Translate from byte offset in the module to function number and byte offset
474 : // within that function, encoded as line and column in the position info.
475 : // Returns true if the position is valid inside this module, false otherwise.
476 : bool GetPositionInfo(uint32_t position, Script::PositionInfo* info);
477 :
478 : // Get the asm.js source position from a byte offset.
479 : // Must only be called if the associated wasm object was created from asm.js.
480 : static int GetAsmJsSourcePosition(Handle<WasmCompiledModule> compiled_module,
481 : uint32_t func_index, uint32_t byte_offset,
482 : bool is_at_number_conversion);
483 :
484 : // Compute the disassembly of a wasm function.
485 : // Returns the disassembly string and a list of <byte_offset, line, column>
486 : // entries, mapping wasm byte offsets to line and column in the disassembly.
487 : // The list is guaranteed to be ordered by the byte_offset.
488 : // Returns an empty string and empty vector if the function index is invalid.
489 : debug::WasmDisassembly DisassembleFunction(int func_index);
490 :
491 : // Extract a portion of the wire bytes as UTF-8 string.
492 : // Returns a null handle if the respective bytes do not form a valid UTF-8
493 : // string.
494 : static MaybeHandle<String> ExtractUtf8StringFromModuleBytes(
495 : Isolate* isolate, Handle<WasmCompiledModule> compiled_module,
496 : uint32_t offset, uint32_t size);
497 :
498 : // Get a list of all possible breakpoints within a given range of this module.
499 : bool GetPossibleBreakpoints(const debug::Location& start,
500 : const debug::Location& end,
501 : std::vector<debug::BreakLocation>* locations);
502 :
503 : // Set a breakpoint on the given byte position inside the given module.
504 : // This will affect all live and future instances of the module.
505 : // The passed position might be modified to point to the next breakable
506 : // location inside the same function.
507 : // If it points outside a function, or behind the last breakable location,
508 : // this function returns false and does not set any breakpoint.
509 : static bool SetBreakPoint(Handle<WasmCompiledModule>, int* position,
510 : Handle<Object> break_point_object);
511 :
512 : // Return an empty handle if no breakpoint is hit at that location, or a
513 : // FixedArray with all hit breakpoint objects.
514 : MaybeHandle<FixedArray> CheckBreakPoints(int position);
515 :
516 : // Compile lazily the function called in the given caller code object at the
517 : // given offset.
518 : // If the called function cannot be determined from the caller (indirect
519 : // call / exported function), func_index must be set. Otherwise it can be -1.
520 : // If patch_caller is set, then all direct calls to functions which were
521 : // already lazily compiled are patched (at least the given call site).
522 : // Returns the Code to be called at the given call site, or an empty Handle if
523 : // an error occured during lazy compilation. In this case, an exception has
524 : // been set on the isolate.
525 : static MaybeHandle<Code> CompileLazy(Isolate*, Handle<WasmInstanceObject>,
526 : Handle<Code> caller, int offset,
527 : int func_index, bool patch_caller);
528 :
529 : void ReplaceCodeTableForTesting(Handle<FixedArray> testing_table) {
530 : set_code_table(testing_table);
531 : }
532 :
533 : private:
534 : void InitId();
535 :
536 : DISALLOW_IMPLICIT_CONSTRUCTORS(WasmCompiledModule);
537 : };
538 :
539 : class WasmDebugInfo : public FixedArray {
540 : public:
541 : // The 0-th field is used by the Blink Wrapper Tracer.
542 : enum Fields {
543 : kWrapperTracerHeader,
544 : kInstance,
545 : kInterpreterHandle,
546 : kInterpretedFunctions,
547 : kFieldCount
548 : };
549 :
550 : static Handle<WasmDebugInfo> New(Handle<WasmInstanceObject>);
551 :
552 : static bool IsDebugInfo(Object*);
553 : static WasmDebugInfo* cast(Object*);
554 :
555 : // Set a breakpoint in the given function at the given byte offset within that
556 : // function. This will redirect all future calls to this function to the
557 : // interpreter and will always pause at the given offset.
558 : static void SetBreakpoint(Handle<WasmDebugInfo>, int func_index, int offset);
559 :
560 : // Make a set of functions always execute in the interpreter without setting
561 : // breakpoints.
562 : static void RedirectToInterpreter(Handle<WasmDebugInfo>,
563 : Vector<int> func_indexes);
564 :
565 : void PrepareStep(StepAction);
566 :
567 : // Execute the specified funtion in the interpreter. Read arguments from
568 : // arg_buffer.
569 : // The frame_pointer will be used to identify the new activation of the
570 : // interpreter for unwinding and frame inspection.
571 : // Returns true if exited regularly, false if a trap occured. In the latter
572 : // case, a pending exception will have been set on the isolate.
573 : bool RunInterpreter(Address frame_pointer, int func_index,
574 : uint8_t* arg_buffer);
575 :
576 : // Get the stack of the wasm interpreter as pairs of <function index, byte
577 : // offset>. The list is ordered bottom-to-top, i.e. caller before callee.
578 : std::vector<std::pair<uint32_t, int>> GetInterpretedStack(
579 : Address frame_pointer);
580 :
581 : std::unique_ptr<wasm::InterpretedFrame> GetInterpretedFrame(
582 : Address frame_pointer, int frame_index);
583 :
584 : // Unwind the interpreted stack belonging to the passed interpreter entry
585 : // frame.
586 : void Unwind(Address frame_pointer);
587 :
588 : // Returns the number of calls / function frames executed in the interpreter.
589 : uint64_t NumInterpretedCalls();
590 :
591 : DECLARE_GETTER(wasm_instance, WasmInstanceObject);
592 :
593 : // Update the memory view of the interpreter after executing GrowMemory in
594 : // compiled code.
595 : void UpdateMemory(JSArrayBuffer* new_memory);
596 :
597 : // Get scope details for a specific interpreted frame.
598 : // This returns a JSArray of length two: One entry for the global scope, one
599 : // for the local scope. Both elements are JSArrays of size
600 : // ScopeIterator::kScopeDetailsSize and layout as described in debug-scopes.h.
601 : // The global scope contains information about globals and the memory.
602 : // The local scope contains information about parameters, locals, and stack
603 : // values.
604 : static Handle<JSArray> GetScopeDetails(Handle<WasmDebugInfo>,
605 : Address frame_pointer,
606 : int frame_index);
607 : };
608 :
609 : class WasmInstanceWrapper : public FixedArray {
610 : public:
611 : static Handle<WasmInstanceWrapper> New(Isolate* isolate,
612 : Handle<WasmInstanceObject> instance);
613 : static WasmInstanceWrapper* cast(Object* fixed_array) {
614 : SLOW_DCHECK(IsWasmInstanceWrapper(fixed_array));
615 : return reinterpret_cast<WasmInstanceWrapper*>(fixed_array);
616 : }
617 : static bool IsWasmInstanceWrapper(Object* obj);
618 : bool has_instance() { return get(kWrapperInstanceObject)->IsWeakCell(); }
619 4230 : Handle<WasmInstanceObject> instance_object() {
620 : Object* obj = get(kWrapperInstanceObject);
621 : DCHECK(obj->IsWeakCell());
622 : WeakCell* cell = WeakCell::cast(obj);
623 : DCHECK(cell->value()->IsJSObject());
624 4230 : return handle(WasmInstanceObject::cast(cell->value()));
625 : }
626 10712 : bool has_next() { return IsWasmInstanceWrapper(get(kNextInstanceWrapper)); }
627 1141 : bool has_previous() {
628 1141 : return IsWasmInstanceWrapper(get(kPreviousInstanceWrapper));
629 : }
630 : void set_next_wrapper(Object* obj) {
631 : DCHECK(IsWasmInstanceWrapper(obj));
632 542 : set(kNextInstanceWrapper, obj);
633 : }
634 : void set_previous_wrapper(Object* obj) {
635 : DCHECK(IsWasmInstanceWrapper(obj));
636 542 : set(kPreviousInstanceWrapper, obj);
637 : }
638 3408 : Handle<WasmInstanceWrapper> next_wrapper() {
639 : Object* obj = get(kNextInstanceWrapper);
640 : DCHECK(IsWasmInstanceWrapper(obj));
641 3408 : return handle(WasmInstanceWrapper::cast(obj));
642 : }
643 269 : Handle<WasmInstanceWrapper> previous_wrapper() {
644 : Object* obj = get(kPreviousInstanceWrapper);
645 : DCHECK(IsWasmInstanceWrapper(obj));
646 269 : return handle(WasmInstanceWrapper::cast(obj));
647 : }
648 207 : void reset_next_wrapper() { set_undefined(kNextInstanceWrapper); }
649 61 : void reset_previous_wrapper() { set_undefined(kPreviousInstanceWrapper); }
650 : void reset() {
651 990 : for (int kID = 0; kID < kWrapperPropertyCount; kID++) set_undefined(kID);
652 : }
653 :
654 : private:
655 : enum {
656 : kWrapperInstanceObject,
657 : kNextInstanceWrapper,
658 : kPreviousInstanceWrapper,
659 : kWrapperPropertyCount
660 : };
661 : };
662 :
663 : #undef DECLARE_ACCESSORS
664 : #undef DECLARE_OPTIONAL_ACCESSORS
665 :
666 : } // namespace internal
667 : } // namespace v8
668 :
669 : #endif // V8_WASM_OBJECTS_H_
|