Line data Source code
1 : // Copyright 2016 the V8 project authors. All rights reserved. Use of
2 : // this source code is governed by a BSD-style license that can be
3 : // found in the LICENSE file.
4 :
5 : #ifndef V8_WASM_WASM_OBJECTS_H_
6 : #define V8_WASM_WASM_OBJECTS_H_
7 :
8 : #include "src/base/bits.h"
9 : #include "src/debug/debug.h"
10 : #include "src/debug/interface-types.h"
11 : #include "src/heap/heap.h"
12 : #include "src/objects.h"
13 : #include "src/objects/script.h"
14 : #include "src/signature.h"
15 : #include "src/wasm/value-type.h"
16 :
17 : // Has to be the last include (doesn't have include guards)
18 : #include "src/objects/object-macros.h"
19 :
20 : namespace v8 {
21 : namespace internal {
22 : namespace wasm {
23 : struct CompilationEnv;
24 : class InterpretedFrame;
25 : struct InterpretedFrameDeleter;
26 : class NativeModule;
27 : class SignatureMap;
28 : class WasmCode;
29 : struct WasmFeatures;
30 : class WasmInterpreter;
31 : struct WasmModule;
32 : class WireBytesRef;
33 : } // namespace wasm
34 :
35 : class BreakPoint;
36 : class JSArrayBuffer;
37 : class SeqOneByteString;
38 : class WasmDebugInfo;
39 : class WasmInstanceObject;
40 : class WasmModuleObject;
41 :
42 : template <class CppType>
43 : class Managed;
44 :
45 : #define DECL_OPTIONAL_ACCESSORS(name, type) \
46 : V8_INLINE bool has_##name(); \
47 : DECL_ACCESSORS(name, type)
48 :
49 : // A helper for an entry in an indirect function table (IFT).
50 : // The underlying storage in the instance is used by generated code to
51 : // call functions indirectly at runtime.
52 : // Each entry has the following fields:
53 : // - object = target instance, if a WASM function, tuple if imported
54 : // - sig_id = signature id of function
55 : // - target = entrypoint to WASM code or import wrapper code
56 : class IndirectFunctionTableEntry {
57 : public:
58 : inline IndirectFunctionTableEntry(Handle<WasmInstanceObject>, int index);
59 :
60 : void clear();
61 : void Set(int sig_id, Handle<WasmInstanceObject> target_instance,
62 : int target_func_index);
63 :
64 : void CopyFrom(const IndirectFunctionTableEntry& that);
65 :
66 : Object object_ref();
67 : int sig_id();
68 : Address target();
69 :
70 : private:
71 : Handle<WasmInstanceObject> const instance_;
72 : int const index_;
73 : };
74 :
75 : // A helper for an entry for an imported function, indexed statically.
76 : // The underlying storage in the instance is used by generated code to
77 : // call imported functions at runtime.
78 : // Each entry is either:
79 : // - WASM to JS, which has fields
80 : // - object = a Tuple2 of the importing instance and the callable
81 : // - target = entrypoint to import wrapper code
82 : // - WASM to WASM, which has fields
83 : // - object = target instance
84 : // - target = entrypoint for the function
85 : class ImportedFunctionEntry {
86 : public:
87 : inline ImportedFunctionEntry(Handle<WasmInstanceObject>, int index);
88 :
89 : // Initialize this entry as a WASM to JS call. This accepts the isolate as a
90 : // parameter, since it must allocate a tuple.
91 : void SetWasmToJs(Isolate*, Handle<JSReceiver> callable,
92 : const wasm::WasmCode* wasm_to_js_wrapper);
93 : // Initialize this entry as a WASM to WASM call.
94 : void SetWasmToWasm(WasmInstanceObject target_instance, Address call_target);
95 :
96 : WasmInstanceObject instance();
97 : JSReceiver callable();
98 : Object object_ref();
99 : Address target();
100 :
101 : private:
102 : Handle<WasmInstanceObject> const instance_;
103 : int const index_;
104 : };
105 :
106 : // Representation of a WebAssembly.Module JavaScript-level object.
107 : class WasmModuleObject : public JSObject {
108 : public:
109 : DECL_CAST(WasmModuleObject)
110 :
111 : DECL_ACCESSORS(managed_native_module, Managed<wasm::NativeModule>)
112 : DECL_ACCESSORS(export_wrappers, FixedArray)
113 : DECL_ACCESSORS(script, Script)
114 : DECL_ACCESSORS(weak_instance_list, WeakArrayList)
115 : DECL_OPTIONAL_ACCESSORS(asm_js_offset_table, ByteArray)
116 : DECL_OPTIONAL_ACCESSORS(breakpoint_infos, FixedArray)
117 : inline wasm::NativeModule* native_module() const;
118 : inline std::shared_ptr<wasm::NativeModule> shared_native_module() const;
119 : inline const wasm::WasmModule* module() const;
120 : inline void reset_breakpoint_infos();
121 :
122 : // Dispatched behavior.
123 : DECL_PRINTER(WasmModuleObject)
124 : DECL_VERIFIER(WasmModuleObject)
125 :
126 : // Layout description.
127 : #define WASM_MODULE_OBJECT_FIELDS(V) \
128 : V(kNativeModuleOffset, kTaggedSize) \
129 : V(kExportWrappersOffset, kTaggedSize) \
130 : V(kScriptOffset, kTaggedSize) \
131 : V(kWeakInstanceListOffset, kTaggedSize) \
132 : V(kAsmJsOffsetTableOffset, kTaggedSize) \
133 : V(kBreakPointInfosOffset, kTaggedSize) \
134 : V(kSize, 0)
135 :
136 : DEFINE_FIELD_OFFSET_CONSTANTS(JSObject::kHeaderSize,
137 : WASM_MODULE_OBJECT_FIELDS)
138 : #undef WASM_MODULE_OBJECT_FIELDS
139 :
140 : // Creates a new {WasmModuleObject} with a new {NativeModule} underneath.
141 : static Handle<WasmModuleObject> New(
142 : Isolate* isolate, const wasm::WasmFeatures& enabled,
143 : std::shared_ptr<const wasm::WasmModule> module,
144 : OwnedVector<const uint8_t> wire_bytes, Handle<Script> script,
145 : Handle<ByteArray> asm_js_offset_table);
146 :
147 : // Creates a new {WasmModuleObject} for an existing {NativeModule} that is
148 : // reference counted and might be shared between multiple Isolates.
149 : static Handle<WasmModuleObject> New(
150 : Isolate* isolate, std::shared_ptr<wasm::NativeModule> native_module,
151 : Handle<Script> script, size_t code_size_estimate);
152 : static Handle<WasmModuleObject> New(
153 : Isolate* isolate, std::shared_ptr<wasm::NativeModule> native_module,
154 : Handle<Script> script, Handle<FixedArray> export_wrappers,
155 : size_t code_size_estimate);
156 :
157 : // Set a breakpoint on the given byte position inside the given module.
158 : // This will affect all live and future instances of the module.
159 : // The passed position might be modified to point to the next breakable
160 : // location inside the same function.
161 : // If it points outside a function, or behind the last breakable location,
162 : // this function returns false and does not set any breakpoint.
163 : static bool SetBreakPoint(Handle<WasmModuleObject>, int* position,
164 : Handle<BreakPoint> break_point);
165 :
166 : // Check whether this module was generated from asm.js source.
167 : inline bool is_asm_js();
168 :
169 : static void AddBreakpoint(Handle<WasmModuleObject>, int position,
170 : Handle<BreakPoint> break_point);
171 :
172 : static void SetBreakpointsOnNewInstance(Handle<WasmModuleObject>,
173 : Handle<WasmInstanceObject>);
174 :
175 : // Get the module name, if set. Returns an empty handle otherwise.
176 : static MaybeHandle<String> GetModuleNameOrNull(Isolate*,
177 : Handle<WasmModuleObject>);
178 :
179 : // Get the function name of the function identified by the given index.
180 : // Returns a null handle if the function is unnamed or the name is not a valid
181 : // UTF-8 string.
182 : static MaybeHandle<String> GetFunctionNameOrNull(Isolate*,
183 : Handle<WasmModuleObject>,
184 : uint32_t func_index);
185 :
186 : // Get the function name of the function identified by the given index.
187 : // Returns "wasm-function[func_index]" if the function is unnamed or the
188 : // name is not a valid UTF-8 string.
189 : static Handle<String> GetFunctionName(Isolate*, Handle<WasmModuleObject>,
190 : uint32_t func_index);
191 :
192 : // Get the raw bytes of the function name of the function identified by the
193 : // given index.
194 : // Meant to be used for debugging or frame printing.
195 : // Does not allocate, hence gc-safe.
196 : Vector<const uint8_t> GetRawFunctionName(uint32_t func_index);
197 :
198 : // Return the byte offset of the function identified by the given index.
199 : // The offset will be relative to the start of the module bytes.
200 : // Returns -1 if the function index is invalid.
201 : int GetFunctionOffset(uint32_t func_index);
202 :
203 : // Returns the function containing the given byte offset.
204 : // Returns -1 if the byte offset is not contained in any function of this
205 : // module.
206 : int GetContainingFunction(uint32_t byte_offset);
207 :
208 : // Translate from byte offset in the module to function number and byte offset
209 : // within that function, encoded as line and column in the position info.
210 : // Returns true if the position is valid inside this module, false otherwise.
211 : bool GetPositionInfo(uint32_t position, Script::PositionInfo* info);
212 :
213 : // Get the source position from a given function index and byte offset,
214 : // for either asm.js or pure WASM modules.
215 : static int GetSourcePosition(Handle<WasmModuleObject>, uint32_t func_index,
216 : uint32_t byte_offset,
217 : bool is_at_number_conversion);
218 :
219 : // Compute the disassembly of a wasm function.
220 : // Returns the disassembly string and a list of <byte_offset, line, column>
221 : // entries, mapping wasm byte offsets to line and column in the disassembly.
222 : // The list is guaranteed to be ordered by the byte_offset.
223 : // Returns an empty string and empty vector if the function index is invalid.
224 : debug::WasmDisassembly DisassembleFunction(int func_index);
225 :
226 : // Extract a portion of the wire bytes as UTF-8 string.
227 : // Returns a null handle if the respective bytes do not form a valid UTF-8
228 : // string.
229 : static MaybeHandle<String> ExtractUtf8StringFromModuleBytes(
230 : Isolate* isolate, Handle<WasmModuleObject>, wasm::WireBytesRef ref);
231 : static MaybeHandle<String> ExtractUtf8StringFromModuleBytes(
232 : Isolate* isolate, Vector<const uint8_t> wire_byte,
233 : wasm::WireBytesRef ref);
234 :
235 : // Get a list of all possible breakpoints within a given range of this module.
236 : bool GetPossibleBreakpoints(const debug::Location& start,
237 : const debug::Location& end,
238 : std::vector<debug::BreakLocation>* locations);
239 :
240 : // Return an empty handle if no breakpoint is hit at that location, or a
241 : // FixedArray with all hit breakpoint objects.
242 : static MaybeHandle<FixedArray> CheckBreakPoints(Isolate*,
243 : Handle<WasmModuleObject>,
244 : int position);
245 :
246 160534 : OBJECT_CONSTRUCTORS(WasmModuleObject, JSObject)
247 : };
248 :
249 : // Representation of a WebAssembly.Table JavaScript-level object.
250 : class WasmTableObject : public JSObject {
251 : public:
252 : DECL_CAST(WasmTableObject)
253 :
254 : DECL_ACCESSORS(functions, FixedArray)
255 : // TODO(titzer): introduce DECL_I64_ACCESSORS macro
256 : DECL_ACCESSORS(maximum_length, Object)
257 : DECL_ACCESSORS(dispatch_tables, FixedArray)
258 :
259 : // Layout description.
260 : #define WASM_TABLE_OBJECT_FIELDS(V) \
261 : V(kFunctionsOffset, kTaggedSize) \
262 : V(kMaximumLengthOffset, kTaggedSize) \
263 : V(kDispatchTablesOffset, kTaggedSize) \
264 : V(kSize, 0)
265 :
266 : DEFINE_FIELD_OFFSET_CONSTANTS(JSObject::kHeaderSize, WASM_TABLE_OBJECT_FIELDS)
267 : #undef WASM_TABLE_OBJECT_FIELDS
268 :
269 : inline uint32_t current_length();
270 : void Grow(Isolate* isolate, uint32_t count);
271 :
272 : static Handle<WasmTableObject> New(Isolate* isolate, uint32_t initial,
273 : uint32_t maximum,
274 : Handle<FixedArray>* js_functions);
275 : static void AddDispatchTable(Isolate* isolate, Handle<WasmTableObject> table,
276 : Handle<WasmInstanceObject> instance,
277 : int table_index);
278 :
279 : static void Set(Isolate* isolate, Handle<WasmTableObject> table,
280 : uint32_t index, Handle<JSFunction> function);
281 :
282 : static void UpdateDispatchTables(Isolate* isolate,
283 : Handle<WasmTableObject> table,
284 : int table_index, wasm::FunctionSig* sig,
285 : Handle<WasmInstanceObject> target_instance,
286 : int target_func_index);
287 :
288 : static void ClearDispatchTables(Isolate* isolate,
289 : Handle<WasmTableObject> table, int index);
290 :
291 : OBJECT_CONSTRUCTORS(WasmTableObject, JSObject)
292 : };
293 :
294 : // Representation of a WebAssembly.Memory JavaScript-level object.
295 : class WasmMemoryObject : public JSObject {
296 : public:
297 : DECL_CAST(WasmMemoryObject)
298 :
299 : DECL_ACCESSORS(array_buffer, JSArrayBuffer)
300 : DECL_INT_ACCESSORS(maximum_pages)
301 : DECL_OPTIONAL_ACCESSORS(instances, WeakArrayList)
302 :
303 : // Layout description.
304 : #define WASM_MEMORY_OBJECT_FIELDS(V) \
305 : V(kArrayBufferOffset, kTaggedSize) \
306 : V(kMaximumPagesOffset, kTaggedSize) \
307 : V(kInstancesOffset, kTaggedSize) \
308 : V(kSize, 0)
309 :
310 : DEFINE_FIELD_OFFSET_CONSTANTS(JSObject::kHeaderSize,
311 : WASM_MEMORY_OBJECT_FIELDS)
312 : #undef WASM_MEMORY_OBJECT_FIELDS
313 :
314 : // Add an instance to the internal (weak) list.
315 : static void AddInstance(Isolate* isolate, Handle<WasmMemoryObject> memory,
316 : Handle<WasmInstanceObject> object);
317 : inline bool has_maximum_pages();
318 :
319 : // Return whether the underlying backing store has guard regions large enough
320 : // to be used with trap handlers.
321 : bool has_full_guard_region(Isolate* isolate);
322 :
323 : V8_EXPORT_PRIVATE static Handle<WasmMemoryObject> New(
324 : Isolate* isolate, MaybeHandle<JSArrayBuffer> buffer, uint32_t maximum);
325 :
326 : static int32_t Grow(Isolate*, Handle<WasmMemoryObject>, uint32_t pages);
327 :
328 70146 : OBJECT_CONSTRUCTORS(WasmMemoryObject, JSObject)
329 : };
330 :
331 : // Representation of a WebAssembly.Global JavaScript-level object.
332 : class WasmGlobalObject : public JSObject {
333 : public:
334 : DECL_CAST(WasmGlobalObject)
335 :
336 : DECL_ACCESSORS(untagged_buffer, JSArrayBuffer)
337 : DECL_ACCESSORS(tagged_buffer, FixedArray)
338 : DECL_INT32_ACCESSORS(offset)
339 : DECL_INT_ACCESSORS(flags)
340 : DECL_PRIMITIVE_ACCESSORS(type, wasm::ValueType)
341 : DECL_BOOLEAN_ACCESSORS(is_mutable)
342 :
343 : #define WASM_GLOBAL_OBJECT_FLAGS_BIT_FIELDS(V, _) \
344 : V(TypeBits, wasm::ValueType, 8, _) \
345 : V(IsMutableBit, bool, 1, _)
346 :
347 : DEFINE_BIT_FIELDS(WASM_GLOBAL_OBJECT_FLAGS_BIT_FIELDS)
348 :
349 : #undef WASM_GLOBAL_OBJECT_FLAGS_BIT_FIELDS
350 :
351 : // Layout description.
352 : #define WASM_GLOBAL_OBJECT_FIELDS(V) \
353 : V(kUntaggedBufferOffset, kTaggedSize) \
354 : V(kTaggedBufferOffset, kTaggedSize) \
355 : V(kOffsetOffset, kTaggedSize) \
356 : V(kFlagsOffset, kTaggedSize) \
357 : V(kSize, 0)
358 :
359 : DEFINE_FIELD_OFFSET_CONSTANTS(JSObject::kHeaderSize,
360 : WASM_GLOBAL_OBJECT_FIELDS)
361 : #undef WASM_GLOBAL_OBJECT_FIELDS
362 :
363 : V8_EXPORT_PRIVATE static MaybeHandle<WasmGlobalObject> New(
364 : Isolate* isolate, MaybeHandle<JSArrayBuffer> maybe_untagged_buffer,
365 : MaybeHandle<FixedArray> maybe_tagged_buffer, wasm::ValueType type,
366 : int32_t offset, bool is_mutable);
367 :
368 : inline int type_size() const;
369 :
370 : inline int32_t GetI32();
371 : inline int64_t GetI64();
372 : inline float GetF32();
373 : inline double GetF64();
374 : inline Handle<Object> GetAnyRef();
375 :
376 : inline void SetI32(int32_t value);
377 : inline void SetI64(int64_t value);
378 : inline void SetF32(float value);
379 : inline void SetF64(double value);
380 : inline void SetAnyRef(Handle<Object> value);
381 :
382 : private:
383 : // This function returns the address of the global's data in the
384 : // JSArrayBuffer. This buffer may be allocated on-heap, in which case it may
385 : // not have a fixed address.
386 : inline Address address() const;
387 :
388 : OBJECT_CONSTRUCTORS(WasmGlobalObject, JSObject)
389 : };
390 :
391 : // Representation of a WebAssembly.Instance JavaScript-level object.
392 : class WasmInstanceObject : public JSObject {
393 : public:
394 : DECL_CAST(WasmInstanceObject)
395 :
396 : DECL_ACCESSORS(module_object, WasmModuleObject)
397 : DECL_ACCESSORS(exports_object, JSObject)
398 : DECL_ACCESSORS(native_context, Context)
399 : DECL_OPTIONAL_ACCESSORS(memory_object, WasmMemoryObject)
400 : DECL_OPTIONAL_ACCESSORS(untagged_globals_buffer, JSArrayBuffer)
401 : DECL_OPTIONAL_ACCESSORS(tagged_globals_buffer, FixedArray)
402 : DECL_OPTIONAL_ACCESSORS(imported_mutable_globals_buffers, FixedArray)
403 : DECL_OPTIONAL_ACCESSORS(debug_info, WasmDebugInfo)
404 : DECL_OPTIONAL_ACCESSORS(table_object, WasmTableObject)
405 : DECL_ACCESSORS(imported_function_refs, FixedArray)
406 : DECL_OPTIONAL_ACCESSORS(indirect_function_table_refs, FixedArray)
407 : DECL_OPTIONAL_ACCESSORS(managed_native_allocations, Foreign)
408 : DECL_OPTIONAL_ACCESSORS(exceptions_table, FixedArray)
409 : DECL_ACCESSORS(undefined_value, Oddball)
410 : DECL_ACCESSORS(null_value, Oddball)
411 : DECL_ACCESSORS(centry_stub, Code)
412 : DECL_PRIMITIVE_ACCESSORS(memory_start, byte*)
413 : DECL_PRIMITIVE_ACCESSORS(memory_size, size_t)
414 : DECL_PRIMITIVE_ACCESSORS(memory_mask, size_t)
415 : DECL_PRIMITIVE_ACCESSORS(isolate_root, Address)
416 : DECL_PRIMITIVE_ACCESSORS(stack_limit_address, Address)
417 : DECL_PRIMITIVE_ACCESSORS(real_stack_limit_address, Address)
418 : DECL_PRIMITIVE_ACCESSORS(imported_function_targets, Address*)
419 : DECL_PRIMITIVE_ACCESSORS(globals_start, byte*)
420 : DECL_PRIMITIVE_ACCESSORS(imported_mutable_globals, Address*)
421 : DECL_PRIMITIVE_ACCESSORS(indirect_function_table_size, uint32_t)
422 : DECL_PRIMITIVE_ACCESSORS(indirect_function_table_sig_ids, uint32_t*)
423 : DECL_PRIMITIVE_ACCESSORS(indirect_function_table_targets, Address*)
424 : DECL_PRIMITIVE_ACCESSORS(jump_table_start, Address)
425 : DECL_PRIMITIVE_ACCESSORS(data_segment_starts, Address*)
426 : DECL_PRIMITIVE_ACCESSORS(data_segment_sizes, uint32_t*)
427 : DECL_PRIMITIVE_ACCESSORS(dropped_data_segments, byte*)
428 : DECL_PRIMITIVE_ACCESSORS(dropped_elem_segments, byte*)
429 :
430 : V8_INLINE void clear_padding();
431 :
432 : // Dispatched behavior.
433 : DECL_PRINTER(WasmInstanceObject)
434 : DECL_VERIFIER(WasmInstanceObject)
435 :
436 : // Layout description.
437 : #define WASM_INSTANCE_OBJECT_FIELDS(V) \
438 : /* Tagged values. */ \
439 : V(kModuleObjectOffset, kTaggedSize) \
440 : V(kExportsObjectOffset, kTaggedSize) \
441 : V(kNativeContextOffset, kTaggedSize) \
442 : V(kMemoryObjectOffset, kTaggedSize) \
443 : V(kUntaggedGlobalsBufferOffset, kTaggedSize) \
444 : V(kTaggedGlobalsBufferOffset, kTaggedSize) \
445 : V(kImportedMutableGlobalsBuffersOffset, kTaggedSize) \
446 : V(kDebugInfoOffset, kTaggedSize) \
447 : V(kTableObjectOffset, kTaggedSize) \
448 : V(kImportedFunctionRefsOffset, kTaggedSize) \
449 : V(kIndirectFunctionTableRefsOffset, kTaggedSize) \
450 : V(kManagedNativeAllocationsOffset, kTaggedSize) \
451 : V(kExceptionsTableOffset, kTaggedSize) \
452 : V(kUndefinedValueOffset, kTaggedSize) \
453 : V(kNullValueOffset, kTaggedSize) \
454 : V(kCEntryStubOffset, kTaggedSize) \
455 : V(kEndOfTaggedFieldsOffset, 0) \
456 : /* Raw data. */ \
457 : V(kIndirectFunctionTableSizeOffset, kUInt32Size) \
458 : /* Optional padding to align system pointer size fields */ \
459 : V(kOptionalPaddingOffset, POINTER_SIZE_PADDING(kOptionalPaddingOffset)) \
460 : V(kFirstSystemPointerFieldOffset, 0) \
461 : V(kMemoryStartOffset, kSystemPointerSize) \
462 : V(kMemorySizeOffset, kSizetSize) \
463 : V(kMemoryMaskOffset, kSizetSize) \
464 : V(kIsolateRootOffset, kSystemPointerSize) \
465 : V(kStackLimitAddressOffset, kSystemPointerSize) \
466 : V(kRealStackLimitAddressOffset, kSystemPointerSize) \
467 : V(kImportedFunctionTargetsOffset, kSystemPointerSize) \
468 : V(kGlobalsStartOffset, kSystemPointerSize) \
469 : V(kImportedMutableGlobalsOffset, kSystemPointerSize) \
470 : V(kIndirectFunctionTableSigIdsOffset, kSystemPointerSize) \
471 : V(kIndirectFunctionTableTargetsOffset, kSystemPointerSize) \
472 : V(kJumpTableStartOffset, kSystemPointerSize) \
473 : V(kDataSegmentStartsOffset, kSystemPointerSize) \
474 : V(kDataSegmentSizesOffset, kSystemPointerSize) \
475 : V(kDroppedDataSegmentsOffset, kSystemPointerSize) \
476 : V(kDroppedElemSegmentsOffset, kSystemPointerSize) \
477 : /* Header size. */ \
478 : V(kSize, 0)
479 :
480 : DEFINE_FIELD_OFFSET_CONSTANTS(JSObject::kHeaderSize,
481 : WASM_INSTANCE_OBJECT_FIELDS)
482 : #undef WASM_INSTANCE_OBJECT_FIELDS
483 :
484 : STATIC_ASSERT(IsAligned(kFirstSystemPointerFieldOffset, kSystemPointerSize));
485 : STATIC_ASSERT(IsAligned(kSize, kTaggedSize));
486 :
487 : V8_EXPORT_PRIVATE const wasm::WasmModule* module();
488 :
489 : static bool EnsureIndirectFunctionTableWithMinimumSize(
490 : Handle<WasmInstanceObject> instance, uint32_t minimum_size);
491 :
492 : bool has_indirect_function_table();
493 :
494 : void SetRawMemory(byte* mem_start, size_t mem_size);
495 :
496 : // Get the debug info associated with the given wasm object.
497 : // If no debug info exists yet, it is created automatically.
498 : static Handle<WasmDebugInfo> GetOrCreateDebugInfo(Handle<WasmInstanceObject>);
499 :
500 : static Handle<WasmInstanceObject> New(Isolate*, Handle<WasmModuleObject>);
501 :
502 : Address GetCallTarget(uint32_t func_index);
503 :
504 : // Copies table entries. Returns {false} if the ranges are out-of-bounds.
505 : static bool CopyTableEntries(Isolate* isolate,
506 : Handle<WasmInstanceObject> instance,
507 : uint32_t table_index, uint32_t dst, uint32_t src,
508 : uint32_t count) V8_WARN_UNUSED_RESULT;
509 :
510 : // Iterates all fields in the object except the untagged fields.
511 : class BodyDescriptor;
512 :
513 110807 : OBJECT_CONSTRUCTORS(WasmInstanceObject, JSObject)
514 :
515 : private:
516 : static void InitDataSegmentArrays(Handle<WasmInstanceObject>,
517 : Handle<WasmModuleObject>);
518 : static void InitElemSegmentArrays(Handle<WasmInstanceObject>,
519 : Handle<WasmModuleObject>);
520 : };
521 :
522 : // Representation of WebAssembly.Exception JavaScript-level object.
523 : class WasmExceptionObject : public JSObject {
524 : public:
525 : DECL_CAST(WasmExceptionObject)
526 :
527 : DECL_ACCESSORS(serialized_signature, PodArray<wasm::ValueType>)
528 : DECL_ACCESSORS(exception_tag, HeapObject)
529 :
530 : // Layout description.
531 : #define WASM_EXCEPTION_OBJECT_FIELDS(V) \
532 : V(kSerializedSignatureOffset, kTaggedSize) \
533 : V(kExceptionTagOffset, kTaggedSize) \
534 : V(kSize, 0)
535 :
536 : DEFINE_FIELD_OFFSET_CONSTANTS(JSObject::kHeaderSize,
537 : WASM_EXCEPTION_OBJECT_FIELDS)
538 : #undef WASM_EXCEPTION_OBJECT_FIELDS
539 :
540 : // Checks whether the given {sig} has the same parameter types as the
541 : // serialized signature stored within this exception object.
542 : bool IsSignatureEqual(const wasm::FunctionSig* sig);
543 :
544 : static Handle<WasmExceptionObject> New(Isolate* isolate,
545 : const wasm::FunctionSig* sig,
546 : Handle<HeapObject> exception_tag);
547 :
548 : OBJECT_CONSTRUCTORS(WasmExceptionObject, JSObject)
549 : };
550 :
551 : // A WASM function that is wrapped and exported to JavaScript.
552 : class WasmExportedFunction : public JSFunction {
553 : public:
554 : WasmInstanceObject instance();
555 : V8_EXPORT_PRIVATE int function_index();
556 :
557 : V8_EXPORT_PRIVATE static bool IsWasmExportedFunction(Object object);
558 :
559 : static Handle<WasmExportedFunction> New(Isolate* isolate,
560 : Handle<WasmInstanceObject> instance,
561 : MaybeHandle<String> maybe_name,
562 : int func_index, int arity,
563 : Handle<Code> export_wrapper);
564 :
565 : Address GetWasmCallTarget();
566 :
567 : wasm::FunctionSig* sig();
568 :
569 : DECL_CAST(WasmExportedFunction)
570 252 : OBJECT_CONSTRUCTORS(WasmExportedFunction, JSFunction)
571 : };
572 :
573 : // Information for a WasmExportedFunction which is referenced as the function
574 : // data of the SharedFunctionInfo underlying the function. For details please
575 : // see the {SharedFunctionInfo::HasWasmExportedFunctionData} predicate.
576 : class WasmExportedFunctionData : public Struct {
577 : public:
578 : DECL_ACCESSORS(wrapper_code, Code);
579 : DECL_ACCESSORS(instance, WasmInstanceObject)
580 : DECL_INT_ACCESSORS(jump_table_offset);
581 : DECL_INT_ACCESSORS(function_index);
582 :
583 : DECL_CAST(WasmExportedFunctionData)
584 :
585 : // Dispatched behavior.
586 : DECL_PRINTER(WasmExportedFunctionData)
587 : DECL_VERIFIER(WasmExportedFunctionData)
588 :
589 : // Layout description.
590 : #define WASM_EXPORTED_FUNCTION_DATA_FIELDS(V) \
591 : V(kWrapperCodeOffset, kTaggedSize) \
592 : V(kInstanceOffset, kTaggedSize) \
593 : V(kJumpTableOffsetOffset, kTaggedSize) /* Smi */ \
594 : V(kFunctionIndexOffset, kTaggedSize) /* Smi */ \
595 : V(kSize, 0)
596 :
597 : DEFINE_FIELD_OFFSET_CONSTANTS(HeapObject::kHeaderSize,
598 : WASM_EXPORTED_FUNCTION_DATA_FIELDS)
599 : #undef WASM_EXPORTED_FUNCTION_DATA_FIELDS
600 :
601 : OBJECT_CONSTRUCTORS(WasmExportedFunctionData, Struct)
602 : };
603 :
604 : class WasmDebugInfo : public Struct {
605 : public:
606 : NEVER_READ_ONLY_SPACE
607 : DECL_ACCESSORS(wasm_instance, WasmInstanceObject)
608 : DECL_ACCESSORS(interpreter_handle, Object); // Foreign or undefined
609 : DECL_ACCESSORS(interpreted_functions, FixedArray);
610 : DECL_OPTIONAL_ACCESSORS(locals_names, FixedArray)
611 : DECL_OPTIONAL_ACCESSORS(c_wasm_entries, FixedArray)
612 : DECL_OPTIONAL_ACCESSORS(c_wasm_entry_map, Managed<wasm::SignatureMap>)
613 :
614 : DECL_CAST(WasmDebugInfo)
615 :
616 : // Dispatched behavior.
617 : DECL_PRINTER(WasmDebugInfo)
618 : DECL_VERIFIER(WasmDebugInfo)
619 :
620 : // Layout description.
621 : #define WASM_DEBUG_INFO_FIELDS(V) \
622 : V(kInstanceOffset, kTaggedSize) \
623 : V(kInterpreterHandleOffset, kTaggedSize) \
624 : V(kInterpretedFunctionsOffset, kTaggedSize) \
625 : V(kLocalsNamesOffset, kTaggedSize) \
626 : V(kCWasmEntriesOffset, kTaggedSize) \
627 : V(kCWasmEntryMapOffset, kTaggedSize) \
628 : V(kSize, 0)
629 :
630 : DEFINE_FIELD_OFFSET_CONSTANTS(HeapObject::kHeaderSize, WASM_DEBUG_INFO_FIELDS)
631 : #undef WASM_DEBUG_INFO_FIELDS
632 :
633 : static Handle<WasmDebugInfo> New(Handle<WasmInstanceObject>);
634 :
635 : // Setup a WasmDebugInfo with an existing WasmInstance struct.
636 : // Returns a pointer to the interpreter instantiated inside this
637 : // WasmDebugInfo.
638 : // Use for testing only.
639 : V8_EXPORT_PRIVATE static wasm::WasmInterpreter* SetupForTesting(
640 : Handle<WasmInstanceObject>);
641 :
642 : // Set a breakpoint in the given function at the given byte offset within that
643 : // function. This will redirect all future calls to this function to the
644 : // interpreter and will always pause at the given offset.
645 : static void SetBreakpoint(Handle<WasmDebugInfo>, int func_index, int offset);
646 :
647 : // Make a set of functions always execute in the interpreter without setting
648 : // breakpoints.
649 : static void RedirectToInterpreter(Handle<WasmDebugInfo>,
650 : Vector<int> func_indexes);
651 :
652 : void PrepareStep(StepAction);
653 :
654 : // Execute the specified function in the interpreter. Read arguments from
655 : // arg_buffer.
656 : // The frame_pointer will be used to identify the new activation of the
657 : // interpreter for unwinding and frame inspection.
658 : // Returns true if exited regularly, false if a trap occurred. In the latter
659 : // case, a pending exception will have been set on the isolate.
660 : static bool RunInterpreter(Isolate* isolate, Handle<WasmDebugInfo>,
661 : Address frame_pointer, int func_index,
662 : Address arg_buffer);
663 :
664 : // Get the stack of the wasm interpreter as pairs of <function index, byte
665 : // offset>. The list is ordered bottom-to-top, i.e. caller before callee.
666 : std::vector<std::pair<uint32_t, int>> GetInterpretedStack(
667 : Address frame_pointer);
668 :
669 : std::unique_ptr<wasm::InterpretedFrame, wasm::InterpretedFrameDeleter>
670 : GetInterpretedFrame(Address frame_pointer, int frame_index);
671 :
672 : // Unwind the interpreted stack belonging to the passed interpreter entry
673 : // frame.
674 : void Unwind(Address frame_pointer);
675 :
676 : // Returns the number of calls / function frames executed in the interpreter.
677 : uint64_t NumInterpretedCalls();
678 :
679 : // Get scope details for a specific interpreted frame.
680 : // This returns a JSArray of length two: One entry for the global scope, one
681 : // for the local scope. Both elements are JSArrays of size
682 : // ScopeIterator::kScopeDetailsSize and layout as described in debug-scopes.h.
683 : // The global scope contains information about globals and the memory.
684 : // The local scope contains information about parameters, locals, and stack
685 : // values.
686 : static Handle<JSObject> GetScopeDetails(Handle<WasmDebugInfo>,
687 : Address frame_pointer,
688 : int frame_index);
689 : static Handle<JSObject> GetGlobalScopeObject(Handle<WasmDebugInfo>,
690 : Address frame_pointer,
691 : int frame_index);
692 : static Handle<JSObject> GetLocalScopeObject(Handle<WasmDebugInfo>,
693 : Address frame_pointer,
694 : int frame_index);
695 :
696 : static Handle<JSFunction> GetCWasmEntry(Handle<WasmDebugInfo>,
697 : wasm::FunctionSig*);
698 :
699 7898 : OBJECT_CONSTRUCTORS(WasmDebugInfo, Struct)
700 : };
701 :
702 : // Tags provide an object identity for each exception defined in a wasm module
703 : // header. They are referenced by the following fields:
704 : // - {WasmExceptionObject::exception_tag} : The tag of the exception object.
705 : // - {WasmInstanceObject::exceptions_table}: List of tags used by an instance.
706 : class WasmExceptionTag : public Struct {
707 : public:
708 : static Handle<WasmExceptionTag> New(Isolate* isolate, int index);
709 :
710 : // Note that this index is only useful for debugging purposes and it is not
711 : // unique across modules. The GC however does not allow objects without at
712 : // least one field, hence this also serves as a padding field for now.
713 : DECL_INT_ACCESSORS(index);
714 :
715 : DECL_CAST(WasmExceptionTag)
716 : DECL_PRINTER(WasmExceptionTag)
717 : DECL_VERIFIER(WasmExceptionTag)
718 :
719 : // Layout description.
720 : #define WASM_EXCEPTION_TAG_FIELDS(V) \
721 : V(kIndexOffset, kTaggedSize) \
722 : /* Total size. */ \
723 : V(kSize, 0)
724 :
725 : DEFINE_FIELD_OFFSET_CONSTANTS(Struct::kHeaderSize, WASM_EXCEPTION_TAG_FIELDS)
726 : #undef WASM_EXCEPTION_TAG_FIELDS
727 :
728 : OBJECT_CONSTRUCTORS(WasmExceptionTag, Struct)
729 : };
730 :
731 : class AsmWasmData : public Struct {
732 : public:
733 : static Handle<AsmWasmData> New(
734 : Isolate* isolate, std::shared_ptr<wasm::NativeModule> native_module,
735 : Handle<FixedArray> export_wrappers, Handle<ByteArray> asm_js_offset_table,
736 : Handle<HeapNumber> uses_bitset);
737 :
738 : DECL_ACCESSORS(managed_native_module, Managed<wasm::NativeModule>)
739 : DECL_ACCESSORS(export_wrappers, FixedArray)
740 : DECL_ACCESSORS(asm_js_offset_table, ByteArray)
741 : DECL_ACCESSORS(uses_bitset, HeapNumber)
742 :
743 : DECL_CAST(AsmWasmData)
744 : DECL_PRINTER(AsmWasmData)
745 : DECL_VERIFIER(AsmWasmData)
746 :
747 : // Layout description.
748 : #define ASM_WASM_DATA_FIELDS(V) \
749 : V(kManagedNativeModuleOffset, kTaggedSize) \
750 : V(kExportWrappersOffset, kTaggedSize) \
751 : V(kAsmJsOffsetTableOffset, kTaggedSize) \
752 : V(kUsesBitsetOffset, kTaggedSize) \
753 : /* Total size. */ \
754 : V(kSize, 0)
755 :
756 : DEFINE_FIELD_OFFSET_CONSTANTS(Struct::kHeaderSize, ASM_WASM_DATA_FIELDS)
757 : #undef ASM_WASM_DATA_FIELDS
758 :
759 : OBJECT_CONSTRUCTORS(AsmWasmData, Struct)
760 : };
761 :
762 : #undef DECL_OPTIONAL_ACCESSORS
763 :
764 : } // namespace internal
765 : } // namespace v8
766 :
767 : #include "src/objects/object-macros-undef.h"
768 :
769 : #endif // V8_WASM_WASM_OBJECTS_H_
|