diff --git a/js/moz.configure b/js/moz.configure index 65987aaa01b1..37758aeca5c6 100644 --- a/js/moz.configure +++ b/js/moz.configure @@ -867,34 +867,6 @@ def wasm_relaxed_simd(value, wasm_simd): set_config("ENABLE_WASM_RELAXED_SIMD", wasm_relaxed_simd) set_define("ENABLE_WASM_RELAXED_SIMD", wasm_relaxed_simd) -# Support for WebAssembly intgemm private intrinsics -# ===================================================== - - -@depends(milestone.is_nightly) -def default_wasm_moz_intgemm(is_nightly): - if is_nightly: - return True - - -option( - "--enable-wasm-moz-intgemm", - default=default_wasm_moz_intgemm, - help="{Enable|Disable} WebAssembly intgemm private intrinsics", -) - - -@depends("--enable-wasm-moz-intgemm") -def wasm_moz_intgemm(value): - if not value: - return - - return True - - -set_config("ENABLE_WASM_MOZ_INTGEMM", wasm_moz_intgemm) -set_define("ENABLE_WASM_MOZ_INTGEMM", wasm_moz_intgemm) - # Support for WebAssembly Memory64. # =========================== diff --git a/js/public/WasmFeatures.h b/js/public/WasmFeatures.h index c48f4503aa81..3cd3525e345b 100644 --- a/js/public/WasmFeatures.h +++ b/js/public/WasmFeatures.h @@ -82,11 +82,6 @@ #else # define WASM_MEMORY64_ENABLED 0 #endif -#ifdef ENABLE_WASM_MOZ_INTGEMM -# define WASM_MOZ_INTGEMM_ENABLED 1 -#else -# define WASM_MOZ_INTGEMM_ENABLED 0 -#endif // clang-format off #define JS_FOR_WASM_FEATURES(DEFAULT, EXPERIMENTAL) \ @@ -143,16 +138,7 @@ /* flag predicate */ !IsFuzzingIon(cx) && \ !IsFuzzingCranelift(cx), \ /* shell flag */ "memory64", \ - /* preference name */ "memory64") \ - EXPERIMENTAL(/* capitalized name */ MozIntGemm, \ - /* lower case name */ mozIntGemm, \ - /* compile predicate */ WASM_MOZ_INTGEMM_ENABLED, \ - /* compiler predicate */ BaselineAvailable(cx) || \ - IonAvailable(cx), \ - /* flag predicate */ IsSimdPrivilegedContext(cx) && \ - !IsFuzzingCranelift(cx), \ - /* shell flag */ "moz-intgemm", \ - /* preference name */ "moz_intgemm") + /* preference name */ "memory64") // clang-format on diff --git a/js/src/builtin/TestingFunctions.cpp b/js/src/builtin/TestingFunctions.cpp index 1bbeabda53be..a296de53a436 100644 --- a/js/src/builtin/TestingFunctions.cpp +++ b/js/src/builtin/TestingFunctions.cpp @@ -1956,9 +1956,8 @@ static bool WasmIntrinsicI8VecMul(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); - wasm::IntrinsicOp ops[] = {wasm::IntrinsicOp::I8VecMul}; RootedWasmModuleObject module(cx); - if (!wasm::CompileIntrinsicModule(cx, ops, wasm::Shareable::False, &module)) { + if (!wasm::CompileIntrinsicModule(cx, wasm::IntrinsicOp::I8VecMul, &module)) { ReportOutOfMemory(cx); return false; } diff --git a/js/src/wasm/WasmIntrinsic.cpp b/js/src/wasm/WasmIntrinsic.cpp index abf76a35f2ba..5509796f7421 100644 --- a/js/src/wasm/WasmIntrinsic.cpp +++ b/js/src/wasm/WasmIntrinsic.cpp @@ -57,8 +57,7 @@ const Intrinsic& Intrinsic::getFromOp(IntrinsicOp op) { } } -bool EncodeIntrinsicBody(const Intrinsic& intrinsic, IntrinsicOp op, - Bytes* body) { +bool EncodeIntrinsicBody(const Intrinsic& intrinsic, Bytes* body) { Encoder encoder(*body); if (!EncodeLocalEntries(encoder, ValTypeVector())) { return false; @@ -68,7 +67,7 @@ bool EncodeIntrinsicBody(const Intrinsic& intrinsic, IntrinsicOp op, return false; } } - if (!encoder.writeOp(op)) { + if (!encoder.writeOp(IntrinsicOp::I8VecMul)) { return false; } if (!encoder.writeOp(Op::End)) { @@ -77,10 +76,10 @@ bool EncodeIntrinsicBody(const Intrinsic& intrinsic, IntrinsicOp op, return true; } -bool wasm::CompileIntrinsicModule(JSContext* cx, - const mozilla::Span ops, - Shareable sharedMemory, +bool wasm::CompileIntrinsicModule(JSContext* cx, IntrinsicOp op, MutableHandleWasmModuleObject result) { + const Intrinsic& intrinsic = Intrinsic::getFromOp(op); + // Create the options manually, enabling intrinsics FeatureOptions featureOptions; featureOptions.intrinsics = true; @@ -105,79 +104,44 @@ bool wasm::CompileIntrinsicModule(JSContext* cx, DefinitionKind::Memory))) { return false; } - moduleEnv.memory = Some(MemoryDesc(Limits(0, Nothing(), sharedMemory))); + moduleEnv.memory = Some(MemoryDesc(Limits(0))); - // Add (type (func (params ...))) for each intrinsic. The function types will - // be deduplicated by the runtime - for (uint32_t funcIndex = 0; funcIndex < ops.size(); funcIndex++) { - const Intrinsic& intrinsic = Intrinsic::getFromOp(ops[funcIndex]); - - FuncType type; - if (!intrinsic.funcType(&type) || - !moduleEnv.types.append(TypeDef(std::move(type))) || - !moduleEnv.typeIds.append(TypeIdDesc())) { - return false; - } + // Add (type (func (params ...))) for the intrinsic + FuncType type; + if (!intrinsic.funcType(&type) || + !moduleEnv.types.append(TypeDef(std::move(type))) || + !moduleEnv.typeIds.append(TypeIdDesc())) { + return false; } - // Add (func (type $i)) declarations. Do this after all types have been added - // as the function declaration metadata uses pointers into the type vectors - // that must be stable. - for (uint32_t funcIndex = 0; funcIndex < ops.size(); funcIndex++) { - FuncDesc decl(&moduleEnv.types[funcIndex].funcType(), - &moduleEnv.typeIds[funcIndex], funcIndex); - if (!moduleEnv.funcs.append(decl)) { - return false; - } - moduleEnv.declareFuncExported(funcIndex, true, false); + // Add (func (type 0)) declaration + FuncDesc decl(&moduleEnv.types[0].funcType(), &moduleEnv.typeIds[0], 0); + if (!moduleEnv.funcs.append(decl)) { + return false; + } + moduleEnv.declareFuncExported(0, true, false); + + // Encode func body that will call the intrinsic using our builtin opcode + Bytes intrinsicBody; + if (!EncodeIntrinsicBody(intrinsic, &intrinsicBody)) { + return false; } - // Add (export "$name" (func $i)) declarations. - for (uint32_t funcIndex = 0; funcIndex < ops.size(); funcIndex++) { - const Intrinsic& intrinsic = Intrinsic::getFromOp(ops[funcIndex]); - - UniqueChars exportString = DuplicateString(intrinsic.exportName); - if (!exportString || - !moduleEnv.exports.append(Export(std::move(exportString), funcIndex, - DefinitionKind::Function))) { - return false; - } + // Add (export "$name" (func 0)) + UniqueChars exportString = DuplicateString(intrinsic.exportName); + if (!exportString || + !moduleEnv.exports.append( + Export(std::move(exportString), 0, DefinitionKind::Function))) { + return false; } // Compile the module functions UniqueChars error; ModuleGenerator mg(*compileArgs, &moduleEnv, &compilerEnv, nullptr, &error); - if (!mg.init(nullptr)) { - return false; - } - - // Prepare and compile function bodies - Vector bodies; - if (!bodies.reserve(ops.size())) { - return false; - } - for (uint32_t funcIndex = 0; funcIndex < ops.size(); funcIndex++) { - IntrinsicOp op = ops[funcIndex]; - const Intrinsic& intrinsic = Intrinsic::getFromOp(ops[funcIndex]); - - // Compilation may be done using other threads, ModuleGenerator requires - // that function bodies live until after finishFuncDefs(). - bodies.infallibleAppend(Bytes()); - Bytes& bytecode = bodies.back(); - - // Encode function body that will call the intrinsic using our builtin - // opcode, and launch a compile task - if (!EncodeIntrinsicBody(intrinsic, op, &bytecode) || - !mg.compileFuncDef(funcIndex, 0, bytecode.begin(), - bytecode.begin() + bytecode.length())) { - // This must be an OOM and will be reported by the caller - MOZ_ASSERT(!error); - return false; - } - } - - // Finish and block on function compilation - if (!mg.finishFuncDefs()) { + if (!mg.init(nullptr) || + !mg.compileFuncDef(0, 0, intrinsicBody.begin(), + intrinsicBody.begin() + intrinsicBody.length()) || + !mg.finishFuncDefs()) { // This must be an OOM and will be reported by the caller MOZ_ASSERT(!error); return false; diff --git a/js/src/wasm/WasmIntrinsic.h b/js/src/wasm/WasmIntrinsic.h index 7b97edee0af4..858a124bf375 100644 --- a/js/src/wasm/WasmIntrinsic.h +++ b/js/src/wasm/WasmIntrinsic.h @@ -22,7 +22,6 @@ #include "mozilla/Span.h" #include "wasm/WasmBuiltins.h" -#include "wasm/WasmCompileArgs.h" #include "wasm/WasmConstants.h" #include "wasm/WasmTypeDecls.h" #include "wasm/WasmTypeDef.h" @@ -49,9 +48,10 @@ struct Intrinsic { static const Intrinsic& getFromOp(IntrinsicOp op); }; -// Compile and return the intrinsic module for a given set of intrinsic ops. -bool CompileIntrinsicModule(JSContext* cx, const mozilla::Span ops, - Shareable sharedMemory, +// Compile and return the intrinsic module for a given intrinsic op. This only +// allows one intrinsic to be compiled at a time, but eventually we will allow +// multiple to share a module. +bool CompileIntrinsicModule(JSContext* cx, IntrinsicOp op, MutableHandleWasmModuleObject result); } // namespace wasm diff --git a/js/src/wasm/WasmJS.cpp b/js/src/wasm/WasmJS.cpp index 3c07e5468b13..60fc7647ed5f 100644 --- a/js/src/wasm/WasmJS.cpp +++ b/js/src/wasm/WasmJS.cpp @@ -58,7 +58,6 @@ #include "wasm/WasmCompile.h" #include "wasm/WasmCraneliftCompile.h" #include "wasm/WasmInstance.h" -#include "wasm/WasmIntrinsic.h" #include "wasm/WasmIonCompile.h" #include "wasm/WasmModule.h" #include "wasm/WasmProcess.h" @@ -344,12 +343,14 @@ bool wasm::AnyCompilerAvailable(JSContext* cx) { JS_FOR_WASM_FEATURES(WASM_FEATURE, WASM_FEATURE) #undef WASM_FEATURE -bool wasm::IsSimdPrivilegedContext(JSContext* cx) { +#ifdef ENABLE_WASM_SIMD_WORMHOLE +static bool IsSimdPrivilegedContext(JSContext* cx) { // This may be slightly more lenient than we want in an ideal world, but it // remains safe. return cx->realm() && cx->realm()->principals() && cx->realm()->principals()->isSystemOrAddonPrincipal(); } +#endif bool wasm::SimdWormholeAvailable(JSContext* cx) { #ifdef ENABLE_WASM_SIMD_WORMHOLE @@ -4985,27 +4986,6 @@ static bool WebAssembly_instantiateStreaming(JSContext* cx, unsigned argc, return true; } -#ifdef ENABLE_WASM_MOZ_INTGEMM - -static bool WebAssembly_mozIntGemm(JSContext* cx, unsigned argc, Value* vp) { - CallArgs args = CallArgsFromVp(argc, vp); - - RootedWasmModuleObject module(cx); - if (!wasm::CompileIntrinsicModule(cx, mozilla::Span(), - Shareable::True, &module)) { - ReportOutOfMemory(cx); - return false; - } - args.rval().set(ObjectValue(*module.get())); - return true; -} - -static const JSFunctionSpec WebAssembly_mozIntGemm_methods[] = { - JS_FN("mozIntGemm", WebAssembly_mozIntGemm, 0, JSPROP_ENUMERATE), - JS_FS_END}; - -#endif // ENABLE_WASM_MOZ_INTGEMM - static const JSFunctionSpec WebAssembly_static_methods[] = { JS_FN(js_toSource_str, WebAssembly_toSource, 0, 0), JS_FN("compile", WebAssembly_compile, 1, JSPROP_ENUMERATE), @@ -5029,77 +5009,53 @@ static JSObject* CreateWebAssemblyObject(JSContext* cx, JSProtoKey key) { proto); } -struct NameAndProtoKey { - const char* const name; - JSProtoKey key; -}; - -static bool WebAssemblyDefineConstructor(JSContext* cx, - Handle wasm, - NameAndProtoKey entry, - MutableHandleValue ctorValue, - MutableHandleId id) { - JSObject* ctor = GlobalObject::getOrCreateConstructor(cx, entry.key); - if (!ctor) { - return false; - } - ctorValue.setObject(*ctor); - - JSAtom* className = Atomize(cx, entry.name, strlen(entry.name)); - if (!className) { - return false; - } - id.set(AtomToId(className)); - - if (!DefineDataProperty(cx, wasm, id, ctorValue, 0)) { - return false; - } - return true; -} - static bool WebAssemblyClassFinish(JSContext* cx, HandleObject object, HandleObject proto) { Handle wasm = object.as(); + struct NameAndProtoKey { + const char* const name; + JSProtoKey key; + }; + constexpr NameAndProtoKey entries[] = { {"Module", JSProto_WasmModule}, {"Instance", JSProto_WasmInstance}, {"Memory", JSProto_WasmMemory}, {"Table", JSProto_WasmTable}, {"Global", JSProto_WasmGlobal}, +#ifdef ENABLE_WASM_EXCEPTIONS + {"Tag", JSProto_WasmTag}, + {"Exception", JSProto_WasmException}, +#endif {"CompileError", GetExceptionProtoKey(JSEXN_WASMCOMPILEERROR)}, {"LinkError", GetExceptionProtoKey(JSEXN_WASMLINKERROR)}, {"RuntimeError", GetExceptionProtoKey(JSEXN_WASMRUNTIMEERROR)}, }; + RootedValue ctorValue(cx); RootedId id(cx); for (const auto& entry : entries) { - if (!WebAssemblyDefineConstructor(cx, wasm, entry, &ctorValue, &id)) { + const char* name = entry.name; + JSProtoKey key = entry.key; + + JSObject* ctor = GlobalObject::getOrCreateConstructor(cx, key); + if (!ctor) { + return false; + } + ctorValue.setObject(*ctor); + + JSAtom* className = Atomize(cx, name, strlen(name)); + if (!className) { + return false; + } + id.set(AtomToId(className)); + + if (!DefineDataProperty(cx, wasm, id, ctorValue, 0)) { return false; } } -#ifdef ENABLE_WASM_EXCEPTIONS - if (ExceptionsAvailable(cx)) { - constexpr NameAndProtoKey exceptionEntries[] = { - {"Tag", JSProto_WasmTag}, - {"Exception", JSProto_WasmException}, - }; - for (const auto& entry : exceptionEntries) { - if (!WebAssemblyDefineConstructor(cx, wasm, entry, &ctorValue, &id)) { - return false; - } - } - } -#endif - -#ifdef ENABLE_WASM_MOZ_INTGEMM - if (MozIntGemmAvailable(cx) && - !JS_DefineFunctions(cx, wasm, WebAssembly_mozIntGemm_methods)) { - return false; - } -#endif - return true; } diff --git a/js/src/wasm/WasmJS.h b/js/src/wasm/WasmJS.h index 3c7bbcd53def..9661285d2c7e 100644 --- a/js/src/wasm/WasmJS.h +++ b/js/src/wasm/WasmJS.h @@ -152,9 +152,6 @@ bool ThreadsAvailable(JSContext* cx); JS_FOR_WASM_FEATURES(WASM_FEATURE, WASM_FEATURE) #undef WASM_FEATURE -// Privileged content that can access experimental intrinsics -bool IsSimdPrivilegedContext(JSContext* cx); - // Very experimental SIMD operations. bool SimdWormholeAvailable(JSContext* cx); diff --git a/modules/libpref/init/StaticPrefList.yaml b/modules/libpref/init/StaticPrefList.yaml index bad2818b2b3a..0e92bac6bb77 100644 --- a/modules/libpref/init/StaticPrefList.yaml +++ b/modules/libpref/init/StaticPrefList.yaml @@ -5989,13 +5989,6 @@ mirror: always #endif // defined(ENABLE_WASM_RELAXED_SIMD) -#if defined(ENABLE_WASM_MOZ_INTGEMM) -- name: javascript.options.wasm_moz_intgemm - type: bool - value: @IS_NIGHTLY_BUILD@ - mirror: always -#endif // defined(ENABLE_WASM_MOZ_INTGEMM) - #if defined(ENABLE_WASM_EXTENDED_CONST) - name: javascript.options.wasm_extended_const type: bool