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