From 343cd588245cb4ee82090e82e7ac2abd095e3666 Mon Sep 17 00:00:00 2001 From: Ryan Hunt Date: Thu, 30 Nov 2023 00:46:31 +0000 Subject: [PATCH] Bug 1863794 - wasm: Generalize builtin module function support. r=yury - Add optional result to builtin module functions - Allow RefType params to builtin module functions - Don't require linear memory to be available These are required for expressing the kinds of functions that we want for js-string-builtins. Depends on D193110 Differential Revision: https://phabricator.services.mozilla.com/D193111 --- js/src/builtin/TestingFunctions.cpp | 3 +- js/src/wasm/GenerateBuiltinModules.py | 42 +++++++-- js/src/wasm/WasmBaselineCompile.cpp | 6 +- js/src/wasm/WasmBuiltinModule.cpp | 66 ++++++++------ js/src/wasm/WasmBuiltinModule.h | 11 ++- js/src/wasm/WasmBuiltinModule.yaml | 122 +++++++++++++++----------- js/src/wasm/WasmBuiltins.cpp | 14 +-- js/src/wasm/WasmBuiltins.h | 4 +- js/src/wasm/WasmConstants.h | 3 +- js/src/wasm/WasmFrameIter.cpp | 4 +- js/src/wasm/WasmIonCompile.cpp | 21 ++++- js/src/wasm/WasmJS.cpp | 2 +- js/src/wasm/WasmOpIter.h | 10 ++- js/src/wasm/WasmValType.h | 13 ++- 14 files changed, 203 insertions(+), 118 deletions(-) diff --git a/js/src/builtin/TestingFunctions.cpp b/js/src/builtin/TestingFunctions.cpp index 48b49e6df8bd..9e68f99092ca 100644 --- a/js/src/builtin/TestingFunctions.cpp +++ b/js/src/builtin/TestingFunctions.cpp @@ -2120,7 +2120,8 @@ static bool WasmBuiltinI8VecMul(JSContext* cx, unsigned argc, Value* vp) { wasm::BuiltinModuleFuncId ids[] = {wasm::BuiltinModuleFuncId::I8VecMul}; Rooted module(cx); - if (!wasm::CompileBuiltinModule(cx, ids, wasm::Shareable::False, &module)) { + if (!wasm::CompileBuiltinModule(cx, ids, Some(wasm::Shareable::False), + &module)) { return false; } args.rval().set(ObjectValue(*module.get())); diff --git a/js/src/wasm/GenerateBuiltinModules.py b/js/src/wasm/GenerateBuiltinModules.py index 56f698f276b6..f9bf2cbe86f1 100644 --- a/js/src/wasm/GenerateBuiltinModules.py +++ b/js/src/wasm/GenerateBuiltinModules.py @@ -56,6 +56,12 @@ def load_yaml(yaml_path): return yaml.load(contents, OrderedLoader) +def cppBool(v): + if v: + return "true" + return "false" + + def main(c_out, yaml_path): data = load_yaml(yaml_path) @@ -66,21 +72,41 @@ def main(c_out, yaml_path): sa = op["symbolic_address"] contents += ( f" M({op['op']}, \"{op['export']}\", " - f"{sa['name']}, {sa['type']}, {op['entry']}, {i})\\\n" + f"{sa['name']}, {sa['type']}, {op['entry']}, {cppBool(op['uses_memory'])}, {i})\\\n" ) contents += "\n" for op in data: - # Define DECLARE_BUILTIN_MODULE_FUNC_SAS_PARAM_VALTYPES_ as: + # Define DECLARE_BUILTIN_MODULE_FUNC_PARAM_VALTYPES_ as: # `{ValType::I32, ValType::I32, ...}`. contents += ( - f"#define DECLARE_BUILTIN_MODULE_FUNC_SAS_PARAM_VALTYPES_{op['op']} " - f"{{ValType::{', ValType::'.join(op['params'])}}}\n" + f"#define DECLARE_BUILTIN_MODULE_FUNC_PARAM_VALTYPES_{op['op']} " + f"{{{', '.join(op['params'])}}}\n" ) - # Define DECLARE_BUILTIN_MODULE_FUNC_PARAM_TYPES_ as: + + # Define DECLARE_BUILTIN_MODULE_FUNC_PARAM_SASTYPES_ as: # `, {_PTR, _I32, ..., _PTR, _END}`. - sas_types = f"{{_PTR{''.join(', _' + p for p in op['params'])}, _PTR, _END}}" - num_types = len(op["params"]) + 2 - contents += f"#define DECLARE_BUILTIN_MODULE_FUNC_PARAM_TYPES_{op['op']} {num_types}, {sas_types}\n" + num_types = len(op["params"]) + 1 + sas_types = ( + f"{{_PTR{''.join(', ' + (p + '.toMIRType()') for p in op['params'])}" + ) + if op["uses_memory"]: + sas_types += ", _PTR" + num_types += 1 + sas_types += ", _END}" + + contents += f"#define DECLARE_BUILTIN_MODULE_FUNC_PARAM_SASTYPES_{op['op']} {num_types}, {sas_types}\n" + + result_valtype = "" + result_sastype = "" + if "result" in op: + result_valtype = f"Some({op['result']})\n" + result_sastype = f"{op['result']}.toMIRType()\n" + else: + result_valtype = "Nothing()" + result_sastype = "_VOID" + contents += f"#define DECLARE_BUILTIN_MODULE_FUNC_RESULT_VALTYPE_{op['op']} {result_valtype}\n" + contents += f"#define DECLARE_BUILTIN_MODULE_FUNC_RESULT_SASTYPE_{op['op']} {result_sastype}\n" + contents += f"#define DECLARE_BUILTIN_MODULE_FUNC_FAILMODE_{op['op']} _{op['fail_mode']}\n" generate_header(c_out, "wasm_WasmBuiltinModuleGenerated_h", contents) diff --git a/js/src/wasm/WasmBaselineCompile.cpp b/js/src/wasm/WasmBaselineCompile.cpp index 387504fc87ac..f012f2517ba3 100644 --- a/js/src/wasm/WasmBaselineCompile.cpp +++ b/js/src/wasm/WasmBaselineCompile.cpp @@ -9415,8 +9415,10 @@ bool BaseCompiler::emitCallBuiltinModuleFunc() { return true; } - // The final parameter of an builtinModuleFunc is implicitly the heap base - pushHeapBase(0); + if (builtinModuleFunc->usesMemory) { + // The final parameter of an builtinModuleFunc is implicitly the heap base + pushHeapBase(0); + } // Call the builtinModuleFunc return emitInstanceCall(builtinModuleFunc->signature); diff --git a/js/src/wasm/WasmBuiltinModule.cpp b/js/src/wasm/WasmBuiltinModule.cpp index 9fd0ea86f7e8..b66aa39671e1 100644 --- a/js/src/wasm/WasmBuiltinModule.cpp +++ b/js/src/wasm/WasmBuiltinModule.cpp @@ -32,14 +32,17 @@ using namespace js; using namespace js::wasm; -#define VISIT_BUILTIN_FUNC(op, export, sa_name, abitype, entry, idx) \ - static const ValType BuiltinModuleFunc##op##_Params[] = \ - DECLARE_BUILTIN_MODULE_FUNC_SAS_PARAM_VALTYPES_##op; \ - \ - const BuiltinModuleFunc BuiltinModuleFunc##op = { \ - export, \ - mozilla::Span(BuiltinModuleFunc##op##_Params), \ - SASig##sa_name, \ +#define VISIT_BUILTIN_FUNC(op, export, sa_name, abitype, entry, uses_memory, \ + idx) \ + static const ValType BuiltinModuleFunc##op##_Params[] = \ + DECLARE_BUILTIN_MODULE_FUNC_PARAM_VALTYPES_##op; \ + \ + const BuiltinModuleFunc BuiltinModuleFunc##op = { \ + export, \ + mozilla::Span(BuiltinModuleFunc##op##_Params), \ + DECLARE_BUILTIN_MODULE_FUNC_RESULT_VALTYPE_##op, \ + SASig##sa_name, \ + uses_memory, \ }; FOR_EACH_BUILTIN_MODULE_FUNC(VISIT_BUILTIN_FUNC) @@ -50,15 +53,19 @@ bool BuiltinModuleFunc::funcType(FuncType* type) const { if (!paramVec.append(params.data(), params.data() + params.size())) { return false; } - *type = FuncType(std::move(paramVec), ValTypeVector()); + ValTypeVector resultVec; + if (result.isSome() && !resultVec.append(*result)) { + return false; + } + *type = FuncType(std::move(paramVec), std::move(resultVec)); return true; } /* static */ const BuiltinModuleFunc& BuiltinModuleFunc::getFromId(BuiltinModuleFuncId id) { switch (id) { -#define VISIT_BUILTIN_FUNC(op, export, sa_name, abitype, entry, idx) \ - case BuiltinModuleFuncId::op: \ +#define VISIT_BUILTIN_FUNC(op, ...) \ + case BuiltinModuleFuncId::op: \ return BuiltinModuleFunc##op; FOR_EACH_BUILTIN_MODULE_FUNC(VISIT_BUILTIN_FUNC) #undef VISIT_BUILTIN_FUNC @@ -89,7 +96,7 @@ bool EncodeFuncBody(const BuiltinModuleFunc& builtinModuleFunc, bool wasm::CompileBuiltinModule(JSContext* cx, const mozilla::Span ids, - Shareable sharedMemory, + mozilla::Maybe memory, MutableHandle result) { // Create the options manually, enabling intrinsics FeatureOptions featureOptions; @@ -113,23 +120,24 @@ bool wasm::CompileBuiltinModule(JSContext* cx, return false; } - // Add (import (memory 0)) - CacheableName emptyString; - CacheableName memoryString; - if (!CacheableName::fromUTF8Chars("memory", &memoryString)) { - ReportOutOfMemory(cx); - return false; - } - if (!moduleEnv.imports.append(Import(std::move(emptyString), - std::move(memoryString), - DefinitionKind::Memory))) { - ReportOutOfMemory(cx); - return false; - } - if (!moduleEnv.memories.append( - MemoryDesc(Limits(0, Nothing(), sharedMemory)))) { - ReportOutOfMemory(cx); - return false; + if (memory.isSome()) { + // Add (import (memory 0)) + CacheableName emptyString; + CacheableName memoryString; + if (!CacheableName::fromUTF8Chars("memory", &memoryString)) { + ReportOutOfMemory(cx); + return false; + } + if (!moduleEnv.imports.append(Import(std::move(emptyString), + std::move(memoryString), + DefinitionKind::Memory))) { + ReportOutOfMemory(cx); + return false; + } + if (!moduleEnv.memories.append(MemoryDesc(Limits(0, Nothing(), *memory)))) { + ReportOutOfMemory(cx); + return false; + } } // Add (type (func (params ...))) for each func. The function types will diff --git a/js/src/wasm/WasmBuiltinModule.h b/js/src/wasm/WasmBuiltinModule.h index de64ea70a4b2..67861cd13bbb 100644 --- a/js/src/wasm/WasmBuiltinModule.h +++ b/js/src/wasm/WasmBuiltinModule.h @@ -19,6 +19,7 @@ #ifndef wasm_builtin_module_h #define wasm_builtin_module_h +#include "mozilla/Maybe.h" #include "mozilla/Span.h" #include "wasm/WasmBuiltins.h" @@ -36,11 +37,15 @@ namespace wasm { struct BuiltinModuleFunc { // The name of the func as it is exported const char* exportName; - // The params taken by the func. No results are required for these funcs - // at this time, so we omit them + // The params taken by the func. mozilla::Span params; + // The optional result returned by the func. + mozilla::Maybe result; // The signature of the builtin that implements the func const SymbolicAddressSignature& signature; + // Whether this function takes a pointer to the memory base as a hidden final + // parameter. + bool usesMemory; // Allocate a FuncType for this func, returning false for OOM bool funcType(FuncType* type) const; @@ -53,7 +58,7 @@ struct BuiltinModuleFunc { // Compile and return the builtin module for a given set of operations. bool CompileBuiltinModule(JSContext* cx, const mozilla::Span ids, - Shareable sharedMemory, + mozilla::Maybe memory, MutableHandle result); } // namespace wasm diff --git a/js/src/wasm/WasmBuiltinModule.yaml b/js/src/wasm/WasmBuiltinModule.yaml index e707671750eb..ee1c59b73439 100644 --- a/js/src/wasm/WasmBuiltinModule.yaml +++ b/js/src/wasm/WasmBuiltinModule.yaml @@ -12,10 +12,12 @@ entry: Instance::intrI8VecMul export: i8vecmul params: - - I32 - - I32 - - I32 - - I32 + - 'ValType::i32()' + - 'ValType::i32()' + - 'ValType::i32()' + - 'ValType::i32()' + fail_mode: FailOnNegI32 + uses_memory: true #if defined(ENABLE_WASM_MOZ_INTGEMM) @@ -38,12 +40,14 @@ entry: intgemm::IntrI8PrepareB export: int8_prepare_b params: - - I32 - - F32 - - F32 - - I32 - - I32 - - I32 + - 'ValType::i32()' + - 'ValType::f32()' + - 'ValType::f32()' + - 'ValType::i32()' + - 'ValType::i32()' + - 'ValType::i32()' + fail_mode: FailOnNegI32 + uses_memory: true # Prepare B for the Matrix Multiply intrinsic from transposed version of Input matrix B. @@ -61,12 +65,14 @@ entry: intgemm::IntrI8PrepareBFromTransposed export: int8_prepare_b_from_transposed params: - - I32 - - F32 - - F32 - - I32 - - I32 - - I32 + - 'ValType::i32()' + - 'ValType::f32()' + - 'ValType::f32()' + - 'ValType::i32()' + - 'ValType::i32()' + - 'ValType::i32()' + fail_mode: FailOnNegI32 + uses_memory: true # Prepare B for the Matrix Multiply intrinsic from a quantized and transposed version of Input @@ -84,10 +90,12 @@ entry: intgemm::IntrI8PrepareBFromQuantizedTransposed export: int8_prepare_b_from_quantized_transposed params: - - I32 - - I32 - - I32 - - I32 + - 'ValType::i32()' + - 'ValType::i32()' + - 'ValType::i32()' + - 'ValType::i32()' + fail_mode: FailOnNegI32 + uses_memory: true # Prepare A for the Matrix Multiply intrinsic from Input matrix A. @@ -108,12 +116,14 @@ entry: intgemm::IntrI8PrepareA export: int8_prepare_a params: - - I32 - - F32 - - F32 - - I32 - - I32 - - I32 + - 'ValType::i32()' + - 'ValType::f32()' + - 'ValType::f32()' + - 'ValType::i32()' + - 'ValType::i32()' + - 'ValType::i32()' + fail_mode: FailOnNegI32 + uses_memory: true # Prepares bias for the Matrix Multiply intrinsic. @@ -132,15 +142,17 @@ entry: intgemm::IntrI8PrepareBias export: int8_prepare_bias params: - - I32 - - F32 - - F32 - - F32 - - F32 - - I32 - - I32 - - I32 - - I32 + - 'ValType::i32()' + - 'ValType::f32()' + - 'ValType::f32()' + - 'ValType::f32()' + - 'ValType::f32()' + - 'ValType::i32()' + - 'ValType::i32()' + - 'ValType::i32()' + - 'ValType::i32()' + fail_mode: FailOnNegI32 + uses_memory: true # Perform multiplication of 2 matrices followed by adding a bias. @@ -165,18 +177,20 @@ entry: intgemm::IntrI8MultiplyAndAddBias export: int8_multiply_and_add_bias params: - - I32 - - F32 - - F32 - - I32 - - F32 - - F32 - - I32 - - F32 - - I32 - - I32 - - I32 - - I32 + - 'ValType::i32()' + - 'ValType::f32()' + - 'ValType::f32()' + - 'ValType::i32()' + - 'ValType::f32()' + - 'ValType::f32()' + - 'ValType::i32()' + - 'ValType::f32()' + - 'ValType::i32()' + - 'ValType::i32()' + - 'ValType::i32()' + - 'ValType::i32()' + fail_mode: FailOnNegI32 + uses_memory: true # Select a subset of columns of prepared B. @@ -192,11 +206,13 @@ entry: intgemm::IntrI8SelectColumnsOfB export: int8_select_columns_of_b params: - - I32 - - I32 - - I32 - - I32 - - I32 - - I32 + - 'ValType::i32()' + - 'ValType::i32()' + - 'ValType::i32()' + - 'ValType::i32()' + - 'ValType::i32()' + - 'ValType::i32()' + fail_mode: FailOnNegI32 + uses_memory: true #endif // ENABLE_WASM_MOZ_INTGEMM diff --git a/js/src/wasm/WasmBuiltins.cpp b/js/src/wasm/WasmBuiltins.cpp index 608e7bf72c56..edae14069670 100644 --- a/js/src/wasm/WasmBuiltins.cpp +++ b/js/src/wasm/WasmBuiltins.cpp @@ -393,10 +393,12 @@ const SymbolicAddressSignature SASigArrayCopy = { 7, {_PTR, _RoN, _I32, _RoN, _I32, _I32, _I32, _END}}; -#define VISIT_BUILTIN_FUNC(op, export, sa_name, abitype, entry, idx) \ - const SymbolicAddressSignature SASig##sa_name = { \ - SymbolicAddress::sa_name, _VOID, _FailOnNegI32, \ - DECLARE_BUILTIN_MODULE_FUNC_PARAM_TYPES_##op}; +#define VISIT_BUILTIN_FUNC(op, export, sa_name, ...) \ + const SymbolicAddressSignature SASig##sa_name = { \ + SymbolicAddress::sa_name, \ + DECLARE_BUILTIN_MODULE_FUNC_RESULT_SASTYPE_##op, \ + DECLARE_BUILTIN_MODULE_FUNC_FAILMODE_##op, \ + DECLARE_BUILTIN_MODULE_FUNC_PARAM_SASTYPES_##op}; FOR_EACH_BUILTIN_MODULE_FUNC(VISIT_BUILTIN_FUNC) #undef VISIT_BUILTIN_FUNC @@ -1455,7 +1457,7 @@ void* wasm::AddressOf(SymbolicAddress imm, ABIFunctionType* abiType) { *abiType = Args_General1; return FuncCast(PrintText, *abiType); #endif -#define VISIT_BUILTIN_FUNC(op, export, sa_name, abitype, entry, idx) \ +#define VISIT_BUILTIN_FUNC(op, export, sa_name, abitype, entry, ...) \ case SymbolicAddress::sa_name: \ *abiType = abitype; \ return FuncCast(entry, *abiType); @@ -1617,7 +1619,7 @@ bool wasm::NeedsBuiltinThunk(SymbolicAddress sym) { case SymbolicAddress::ArrayInitData: case SymbolicAddress::ArrayInitElem: case SymbolicAddress::ArrayCopy: -#define VISIT_BUILTIN_FUNC(op, export, sa_name, abitype, entry, idx) \ +#define VISIT_BUILTIN_FUNC(op, export, sa_name, ...) \ case SymbolicAddress::sa_name: FOR_EACH_BUILTIN_MODULE_FUNC(VISIT_BUILTIN_FUNC) #undef VISIT_BUILTIN_FUNC diff --git a/js/src/wasm/WasmBuiltins.h b/js/src/wasm/WasmBuiltins.h index 1329b28a70b7..222a4ae57485 100644 --- a/js/src/wasm/WasmBuiltins.h +++ b/js/src/wasm/WasmBuiltins.h @@ -142,7 +142,7 @@ enum class SymbolicAddress { ArrayInitData, ArrayInitElem, ArrayCopy, -#define VISIT_BUILTIN_FUNC(op, export, sa_name, abitype, entry, idx) sa_name, +#define VISIT_BUILTIN_FUNC(op, export, sa_name, ...) sa_name, FOR_EACH_BUILTIN_MODULE_FUNC(VISIT_BUILTIN_FUNC) #undef VISIT_BUILTIN_FUNC #ifdef WASM_CODEGEN_DEBUG @@ -278,7 +278,7 @@ extern const SymbolicAddressSignature SASigArrayNewElem; extern const SymbolicAddressSignature SASigArrayInitData; extern const SymbolicAddressSignature SASigArrayInitElem; extern const SymbolicAddressSignature SASigArrayCopy; -#define VISIT_BUILTIN_FUNC(op, export, sa_name, abitype, entry, idx) \ +#define VISIT_BUILTIN_FUNC(op, export, sa_name, ...) \ extern const SymbolicAddressSignature SASig##sa_name; FOR_EACH_BUILTIN_MODULE_FUNC(VISIT_BUILTIN_FUNC) #undef VISIT_BUILTIN_FUNC diff --git a/js/src/wasm/WasmConstants.h b/js/src/wasm/WasmConstants.h index 05ac78048a03..a1f784179c61 100644 --- a/js/src/wasm/WasmConstants.h +++ b/js/src/wasm/WasmConstants.h @@ -956,7 +956,8 @@ enum class BuiltinModuleFuncId { // emitted internally when compiling intrinsic modules and are rejected by wasm // validation. // See wasm/WasmBuiltinModule.yaml for the list. -#define VISIT_BUILTIN_FUNC(op, export, sa_name, abitype, entry, idx) \ +#define VISIT_BUILTIN_FUNC(op, export, sa_name, abitype, entry, has_memory, \ + idx) \ op = idx, // NOLINT FOR_EACH_BUILTIN_MODULE_FUNC(VISIT_BUILTIN_FUNC) #undef VISIT_BUILTIN_FUNC diff --git a/js/src/wasm/WasmFrameIter.cpp b/js/src/wasm/WasmFrameIter.cpp index 96d21a3b6667..9e02fcea4951 100644 --- a/js/src/wasm/WasmFrameIter.cpp +++ b/js/src/wasm/WasmFrameIter.cpp @@ -1794,8 +1794,8 @@ static const char* ThunkedNativeToDescription(SymbolicAddress func) { return "call to native array.init_elem function"; case SymbolicAddress::ArrayCopy: return "call to native array.copy function"; -#define VISIT_BUILTIN_FUNC(op, export, sa_name, abitype, entry, idx) \ - case SymbolicAddress::sa_name: \ +#define VISIT_BUILTIN_FUNC(op, export, sa_name, ...) \ + case SymbolicAddress::sa_name: \ return "call to native " #op " builtin (in wasm)"; FOR_EACH_BUILTIN_MODULE_FUNC(VISIT_BUILTIN_FUNC) #undef VISIT_BUILTIN_FUNC diff --git a/js/src/wasm/WasmIonCompile.cpp b/js/src/wasm/WasmIonCompile.cpp index 9583bf07f305..88d6b3909dd9 100644 --- a/js/src/wasm/WasmIonCompile.cpp +++ b/js/src/wasm/WasmIonCompile.cpp @@ -7708,16 +7708,29 @@ static bool EmitCallBuiltinModuleFunc(FunctionCompiler& f) { return false; } - MDefinition* memoryBase = f.memoryBase(0); - if (!f.passArg(memoryBase, MIRType::Pointer, &args)) { - return false; + if (builtinModuleFunc->usesMemory) { + MDefinition* memoryBase = f.memoryBase(0); + if (!f.passArg(memoryBase, MIRType::Pointer, &args)) { + return false; + } } if (!f.finishCall(&args)) { return false; } - return f.builtinInstanceMethodCall(callee, bytecodeOffset, args); + bool hasResult = builtinModuleFunc->result.isSome(); + MDefinition* result = nullptr; + MDefinition** resultOutParam = hasResult ? &result : nullptr; + if (!f.builtinInstanceMethodCall(callee, bytecodeOffset, args, + resultOutParam)) { + return false; + } + + if (hasResult) { + f.iter().setResult(result); + } + return true; } static bool EmitBodyExprs(FunctionCompiler& f) { diff --git a/js/src/wasm/WasmJS.cpp b/js/src/wasm/WasmJS.cpp index 72935eb9a462..9e7691df810c 100644 --- a/js/src/wasm/WasmJS.cpp +++ b/js/src/wasm/WasmJS.cpp @@ -5158,7 +5158,7 @@ static bool WebAssembly_mozIntGemm(JSContext* cx, unsigned argc, Value* vp) { wasm::BuiltinModuleFuncId::I8PrepareBias, wasm::BuiltinModuleFuncId::I8MultiplyAndAddBias, wasm::BuiltinModuleFuncId::I8SelectColumnsOfB}; - if (!wasm::CompileBuiltinModule(cx, ids, Shareable::False, &module)) { + if (!wasm::CompileBuiltinModule(cx, ids, Some(Shareable::False), &module)) { ReportOutOfMemory(cx); return false; } diff --git a/js/src/wasm/WasmOpIter.h b/js/src/wasm/WasmOpIter.h index 5c1123aa44ec..7d1eedaadd21 100644 --- a/js/src/wasm/WasmOpIter.h +++ b/js/src/wasm/WasmOpIter.h @@ -4097,10 +4097,16 @@ inline bool OpIter::readCallBuiltinModuleFunc( *builtinModuleFunc = &BuiltinModuleFunc::getFromId(BuiltinModuleFuncId(id)); - if (env_.numMemories() == 0) { + if ((*builtinModuleFunc)->usesMemory && env_.numMemories() == 0) { return fail("can't touch memory without memory"); } - return popWithTypes((*builtinModuleFunc)->params, params); + if (!popWithTypes((*builtinModuleFunc)->params, params)) { + return false; + } + if ((*builtinModuleFunc)->result.isNothing()) { + return true; + } + return push(*(*builtinModuleFunc)->result); } } // namespace wasm diff --git a/js/src/wasm/WasmValType.h b/js/src/wasm/WasmValType.h index d9ec5e5576db..5d6c4c39ba05 100644 --- a/js/src/wasm/WasmValType.h +++ b/js/src/wasm/WasmValType.h @@ -112,11 +112,11 @@ union PackedTypeCode { static PackedTypeCode pack(TypeCode tc) { return pack(tc, nullptr, false); } - bool isValid() const { return typeCode_ != NoTypeCode; } + constexpr bool isValid() const { return typeCode_ != NoTypeCode; } PackedRepr bits() const { return bits_; } - TypeCode typeCode() const { + constexpr TypeCode typeCode() const { MOZ_ASSERT(isValid()); return TypeCode(typeCode_); } @@ -134,7 +134,7 @@ union PackedTypeCode { // what ValType needs, so that this decoding step is not necessary, but that // moves complexity elsewhere, and the perf gain here would be only about 1% // for baseline compilation throughput. - TypeCode typeCodeAbstracted() const { + constexpr TypeCode typeCodeAbstracted() const { TypeCode tc = typeCode(); return tc < LowestPrimitiveTypeCode ? AbstractReferenceTypeCode : tc; } @@ -634,6 +634,11 @@ class PackedType : public T { inline void AddRef() const; inline void Release() const; + static constexpr PackedType i32() { return PackedType(PackedType::I32); } + static constexpr PackedType f32() { return PackedType(PackedType::F32); } + static constexpr PackedType i64() { return PackedType(PackedType::I64); } + static constexpr PackedType f64() { return PackedType(PackedType::F64); } + static PackedType fromMIRType(jit::MIRType mty) { switch (mty) { case jit::MIRType::Int32: @@ -830,7 +835,7 @@ class PackedType : public T { // as a pointer. At the JS/wasm boundary, an AnyRef can be represented as a // JS::Value, and the type translation may have to be handled specially and on // a case-by-case basis. - jit::MIRType toMIRType() const { + constexpr jit::MIRType toMIRType() const { switch (tc_.typeCodeAbstracted()) { case TypeCode::I32: return jit::MIRType::Int32;