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