diff --git a/Libraries/LibWasm/AbstractMachine/AbstractMachine.h b/Libraries/LibWasm/AbstractMachine/AbstractMachine.h index f57ed0ac5c..375cf9393e 100644 --- a/Libraries/LibWasm/AbstractMachine/AbstractMachine.h +++ b/Libraries/LibWasm/AbstractMachine/AbstractMachine.h @@ -962,6 +962,11 @@ public: return *m_heap; } + // For embedders that decide on a (shared) heap after constructing the machine. Must + // happen before any code runs. + bool has_heap() const { return m_heap != nullptr; } + void adopt_heap(GC::Heap&); + // Validate a module; permanently sets the module's validity status. ErrorOr validate(Module&, Optional cache_config = {}, CompileToNative = CompileToNative::Yes); // Load and instantiate a module, and link it into this interpreter. @@ -1004,7 +1009,6 @@ private: Optional allocate_all_initial_phase(Module const&, ModuleInstance&, Vector&, Vector& global_values, Vector& table_initial_values, Vector& own_functions); Optional allocate_all_final_phase(Module const&, ModuleInstance&, Vector>& elements); - void adopt_heap(GC::Heap&); void create_own_heap(); class RootsProvider final : public GC::ConservativeRangeProvider { diff --git a/Libraries/LibWasm/AbstractMachine/Validator.cpp b/Libraries/LibWasm/AbstractMachine/Validator.cpp index 72fc62e3aa..36b50b3a42 100644 --- a/Libraries/LibWasm/AbstractMachine/Validator.cpp +++ b/Libraries/LibWasm/AbstractMachine/Validator.cpp @@ -1638,8 +1638,7 @@ VALIDATE_INSTRUCTION(select_typed) return Errors::invalid("select types"sv, "exactly one type"sv, required_types); // https://webassembly.github.io/spec/core/valid/instructions.html#parametric-instructions - // select t: valid with [t t i32] -> [t] if the value type t is valid; both operands must - // match the annotated type. + // select t: valid with [t t i32] -> [t] if the value type t is valid; both operands must match the annotated type. TRY(validate(required_types.first())); TRY(stack.take()); TRY(stack.take(required_types.first())); @@ -1781,8 +1780,6 @@ VALIDATE_INSTRUCTION(table_copy) auto lhs_table = TRY(validate(args.lhs)); auto rhs_table = TRY(validate(args.rhs)); - // https://webassembly.github.io/spec/core/valid/instructions.html#table-instructions - // table.copy x y: the source table's reference type rt2 must match the destination's rt1. if (!matches_reference_type(rhs_table.element_type(), lhs_table.element_type(), m_context.type_context())) return Errors::non_conforming_types("table.copy"sv, lhs_table.element_type(), rhs_table.element_type()); @@ -1806,9 +1803,6 @@ VALIDATE_INSTRUCTION(table_init) auto& element_type = m_context.elements[args.element_index.value()]; - // https://webassembly.github.io/spec/core/valid/instructions.html#table-instructions - // table.init x y: "The element segment C.elems[y] must match the reference type rt" of the - // table C.tables[x]. if (!matches_reference_type(element_type, table.element_type(), m_context.type_context())) return Errors::non_conforming_types("table.init"sv, table.element_type(), element_type); @@ -2673,9 +2667,6 @@ VALIDATE_INSTRUCTION(call_indirect) auto table = TRY(validate(args.table)); TRY(validate(args.type)); - // https://webassembly.github.io/spec/core/valid/instructions.html#control-instructions - // call_indirect x y: "The table C.tables[x] must be of the form (at lim rt), and rt must - // match (ref null func)." if (!matches_reference_type(table.element_type(), ValueType(ValueType::FunctionReference), m_context.type_context())) return Errors::invalid("table element type for call.indirect"sv, "a function reference"sv, table.element_type()); @@ -2722,7 +2713,6 @@ VALIDATE_INSTRUCTION(return_call_indirect) TRY(validate(args.type)); auto& table = m_context.tables[args.table.value()]; - // See call_indirect: rt must match (ref null func). if (!matches_reference_type(table.element_type(), ValueType(ValueType::FunctionReference), m_context.type_context())) return Errors::invalid("table element type for call.indirect"sv, "a function reference"sv, table.element_type()); diff --git a/Libraries/LibWasm/Parser/Parser.cpp b/Libraries/LibWasm/Parser/Parser.cpp index d5aa96956c..bba576a4d8 100644 --- a/Libraries/LibWasm/Parser/Parser.cpp +++ b/Libraries/LibWasm/Parser/Parser.cpp @@ -1573,8 +1573,6 @@ ParseResult ElementSection::Element::parse(ConstrainedS // https://webassembly.github.io/spec/core/binary/modules.html#element-section // elemkind ::= 0x00 => (ref func) - // Segments listing function indices have the non-nullable type (ref func) (flags 0-3); - // the flag-4 expression shorthand has type funcref, i.e. (ref null func). auto type = has_exprs ? ValueType(ValueType::FunctionReference) : ValueType(ValueType::FunctionReference, false); if (has_passive || has_explicit_index) { if (has_exprs) { diff --git a/Libraries/LibWeb/WebAssembly/WebAssembly.cpp b/Libraries/LibWeb/WebAssembly/WebAssembly.cpp index a76dcfd3ff..4707c158d2 100644 --- a/Libraries/LibWeb/WebAssembly/WebAssembly.cpp +++ b/Libraries/LibWeb/WebAssembly/WebAssembly.cpp @@ -55,15 +55,17 @@ static GC::Ref compile_potential_webassembly_response(JS::VM&, namespace Detail { -static GC::WeakHashMap& caches() +// The caches hold AbstractMachines whose gc-roots providers keep pointers into them, so they +// live behind OwnPtrs and never move on rehash. +static GC::WeakHashMap>& caches() { - static NeverDestroyed> caches; + static NeverDestroyed>> caches; return *caches; } WebAssemblyCache& get_cache(JS::Realm& realm) { - return caches().ensure(realm.global_object()); + return *caches().ensure(realm.global_object(), [] { return make(); }); } } @@ -72,7 +74,7 @@ void visit_edges(JS::Object& object, JS::Cell::Visitor& visitor) { auto& global_object = HTML::relevant_global_object(object); if (auto maybe_cache = Detail::caches().get(global_object); maybe_cache.has_value()) { - auto& cache = maybe_cache.value(); + auto& cache = *maybe_cache.value(); visitor.visit(cache.function_instances()); visitor.visit(cache.imported_objects()); visitor.visit(cache.extern_values()); diff --git a/Libraries/LibWeb/WebAssembly/WebAssembly.h b/Libraries/LibWeb/WebAssembly/WebAssembly.h index 29dbd46a4a..0cdb0e0581 100644 --- a/Libraries/LibWeb/WebAssembly/WebAssembly.h +++ b/Libraries/LibWeb/WebAssembly/WebAssembly.h @@ -49,7 +49,12 @@ struct CompiledWebAssemblyModule : public RefCounted }; class WebAssemblyCache { + AK_MAKE_NONCOPYABLE(WebAssemblyCache); + AK_MAKE_NONMOVABLE(WebAssemblyCache); + public: + WebAssemblyCache() = default; + void add_compiled_module(NonnullRefPtr module) { m_compiled_modules.append(module); } void add_function_instance(Wasm::FunctionAddress address, GC::Ptr function) { m_function_instances.set(address, function); } void add_imported_object(GC::Ptr object) { m_imported_objects.set(object); }