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 #if !V8_ENABLE_WEBASSEMBLY
6 #error This header should only be included if WebAssembly is enabled.
7 #endif  // !V8_ENABLE_WEBASSEMBLY
8 
9 #ifndef V8_WASM_WASM_OBJECTS_H_
10 #define V8_WASM_WASM_OBJECTS_H_
11 
12 #include <memory>
13 
14 #include "src/base/bit-field.h"
15 #include "src/base/bits.h"
16 #include "src/codegen/signature.h"
17 #include "src/debug/debug.h"
18 #include "src/heap/heap.h"
19 #include "src/objects/js-function.h"
20 #include "src/objects/js-objects.h"
21 #include "src/objects/objects.h"
22 #include "src/wasm/struct-types.h"
23 #include "src/wasm/value-type.h"
24 
25 // Has to be the last include (doesn't have include guards)
26 #include "src/objects/object-macros.h"
27 
28 namespace v8 {
29 namespace internal {
30 namespace wasm {
31 class InterpretedFrame;
32 class NativeModule;
33 class WasmCode;
34 struct WasmGlobal;
35 struct WasmModule;
36 struct WasmTag;
37 class WasmValue;
38 class WireBytesRef;
39 }  // namespace wasm
40 
41 class BreakPoint;
42 class JSArrayBuffer;
43 class SeqOneByteString;
44 class WasmCapiFunction;
45 class WasmExceptionTag;
46 class WasmExportedFunction;
47 class WasmExternalFunction;
48 class WasmInstanceObject;
49 class WasmJSFunction;
50 class WasmModuleObject;
51 
52 enum class SharedFlag : uint8_t;
53 
54 template <class CppType>
55 class Managed;
56 
57 #include "torque-generated/src/wasm/wasm-objects-tq.inc"
58 
59 #define DECL_OPTIONAL_ACCESSORS(name, type) \
60   DECL_GETTER(has_##name, bool)             \
61   DECL_ACCESSORS(name, type)
62 
63 // A helper for an entry in an indirect function table (IFT).
64 // The underlying storage in the instance is used by generated code to
65 // call functions indirectly at runtime.
66 // Each entry has the following fields:
67 // - object = target instance, if a Wasm function, tuple if imported
68 // - sig_id = signature id of function
69 // - target = entrypoint to Wasm code or import wrapper code
70 class V8_EXPORT_PRIVATE IndirectFunctionTableEntry {
71  public:
72   inline IndirectFunctionTableEntry(Handle<WasmInstanceObject>, int table_index,
73                                     int entry_index);
74 
75   inline IndirectFunctionTableEntry(Handle<WasmIndirectFunctionTable> table,
76                                     int entry_index);
77 
78   void clear();
79   void Set(int sig_id, Handle<WasmInstanceObject> target_instance,
80            int target_func_index);
81   void Set(int sig_id, Address call_target, Object ref);
82 
83   Object object_ref() const;
84   int sig_id() const;
85   Address target() const;
86 
87  private:
88   Handle<WasmInstanceObject> const instance_;
89   Handle<WasmIndirectFunctionTable> const table_;
90   int const index_;
91 };
92 
93 // A helper for an entry for an imported function, indexed statically.
94 // The underlying storage in the instance is used by generated code to
95 // call imported functions at runtime.
96 // Each entry is either:
97 //   - Wasm to JS, which has fields
98 //      - object = a Tuple2 of the importing instance and the callable
99 //      - target = entrypoint to import wrapper code
100 //   - Wasm to Wasm, which has fields
101 //      - object = target instance
102 //      - target = entrypoint for the function
103 class ImportedFunctionEntry {
104  public:
105   inline ImportedFunctionEntry(Handle<WasmInstanceObject>, int index);
106 
107   // Initialize this entry as a Wasm to JS call. This accepts the isolate as a
108   // parameter, since it must allocate a tuple.
109   V8_EXPORT_PRIVATE void SetWasmToJs(Isolate*, Handle<JSReceiver> callable,
110                                      const wasm::WasmCode* wasm_to_js_wrapper);
111   // Initialize this entry as a Wasm to Wasm call.
112   void SetWasmToWasm(WasmInstanceObject target_instance, Address call_target);
113 
114   WasmInstanceObject instance();
115   JSReceiver callable();
116   Object maybe_callable();
117   Object object_ref();
118   Address target();
119 
120  private:
121   Handle<WasmInstanceObject> const instance_;
122   int const index_;
123 };
124 
125 enum InternalizeString : bool { kInternalize = true, kNoInternalize = false };
126 
127 // Representation of a WebAssembly.Module JavaScript-level object.
128 class WasmModuleObject
129     : public TorqueGeneratedWasmModuleObject<WasmModuleObject, JSObject> {
130  public:
131   inline wasm::NativeModule* native_module() const;
132   inline const std::shared_ptr<wasm::NativeModule>& shared_native_module()
133       const;
134   inline const wasm::WasmModule* module() const;
135 
136   // Dispatched behavior.
137   DECL_PRINTER(WasmModuleObject)
138 
139   // Creates a new {WasmModuleObject} for an existing {NativeModule} that is
140   // reference counted and might be shared between multiple Isolates.
141   V8_EXPORT_PRIVATE static Handle<WasmModuleObject> New(
142       Isolate* isolate, std::shared_ptr<wasm::NativeModule> native_module,
143       Handle<Script> script);
144   V8_EXPORT_PRIVATE static Handle<WasmModuleObject> New(
145       Isolate* isolate, std::shared_ptr<wasm::NativeModule> native_module,
146       Handle<Script> script, Handle<FixedArray> export_wrappers);
147 
148   // Check whether this module was generated from asm.js source.
149   inline bool is_asm_js();
150 
151   // Get the module name, if set. Returns an empty handle otherwise.
152   static MaybeHandle<String> GetModuleNameOrNull(Isolate*,
153                                                  Handle<WasmModuleObject>);
154 
155   // Get the function name of the function identified by the given index.
156   // Returns a null handle if the function is unnamed or the name is not a valid
157   // UTF-8 string.
158   static MaybeHandle<String> GetFunctionNameOrNull(Isolate*,
159                                                    Handle<WasmModuleObject>,
160                                                    uint32_t func_index);
161 
162   // Get the raw bytes of the function name of the function identified by the
163   // given index.
164   // Meant to be used for debugging or frame printing.
165   // Does not allocate, hence gc-safe.
166   base::Vector<const uint8_t> GetRawFunctionName(int func_index);
167 
168   // Extract a portion of the wire bytes as UTF-8 string, optionally
169   // internalized. (Prefer to internalize early if the string will be used for a
170   // property lookup anyway.)
171   static Handle<String> ExtractUtf8StringFromModuleBytes(
172       Isolate*, Handle<WasmModuleObject>, wasm::WireBytesRef,
173       InternalizeString);
174   static Handle<String> ExtractUtf8StringFromModuleBytes(
175       Isolate*, base::Vector<const uint8_t> wire_byte, wasm::WireBytesRef,
176       InternalizeString);
177 
178   TQ_OBJECT_CONSTRUCTORS(WasmModuleObject)
179 };
180 
181 // Representation of a WebAssembly.Table JavaScript-level object.
182 class WasmTableObject
183     : public TorqueGeneratedWasmTableObject<WasmTableObject, JSObject> {
184  public:
185   inline wasm::ValueType type();
186 
187   V8_EXPORT_PRIVATE static int Grow(Isolate* isolate,
188                                     Handle<WasmTableObject> table,
189                                     uint32_t count, Handle<Object> init_value);
190 
191   V8_EXPORT_PRIVATE static Handle<WasmTableObject> New(
192       Isolate* isolate, Handle<WasmInstanceObject> instance,
193       wasm::ValueType type, uint32_t initial, bool has_maximum,
194       uint32_t maximum, Handle<FixedArray>* entries,
195       Handle<Object> initial_value);
196 
197   V8_EXPORT_PRIVATE static void AddDispatchTable(
198       Isolate* isolate, Handle<WasmTableObject> table,
199       Handle<WasmInstanceObject> instance, int table_index);
200 
201   static bool IsInBounds(Isolate* isolate, Handle<WasmTableObject> table,
202                          uint32_t entry_index);
203 
204   static bool IsValidElement(Isolate* isolate, Handle<WasmTableObject> table,
205                              Handle<Object> entry);
206 
207   V8_EXPORT_PRIVATE static void Set(Isolate* isolate,
208                                     Handle<WasmTableObject> table,
209                                     uint32_t index, Handle<Object> entry);
210 
211   V8_EXPORT_PRIVATE static Handle<Object> Get(Isolate* isolate,
212                                               Handle<WasmTableObject> table,
213                                               uint32_t index);
214 
215   V8_EXPORT_PRIVATE static void Fill(Isolate* isolate,
216                                      Handle<WasmTableObject> table,
217                                      uint32_t start, Handle<Object> entry,
218                                      uint32_t count);
219 
220   // TODO(wasm): Unify these three methods into one.
221   static void UpdateDispatchTables(Isolate* isolate,
222                                    Handle<WasmTableObject> table,
223                                    int entry_index,
224                                    const wasm::FunctionSig* sig,
225                                    Handle<WasmInstanceObject> target_instance,
226                                    int target_func_index);
227   static void UpdateDispatchTables(Isolate* isolate,
228                                    Handle<WasmTableObject> table,
229                                    int entry_index,
230                                    Handle<WasmJSFunction> function);
231   static void UpdateDispatchTables(Isolate* isolate,
232                                    Handle<WasmTableObject> table,
233                                    int entry_index,
234                                    Handle<WasmCapiFunction> capi_function);
235 
236   static void ClearDispatchTables(Isolate* isolate,
237                                   Handle<WasmTableObject> table, int index);
238 
239   V8_EXPORT_PRIVATE static void SetFunctionTablePlaceholder(
240       Isolate* isolate, Handle<WasmTableObject> table, int entry_index,
241       Handle<WasmInstanceObject> instance, int func_index);
242 
243   // This function reads the content of a function table entry and returns it
244   // through the out parameters {is_valid}, {is_null}, {instance},
245   // {function_index}, and {maybe_js_function}.
246   static void GetFunctionTableEntry(
247       Isolate* isolate, const wasm::WasmModule* module,
248       Handle<WasmTableObject> table, int entry_index, bool* is_valid,
249       bool* is_null, MaybeHandle<WasmInstanceObject>* instance,
250       int* function_index, MaybeHandle<WasmJSFunction>* maybe_js_function);
251 
252  private:
253   static void SetFunctionTableEntry(Isolate* isolate,
254                                     Handle<WasmTableObject> table,
255                                     Handle<FixedArray> entries, int entry_index,
256                                     Handle<Object> entry);
257 
258   TQ_OBJECT_CONSTRUCTORS(WasmTableObject)
259 };
260 
261 // Representation of a WebAssembly.Memory JavaScript-level object.
262 class WasmMemoryObject
263     : public TorqueGeneratedWasmMemoryObject<WasmMemoryObject, JSObject> {
264  public:
265   DECL_OPTIONAL_ACCESSORS(instances, WeakArrayList)
266 
267   // Add an instance to the internal (weak) list.
268   V8_EXPORT_PRIVATE static void AddInstance(Isolate* isolate,
269                                             Handle<WasmMemoryObject> memory,
270                                             Handle<WasmInstanceObject> object);
271   inline bool has_maximum_pages();
272 
273   V8_EXPORT_PRIVATE static Handle<WasmMemoryObject> New(
274       Isolate* isolate, MaybeHandle<JSArrayBuffer> buffer, int maximum);
275 
276   V8_EXPORT_PRIVATE static MaybeHandle<WasmMemoryObject> New(Isolate* isolate,
277                                                              int initial,
278                                                              int maximum,
279                                                              SharedFlag shared);
280 
281   static constexpr int kNoMaximum = -1;
282 
283   void update_instances(Isolate* isolate, Handle<JSArrayBuffer> buffer);
284 
285   V8_EXPORT_PRIVATE static int32_t Grow(Isolate*, Handle<WasmMemoryObject>,
286                                         uint32_t pages);
287 
288   TQ_OBJECT_CONSTRUCTORS(WasmMemoryObject)
289 };
290 
291 // Representation of a WebAssembly.Global JavaScript-level object.
292 class WasmGlobalObject
293     : public TorqueGeneratedWasmGlobalObject<WasmGlobalObject, JSObject> {
294  public:
295   DECL_ACCESSORS(untagged_buffer, JSArrayBuffer)
296   DECL_ACCESSORS(tagged_buffer, FixedArray)
297   DECL_PRIMITIVE_ACCESSORS(type, wasm::ValueType)
298 
299   // Dispatched behavior.
300   DECL_PRINTER(WasmGlobalObject)
301 
302   V8_EXPORT_PRIVATE static MaybeHandle<WasmGlobalObject> New(
303       Isolate* isolate, Handle<WasmInstanceObject> instance,
304       MaybeHandle<JSArrayBuffer> maybe_untagged_buffer,
305       MaybeHandle<FixedArray> maybe_tagged_buffer, wasm::ValueType type,
306       int32_t offset, bool is_mutable);
307 
308   inline int type_size() const;
309 
310   inline int32_t GetI32();
311   inline int64_t GetI64();
312   inline float GetF32();
313   inline double GetF64();
314   inline Handle<Object> GetRef();
315 
316   inline void SetI32(int32_t value);
317   inline void SetI64(int64_t value);
318   inline void SetF32(float value);
319   inline void SetF64(double value);
320   inline void SetExternRef(Handle<Object> value);
321   inline bool SetFuncRef(Isolate* isolate, Handle<Object> value);
322 
323  private:
324   // This function returns the address of the global's data in the
325   // JSArrayBuffer. This buffer may be allocated on-heap, in which case it may
326   // not have a fixed address.
327   inline Address address() const;
328 
329   TQ_OBJECT_CONSTRUCTORS(WasmGlobalObject)
330 };
331 
332 // Representation of a WebAssembly.Instance JavaScript-level object.
333 class V8_EXPORT_PRIVATE WasmInstanceObject : public JSObject {
334  public:
335   DECL_CAST(WasmInstanceObject)
336 
337   DECL_ACCESSORS(module_object, WasmModuleObject)
338   DECL_ACCESSORS(exports_object, JSObject)
339   DECL_ACCESSORS(native_context, Context)
340   DECL_OPTIONAL_ACCESSORS(memory_object, WasmMemoryObject)
341   DECL_OPTIONAL_ACCESSORS(untagged_globals_buffer, JSArrayBuffer)
342   DECL_OPTIONAL_ACCESSORS(tagged_globals_buffer, FixedArray)
343   DECL_OPTIONAL_ACCESSORS(imported_mutable_globals_buffers, FixedArray)
344   DECL_OPTIONAL_ACCESSORS(tables, FixedArray)
345   DECL_OPTIONAL_ACCESSORS(indirect_function_tables, FixedArray)
346   DECL_ACCESSORS(imported_function_refs, FixedArray)
347   DECL_OPTIONAL_ACCESSORS(indirect_function_table_refs, FixedArray)
348   DECL_OPTIONAL_ACCESSORS(managed_native_allocations, Foreign)
349   DECL_OPTIONAL_ACCESSORS(tags_table, FixedArray)
350   DECL_OPTIONAL_ACCESSORS(wasm_external_functions, FixedArray)
351   DECL_ACCESSORS(managed_object_maps, FixedArray)
352   DECL_PRIMITIVE_ACCESSORS(memory_start, byte*)
353   DECL_PRIMITIVE_ACCESSORS(memory_size, size_t)
354   DECL_PRIMITIVE_ACCESSORS(isolate_root, Address)
355   DECL_PRIMITIVE_ACCESSORS(stack_limit_address, Address)
356   DECL_PRIMITIVE_ACCESSORS(real_stack_limit_address, Address)
357   DECL_PRIMITIVE_ACCESSORS(new_allocation_limit_address, Address*)
358   DECL_PRIMITIVE_ACCESSORS(new_allocation_top_address, Address*)
359   DECL_PRIMITIVE_ACCESSORS(old_allocation_limit_address, Address*)
360   DECL_PRIMITIVE_ACCESSORS(old_allocation_top_address, Address*)
361   DECL_PRIMITIVE_ACCESSORS(imported_function_targets, Address*)
362   DECL_PRIMITIVE_ACCESSORS(globals_start, byte*)
363   DECL_PRIMITIVE_ACCESSORS(imported_mutable_globals, Address*)
364   DECL_PRIMITIVE_ACCESSORS(indirect_function_table_size, uint32_t)
365   DECL_PRIMITIVE_ACCESSORS(indirect_function_table_sig_ids, uint32_t*)
366   DECL_PRIMITIVE_ACCESSORS(indirect_function_table_targets, Address*)
367   DECL_PRIMITIVE_ACCESSORS(jump_table_start, Address)
368   DECL_PRIMITIVE_ACCESSORS(data_segment_starts, Address*)
369   DECL_PRIMITIVE_ACCESSORS(data_segment_sizes, uint32_t*)
370   DECL_PRIMITIVE_ACCESSORS(dropped_elem_segments, byte*)
371   DECL_PRIMITIVE_ACCESSORS(hook_on_function_call_address, Address)
372   DECL_PRIMITIVE_ACCESSORS(num_liftoff_function_calls_array, uint32_t*)
373   DECL_PRIMITIVE_ACCESSORS(break_on_entry, uint8_t)
374 
375   // Clear uninitialized padding space. This ensures that the snapshot content
376   // is deterministic. Depending on the V8 build mode there could be no padding.
377   V8_INLINE void clear_padding();
378 
379   // Dispatched behavior.
380   DECL_PRINTER(WasmInstanceObject)
381   DECL_VERIFIER(WasmInstanceObject)
382 
383 // Layout description.
384 #define WASM_INSTANCE_OBJECT_FIELDS(V)                                    \
385   /* Often-accessed fields go first to minimize generated code size. */   \
386   /* Less than system pointer sized fields come first. */                 \
387   V(kImportedFunctionRefsOffset, kTaggedSize)                             \
388   V(kIndirectFunctionTableRefsOffset, kTaggedSize)                        \
389   V(kIndirectFunctionTableSizeOffset, kUInt32Size)                        \
390   /* Optional padding to align system pointer size fields */              \
391   V(kOptionalPaddingOffset, POINTER_SIZE_PADDING(kOptionalPaddingOffset)) \
392   V(kMemoryStartOffset, kSystemPointerSize)                               \
393   V(kMemorySizeOffset, kSizetSize)                                        \
394   V(kStackLimitAddressOffset, kSystemPointerSize)                         \
395   V(kImportedFunctionTargetsOffset, kSystemPointerSize)                   \
396   V(kIndirectFunctionTableTargetsOffset, kSystemPointerSize)              \
397   V(kIndirectFunctionTableSigIdsOffset, kSystemPointerSize)               \
398   V(kGlobalsStartOffset, kSystemPointerSize)                              \
399   V(kImportedMutableGlobalsOffset, kSystemPointerSize)                    \
400   V(kIsolateRootOffset, kSystemPointerSize)                               \
401   V(kJumpTableStartOffset, kSystemPointerSize)                            \
402   /* End of often-accessed fields. */                                     \
403   /* Continue with system pointer size fields to maintain alignment. */   \
404   V(kNewAllocationLimitAddressOffset, kSystemPointerSize)                 \
405   V(kNewAllocationTopAddressOffset, kSystemPointerSize)                   \
406   V(kOldAllocationLimitAddressOffset, kSystemPointerSize)                 \
407   V(kOldAllocationTopAddressOffset, kSystemPointerSize)                   \
408   V(kRealStackLimitAddressOffset, kSystemPointerSize)                     \
409   V(kDataSegmentStartsOffset, kSystemPointerSize)                         \
410   V(kDataSegmentSizesOffset, kSystemPointerSize)                          \
411   V(kDroppedElemSegmentsOffset, kSystemPointerSize)                       \
412   V(kHookOnFunctionCallAddressOffset, kSystemPointerSize)                 \
413   V(kNumLiftoffFunctionCallsArrayOffset, kSystemPointerSize)              \
414   /* Less than system pointer size aligned fields are below. */           \
415   V(kModuleObjectOffset, kTaggedSize)                                     \
416   V(kExportsObjectOffset, kTaggedSize)                                    \
417   V(kNativeContextOffset, kTaggedSize)                                    \
418   V(kMemoryObjectOffset, kTaggedSize)                                     \
419   V(kUntaggedGlobalsBufferOffset, kTaggedSize)                            \
420   V(kTaggedGlobalsBufferOffset, kTaggedSize)                              \
421   V(kImportedMutableGlobalsBuffersOffset, kTaggedSize)                    \
422   V(kTablesOffset, kTaggedSize)                                           \
423   V(kIndirectFunctionTablesOffset, kTaggedSize)                           \
424   V(kManagedNativeAllocationsOffset, kTaggedSize)                         \
425   V(kTagsTableOffset, kTaggedSize)                                        \
426   V(kWasmExternalFunctionsOffset, kTaggedSize)                            \
427   V(kManagedObjectMapsOffset, kTaggedSize)                                \
428   V(kBreakOnEntryOffset, kUInt8Size)                                      \
429   /* More padding to make the header pointer-size aligned */              \
430   V(kHeaderPaddingOffset, POINTER_SIZE_PADDING(kHeaderPaddingOffset))     \
431   V(kHeaderSize, 0)
432 
433   DEFINE_FIELD_OFFSET_CONSTANTS(JSObject::kHeaderSize,
434                                 WASM_INSTANCE_OBJECT_FIELDS)
435   STATIC_ASSERT(IsAligned(kHeaderSize, kTaggedSize));
436   // TODO(ishell, v8:8875): When pointer compression is enabled 8-byte size
437   // fields (external pointers, doubles and BigInt data) are only kTaggedSize
438   // aligned so checking for alignments of fields bigger than kTaggedSize
439   // doesn't make sense until v8:8875 is fixed.
440 #define ASSERT_FIELD_ALIGNED(offset, size)                                 \
441   STATIC_ASSERT(size == 0 || IsAligned(offset, size) ||                    \
442                 (COMPRESS_POINTERS_BOOL && (size == kSystemPointerSize) && \
443                  IsAligned(offset, kTaggedSize)));
444   WASM_INSTANCE_OBJECT_FIELDS(ASSERT_FIELD_ALIGNED)
445 #undef ASSERT_FIELD_ALIGNED
446 #undef WASM_INSTANCE_OBJECT_FIELDS
447 
448   static constexpr uint16_t kTaggedFieldOffsets[] = {
449       kImportedFunctionRefsOffset,
450       kIndirectFunctionTableRefsOffset,
451       kModuleObjectOffset,
452       kExportsObjectOffset,
453       kNativeContextOffset,
454       kMemoryObjectOffset,
455       kUntaggedGlobalsBufferOffset,
456       kTaggedGlobalsBufferOffset,
457       kImportedMutableGlobalsBuffersOffset,
458       kTablesOffset,
459       kIndirectFunctionTablesOffset,
460       kManagedNativeAllocationsOffset,
461       kTagsTableOffset,
462       kWasmExternalFunctionsOffset,
463       kManagedObjectMapsOffset};
464 
465   const wasm::WasmModule* module();
466 
467   static bool EnsureIndirectFunctionTableWithMinimumSize(
468       Handle<WasmInstanceObject> instance, int table_index,
469       uint32_t minimum_size);
470 
471   void SetRawMemory(byte* mem_start, size_t mem_size);
472 
473   static Handle<WasmInstanceObject> New(Isolate*, Handle<WasmModuleObject>);
474 
475   Address GetCallTarget(uint32_t func_index);
476 
477   static int IndirectFunctionTableSize(Isolate* isolate,
478                                        Handle<WasmInstanceObject> instance,
479                                        uint32_t table_index);
480 
481   // Copies table entries. Returns {false} if the ranges are out-of-bounds.
482   static bool CopyTableEntries(Isolate* isolate,
483                                Handle<WasmInstanceObject> instance,
484                                uint32_t table_dst_index,
485                                uint32_t table_src_index, uint32_t dst,
486                                uint32_t src,
487                                uint32_t count) V8_WARN_UNUSED_RESULT;
488 
489   // Copy table entries from an element segment. Returns {false} if the ranges
490   // are out-of-bounds.
491   static bool InitTableEntries(Isolate* isolate,
492                                Handle<WasmInstanceObject> instance,
493                                uint32_t table_index, uint32_t segment_index,
494                                uint32_t dst, uint32_t src,
495                                uint32_t count) V8_WARN_UNUSED_RESULT;
496 
497   // Iterates all fields in the object except the untagged fields.
498   class BodyDescriptor;
499 
500   static MaybeHandle<WasmExternalFunction> GetWasmExternalFunction(
501       Isolate* isolate, Handle<WasmInstanceObject> instance, int index);
502 
503   // Acquires the {WasmExternalFunction} for a given {function_index} from the
504   // cache of the given {instance}, or creates a new {WasmExportedFunction} if
505   // it does not exist yet. The new {WasmExportedFunction} is added to the
506   // cache of the {instance} immediately.
507   static Handle<WasmExternalFunction> GetOrCreateWasmExternalFunction(
508       Isolate* isolate, Handle<WasmInstanceObject> instance,
509       int function_index);
510 
511   static void SetWasmExternalFunction(Isolate* isolate,
512                                       Handle<WasmInstanceObject> instance,
513                                       int index,
514                                       Handle<WasmExternalFunction> val);
515 
516   // Imports a constructed {WasmJSFunction} into the indirect function table of
517   // this instance. Note that this might trigger wrapper compilation, since a
518   // {WasmJSFunction} is instance-independent and just wraps a JS callable.
519   static void ImportWasmJSFunctionIntoTable(Isolate* isolate,
520                                             Handle<WasmInstanceObject> instance,
521                                             int table_index, int entry_index,
522                                             Handle<WasmJSFunction> js_function);
523 
524   // Get a raw pointer to the location where the given global is stored.
525   // {global} must not be a reference type.
526   static uint8_t* GetGlobalStorage(Handle<WasmInstanceObject>,
527                                    const wasm::WasmGlobal&);
528 
529   // Get the FixedArray and the index in that FixedArray for the given global,
530   // which must be a reference type.
531   static std::pair<Handle<FixedArray>, uint32_t> GetGlobalBufferAndIndex(
532       Handle<WasmInstanceObject>, const wasm::WasmGlobal&);
533 
534   // Get the value of a global in the given instance.
535   static wasm::WasmValue GetGlobalValue(Handle<WasmInstanceObject>,
536                                         const wasm::WasmGlobal&);
537 
538   OBJECT_CONSTRUCTORS(WasmInstanceObject, JSObject);
539 
540  private:
541   static void InitDataSegmentArrays(Handle<WasmInstanceObject>,
542                                     Handle<WasmModuleObject>);
543   static void InitElemSegmentArrays(Handle<WasmInstanceObject>,
544                                     Handle<WasmModuleObject>);
545 };
546 
547 // Representation of WebAssembly.Exception JavaScript-level object.
548 class WasmTagObject
549     : public TorqueGeneratedWasmTagObject<WasmTagObject, JSObject> {
550  public:
551   // Checks whether the given {sig} has the same parameter types as the
552   // serialized signature stored within this tag object.
553   bool MatchesSignature(const wasm::FunctionSig* sig);
554 
555   static Handle<WasmTagObject> New(Isolate* isolate,
556                                    const wasm::FunctionSig* sig,
557                                    Handle<HeapObject> tag);
558 
559   TQ_OBJECT_CONSTRUCTORS(WasmTagObject)
560 };
561 
562 // A Wasm exception that has been thrown out of Wasm code.
563 class V8_EXPORT_PRIVATE WasmExceptionPackage : public JSObject {
564  public:
565   static Handle<WasmExceptionPackage> New(
566       Isolate* isolate, Handle<WasmExceptionTag> exception_tag,
567       int encoded_size);
568 
569   static Handle<WasmExceptionPackage> New(
570       Isolate* isolate, Handle<WasmExceptionTag> exception_tag,
571       Handle<FixedArray> values);
572 
573   // The below getters return {undefined} in case the given exception package
574   // does not carry the requested values (i.e. is of a different type).
575   static Handle<Object> GetExceptionTag(
576       Isolate* isolate, Handle<WasmExceptionPackage> exception_package);
577   static Handle<Object> GetExceptionValues(
578       Isolate* isolate, Handle<WasmExceptionPackage> exception_package);
579 
580   // Determines the size of the array holding all encoded exception values.
581   static uint32_t GetEncodedSize(const wasm::WasmTag* tag);
582 
583   DECL_CAST(WasmExceptionPackage)
584   OBJECT_CONSTRUCTORS(WasmExceptionPackage, JSObject);
585 };
586 
587 void V8_EXPORT_PRIVATE EncodeI32ExceptionValue(
588     Handle<FixedArray> encoded_values, uint32_t* encoded_index, uint32_t value);
589 
590 void V8_EXPORT_PRIVATE EncodeI64ExceptionValue(
591     Handle<FixedArray> encoded_values, uint32_t* encoded_index, uint64_t value);
592 
593 void V8_EXPORT_PRIVATE
594 DecodeI32ExceptionValue(Handle<FixedArray> encoded_values,
595                         uint32_t* encoded_index, uint32_t* value);
596 
597 void V8_EXPORT_PRIVATE
598 DecodeI64ExceptionValue(Handle<FixedArray> encoded_values,
599                         uint32_t* encoded_index, uint64_t* value);
600 
601 // A Wasm function that is wrapped and exported to JavaScript.
602 // Representation of WebAssembly.Function JavaScript-level object.
603 class WasmExportedFunction : public JSFunction {
604  public:
605   WasmInstanceObject instance();
606   V8_EXPORT_PRIVATE int function_index();
607 
608   V8_EXPORT_PRIVATE static bool IsWasmExportedFunction(Object object);
609 
610   V8_EXPORT_PRIVATE static Handle<WasmExportedFunction> New(
611       Isolate* isolate, Handle<WasmInstanceObject> instance, int func_index,
612       int arity, Handle<Code> export_wrapper);
613 
614   Address GetWasmCallTarget();
615 
616   V8_EXPORT_PRIVATE const wasm::FunctionSig* sig();
617 
618   bool MatchesSignature(const wasm::WasmModule* other_module,
619                         const wasm::FunctionSig* other_sig);
620 
621   // Return a null-terminated string with the debug name in the form
622   // 'js-to-wasm:<sig>'.
623   static std::unique_ptr<char[]> GetDebugName(const wasm::FunctionSig* sig);
624 
625   DECL_CAST(WasmExportedFunction)
626   OBJECT_CONSTRUCTORS(WasmExportedFunction, JSFunction);
627 };
628 
629 // A Wasm function that was created by wrapping a JavaScript callable.
630 // Representation of WebAssembly.Function JavaScript-level object.
631 class WasmJSFunction : public JSFunction {
632  public:
633   static bool IsWasmJSFunction(Object object);
634 
635   static Handle<WasmJSFunction> New(Isolate* isolate,
636                                     const wasm::FunctionSig* sig,
637                                     Handle<JSReceiver> callable);
638 
639   JSReceiver GetCallable() const;
640   // Deserializes the signature of this function using the provided zone. Note
641   // that lifetime of the signature is hence directly coupled to the zone.
642   const wasm::FunctionSig* GetSignature(Zone* zone);
643   bool MatchesSignature(const wasm::FunctionSig* sig);
644 
645   DECL_CAST(WasmJSFunction)
646   OBJECT_CONSTRUCTORS(WasmJSFunction, JSFunction);
647 };
648 
649 // An external function exposed to Wasm via the C/C++ API.
650 class WasmCapiFunction : public JSFunction {
651  public:
652   static bool IsWasmCapiFunction(Object object);
653 
654   static Handle<WasmCapiFunction> New(
655       Isolate* isolate, Address call_target, Handle<Foreign> embedder_data,
656       Handle<PodArray<wasm::ValueType>> serialized_signature);
657 
658   PodArray<wasm::ValueType> GetSerializedSignature() const;
659   // Checks whether the given {sig} has the same parameter types as the
660   // serialized signature stored within this C-API function object.
661   bool MatchesSignature(const wasm::FunctionSig* sig) const;
662 
663   DECL_CAST(WasmCapiFunction)
664   OBJECT_CONSTRUCTORS(WasmCapiFunction, JSFunction);
665 };
666 
667 // Any external function that can be imported/exported in modules. This abstract
668 // class just dispatches to the following concrete classes:
669 //  - {WasmExportedFunction}: A proper Wasm function exported from a module.
670 //  - {WasmJSFunction}: A function constructed via WebAssembly.Function in JS.
671 // // TODO(wasm): Potentially {WasmCapiFunction} will be added here as well.
672 class WasmExternalFunction : public JSFunction {
673  public:
674   static bool IsWasmExternalFunction(Object object);
675 
676   DECL_CAST(WasmExternalFunction)
677   OBJECT_CONSTRUCTORS(WasmExternalFunction, JSFunction);
678 };
679 
680 class WasmIndirectFunctionTable
681     : public TorqueGeneratedWasmIndirectFunctionTable<WasmIndirectFunctionTable,
682                                                       Struct> {
683  public:
684   DECL_PRIMITIVE_ACCESSORS(sig_ids, uint32_t*)
685   DECL_PRIMITIVE_ACCESSORS(targets, Address*)
686   DECL_OPTIONAL_ACCESSORS(managed_native_allocations, Foreign)
687 
688   V8_EXPORT_PRIVATE static Handle<WasmIndirectFunctionTable> New(
689       Isolate* isolate, uint32_t size);
690   static void Resize(Isolate* isolate, Handle<WasmIndirectFunctionTable> table,
691                      uint32_t new_size);
692 
693   DECL_PRINTER(WasmIndirectFunctionTable)
694 
695   STATIC_ASSERT(kStartOfStrongFieldsOffset == kManagedNativeAllocationsOffset);
696   using BodyDescriptor = FlexibleBodyDescriptor<kStartOfStrongFieldsOffset>;
697 
698   TQ_OBJECT_CONSTRUCTORS(WasmIndirectFunctionTable)
699 };
700 
701 class WasmFunctionData
702     : public TorqueGeneratedWasmFunctionData<WasmFunctionData, Foreign> {
703  public:
704   DECL_ACCESSORS(ref, Object)
705   DECL_ACCESSORS(wrapper_code, Code)
706 
707   DECL_PRINTER(WasmFunctionData)
708 
709   TQ_OBJECT_CONSTRUCTORS(WasmFunctionData)
710 };
711 
712 // Information for a WasmExportedFunction which is referenced as the function
713 // data of the SharedFunctionInfo underlying the function. For details please
714 // see the {SharedFunctionInfo::HasWasmExportedFunctionData} predicate.
715 class WasmExportedFunctionData
716     : public TorqueGeneratedWasmExportedFunctionData<WasmExportedFunctionData,
717                                                      WasmFunctionData> {
718  public:
719   inline wasm::FunctionSig* sig() const;
720 
721   // Dispatched behavior.
722   DECL_PRINTER(WasmExportedFunctionData)
723   DECL_VERIFIER(WasmExportedFunctionData)
724 
725   class BodyDescriptor;
726 
727   TQ_OBJECT_CONSTRUCTORS(WasmExportedFunctionData)
728 };
729 
730 // Information for a WasmJSFunction which is referenced as the function data of
731 // the SharedFunctionInfo underlying the function. For details please see the
732 // {SharedFunctionInfo::HasWasmJSFunctionData} predicate.
733 class WasmJSFunctionData
734     : public TorqueGeneratedWasmJSFunctionData<WasmJSFunctionData,
735                                                WasmFunctionData> {
736  public:
737   DECL_ACCESSORS(wasm_to_js_wrapper_code, Code)
738 
739   // Dispatched behavior.
740   DECL_PRINTER(WasmJSFunctionData)
741 
742   class BodyDescriptor;
743 
744  private:
745   DECL_ACCESSORS(raw_wasm_to_js_wrapper_code, CodeT)
746 
747   TQ_OBJECT_CONSTRUCTORS(WasmJSFunctionData)
748 };
749 
750 class WasmCapiFunctionData
751     : public TorqueGeneratedWasmCapiFunctionData<WasmCapiFunctionData,
752                                                  WasmFunctionData> {
753  public:
754   DECL_PRINTER(WasmCapiFunctionData)
755 
756   class BodyDescriptor;
757 
758   TQ_OBJECT_CONSTRUCTORS(WasmCapiFunctionData)
759 };
760 
761 class WasmScript : public AllStatic {
762  public:
763   // Position used for storing "on entry" breakpoints (a.k.a. instrumentation
764   // breakpoints). This would be an illegal position for any other breakpoint.
765   static constexpr int kOnEntryBreakpointPosition = -1;
766 
767   // Set a breakpoint on the given byte position inside the given module.
768   // This will affect all live and future instances of the module.
769   // The passed position might be modified to point to the next breakable
770   // location inside the same function.
771   // If it points outside a function, or behind the last breakable location,
772   // this function returns false and does not set any breakpoint.
773   V8_EXPORT_PRIVATE static bool SetBreakPoint(Handle<Script>, int* position,
774                                               Handle<BreakPoint> break_point);
775 
776   // Set an "on entry" breakpoint (a.k.a. instrumentation breakpoint) inside
777   // the given module. This will affect all live and future instances of the
778   // module.
779   V8_EXPORT_PRIVATE static void SetBreakPointOnEntry(
780       Handle<Script>, Handle<BreakPoint> break_point);
781 
782   // Set a breakpoint on first breakable position of the given function index
783   // inside the given module. This will affect all live and future instances of
784   // the module.
785   V8_EXPORT_PRIVATE static bool SetBreakPointOnFirstBreakableForFunction(
786       Handle<Script>, int function_index, Handle<BreakPoint> break_point);
787 
788   // Set a breakpoint at the breakable offset of the given function index
789   // inside the given module. This will affect all live and future instances of
790   // the module.
791   V8_EXPORT_PRIVATE static bool SetBreakPointForFunction(
792       Handle<Script>, int function_index, int breakable_offset,
793       Handle<BreakPoint> break_point);
794 
795   // Remove a previously set breakpoint at the given byte position inside the
796   // given module. If this breakpoint is not found this function returns false.
797   V8_EXPORT_PRIVATE static bool ClearBreakPoint(Handle<Script>, int position,
798                                                 Handle<BreakPoint> break_point);
799 
800   // Remove a previously set breakpoint by id. If this breakpoint is not found,
801   // returns false.
802   V8_EXPORT_PRIVATE static bool ClearBreakPointById(Handle<Script>,
803                                                     int breakpoint_id);
804 
805   // Remove all set breakpoints.
806   static void ClearAllBreakpoints(Script);
807 
808   // Get a list of all possible breakpoints within a given range of this module.
809   V8_EXPORT_PRIVATE static bool GetPossibleBreakpoints(
810       wasm::NativeModule* native_module, const debug::Location& start,
811       const debug::Location& end, std::vector<debug::BreakLocation>* locations);
812 
813   // Return an empty handle if no breakpoint is hit at that location, or a
814   // FixedArray with all hit breakpoint objects.
815   static MaybeHandle<FixedArray> CheckBreakPoints(Isolate*, Handle<Script>,
816                                                   int position,
817                                                   StackFrameId stack_frame_id);
818 
819  private:
820   // Helper functions that update the breakpoint info list.
821   static void AddBreakpointToInfo(Handle<Script>, int position,
822                                   Handle<BreakPoint> break_point);
823 };
824 
825 // Tags provide an object identity for each exception defined in a wasm module
826 // header. They are referenced by the following fields:
827 //  - {WasmTagObject::tag}: The tag of the {Tag} object.
828 //  - {WasmInstanceObject::tags_table}: List of tags used by an instance.
829 class WasmExceptionTag
830     : public TorqueGeneratedWasmExceptionTag<WasmExceptionTag, Struct> {
831  public:
832   V8_EXPORT_PRIVATE static Handle<WasmExceptionTag> New(Isolate* isolate,
833                                                         int index);
834 
835   TQ_OBJECT_CONSTRUCTORS(WasmExceptionTag)
836 };
837 
838 // Data annotated to the asm.js Module function. Used for later instantiation of
839 // that function.
840 class AsmWasmData : public TorqueGeneratedAsmWasmData<AsmWasmData, Struct> {
841  public:
842   static Handle<AsmWasmData> New(
843       Isolate* isolate, std::shared_ptr<wasm::NativeModule> native_module,
844       Handle<FixedArray> export_wrappers, Handle<HeapNumber> uses_bitset);
845 
846   DECL_PRINTER(AsmWasmData)
847 
848   TQ_OBJECT_CONSTRUCTORS(AsmWasmData)
849 };
850 
851 class WasmTypeInfo : public TorqueGeneratedWasmTypeInfo<WasmTypeInfo, Foreign> {
852  public:
853   inline void clear_foreign_address(Isolate* isolate);
854 
855   DECL_PRINTER(WasmTypeInfo)
856 
857   class BodyDescriptor;
858 
859   TQ_OBJECT_CONSTRUCTORS(WasmTypeInfo)
860 };
861 
862 class WasmObject : public TorqueGeneratedWasmObject<WasmObject, JSReceiver> {
863  public:
864   // Prepares given value for being stored into a field of given Wasm type.
865   V8_WARN_UNUSED_RESULT static inline MaybeHandle<Object> ToWasmValue(
866       Isolate* isolate, wasm::ValueType type, Handle<Object> value);
867 
868  protected:
869   // Returns boxed value of the object's field/element with given type and
870   // offset.
871   static inline Handle<Object> ReadValueAt(Isolate* isolate,
872                                            Handle<HeapObject> obj,
873                                            wasm::ValueType type,
874                                            uint32_t offset);
875 
876   static inline void WriteValueAt(Isolate* isolate, Handle<HeapObject> obj,
877                                   wasm::ValueType type, uint32_t offset,
878                                   Handle<Object> value);
879 
880  private:
881   template <typename ElementType>
882   static ElementType FromNumber(Object value);
883 
884   TQ_OBJECT_CONSTRUCTORS(WasmObject)
885 };
886 
887 class WasmStruct : public TorqueGeneratedWasmStruct<WasmStruct, WasmObject> {
888  public:
889   static inline wasm::StructType* type(Map map);
890   inline wasm::StructType* type() const;
891   static inline wasm::StructType* GcSafeType(Map map);
892   static inline int Size(const wasm::StructType* type);
893   static inline int GcSafeSize(Map map);
894   static inline void EncodeInstanceSizeInMap(int instance_size, Map map);
895   static inline int DecodeInstanceSizeFromMap(Map map);
896 
897   // Returns the address of the field at given offset.
898   inline Address RawFieldAddress(int raw_offset);
899 
900   // Returns the ObjectSlot for tagged value at given offset.
901   inline ObjectSlot RawField(int raw_offset);
902 
903   wasm::WasmValue GetFieldValue(uint32_t field_index);
904 
905   // Returns boxed value of the object's field.
906   static inline Handle<Object> GetField(Isolate* isolate,
907                                         Handle<WasmStruct> obj,
908                                         uint32_t field_index);
909 
910   static inline void SetField(Isolate* isolate, Handle<WasmStruct> obj,
911                               uint32_t field_index, Handle<Object> value);
912 
913   DECL_PRINTER(WasmStruct)
914 
915   class BodyDescriptor;
916 
917   TQ_OBJECT_CONSTRUCTORS(WasmStruct)
918 };
919 
920 class WasmArray : public TorqueGeneratedWasmArray<WasmArray, WasmObject> {
921  public:
922   static inline wasm::ArrayType* type(Map map);
923   inline wasm::ArrayType* type() const;
924   static inline wasm::ArrayType* GcSafeType(Map map);
925 
926   // Get the {ObjectSlot} corresponding to the element at {index}. Requires that
927   // this is a reference array.
928   inline ObjectSlot ElementSlot(uint32_t index);
929   V8_EXPORT_PRIVATE wasm::WasmValue GetElement(uint32_t index);
930 
931   static inline int SizeFor(Map map, int length);
932 
933   // Returns boxed value of the array's element.
934   static inline Handle<Object> GetElement(Isolate* isolate,
935                                           Handle<WasmArray> array,
936                                           uint32_t index);
937 
938   // Returns the offset/Address of the element at {index}.
939   inline uint32_t element_offset(uint32_t index);
940   inline Address ElementAddress(uint32_t index);
941 
942   static int MaxLength(const wasm::ArrayType* type) {
943     // The total object size must fit into a Smi, for filler objects. To make
944     // the behavior of Wasm programs independent from the Smi configuration,
945     // we hard-code the smaller of the two supported ranges.
946     int element_shift = type->element_type().element_size_log2();
947     return (SmiTagging<4>::kSmiMaxValue - kHeaderSize) >> element_shift;
948   }
949 
950   static inline void EncodeElementSizeInMap(int element_size, Map map);
951   static inline int DecodeElementSizeFromMap(Map map);
952 
953   DECL_PRINTER(WasmArray)
954 
955   class BodyDescriptor;
956 
957   TQ_OBJECT_CONSTRUCTORS(WasmArray)
958 };
959 
960 #undef DECL_OPTIONAL_ACCESSORS
961 
962 namespace wasm {
963 
964 Handle<Map> CreateStructMap(Isolate* isolate, const WasmModule* module,
965                             int struct_index, MaybeHandle<Map> rtt_parent,
966                             Handle<WasmInstanceObject> instance);
967 Handle<Map> CreateArrayMap(Isolate* isolate, const WasmModule* module,
968                            int array_index, MaybeHandle<Map> rtt_parent,
969                            Handle<WasmInstanceObject> instance);
970 Handle<Map> AllocateSubRtt(Isolate* isolate,
971                            Handle<WasmInstanceObject> instance, uint32_t type,
972                            Handle<Map> parent, WasmRttSubMode mode);
973 
974 bool TypecheckJSObject(Isolate* isolate, const WasmModule* module,
975                        Handle<Object> value, ValueType expected,
976                        const char** error_message);
977 }  // namespace wasm
978 
979 }  // namespace internal
980 }  // namespace v8
981 
982 #include "src/objects/object-macros-undef.h"
983 
984 #endif  // V8_WASM_WASM_OBJECTS_H_
985