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