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