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