Diff
Modified: trunk/JSTests/ChangeLog (276895 => 276896)
--- trunk/JSTests/ChangeLog 2021-05-03 09:29:48 UTC (rev 276895)
+++ trunk/JSTests/ChangeLog 2021-05-03 11:00:43 UTC (rev 276896)
@@ -1,3 +1,23 @@
+2021-05-03 Dmitry Bezhetskov <[email protected]>
+
+ [WASM-Function-References] Add call_ref instruction
+ https://bugs.webkit.org/show_bug.cgi?id=222903
+
+ Reviewed by Yusuke Suzuki.
+
+ Add basic tests for new call_ref instruction:
+ https://github.com/WebAssembly/function-references/blob/master/proposals/function-references/Overview.md.
+ Add tests for calling same-instance wasm function, foreign-instance
+ wasm function and for calling imported js function.
+
+ * wasm.yaml:
+ * wasm/function-references/call_ref.js: Added.
+ (module):
+ (async basics):
+ (async indirectCall):
+ (async importHostCall):
+ * wasm/wasm.json:
+
2021-04-28 Mark Lam <[email protected]>
Fix exception assertions in light of the TerminationException.
Added: trunk/JSTests/wasm/function-references/call_ref.js (0 => 276896)
--- trunk/JSTests/wasm/function-references/call_ref.js (rev 0)
+++ trunk/JSTests/wasm/function-references/call_ref.js 2021-05-03 11:00:43 UTC (rev 276896)
@@ -0,0 +1,75 @@
+//@ runWebAssemblySuite("--useWebAssemblyTypedFunctionReferences=true")
+import * as assert from '../assert.js';
+import { instantiate } from "../wabt-wrapper.js";
+
+function module(bytes, valid = true) {
+ let buffer = new ArrayBuffer(bytes.length);
+ let view = new Uint8Array(buffer);
+ for (let i = 0; i < bytes.length; ++i) {
+ view[i] = bytes.charCodeAt(i);
+ }
+ return new WebAssembly.Module(buffer);
+}
+
+async function callFunctionFromTheSameInstance() {
+ /*
+ (module
+ (elem declare funcref (ref.func $foo))
+ (func $foo (param $x i32) (result i32)
+ (i32.add (local.get $x)
+ (i32.const 19)
+ )
+ )
+ (func (export "main") (result i32)
+ (call_ref (i32.const 10) (ref.func $foo))
+ )
+ )
+ */
+ let instance = new WebAssembly.Instance(module("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x0a\x02\x60\x01\x7f\x01\x7f\x60\x00\x01\x7f\x03\x03\x02\x00\x01\x07\x08\x01\x04\x6d\x61\x69\x6e\x00\x01\x09\x05\x01\x03\x00\x01\x00\x0a\x11\x02\x07\x00\x20\x00\x41\x13\x6a\x0b\x07\x00\x41\x0a\xd2\x00\x14\x0b"));
+ assert.eq(instance.exports.main(), 29);
+}
+
+async function callFunctionFromTheDifferentInstance() {
+ let wat = `
+ (module
+ (func (export "bar") (param $x i32) (result i32)
+ (i32.add (local.get $x)
+ (i32.const 19))
+ )
+ )`;
+ const barProvider = await instantiate(wat, {}, {reference_types: true});
+
+ /*
+ (module
+ (import "exports" "bar" (func $bar (param i32) (result i32)))
+ (elem declare funcref (ref.func $bar))
+ (func (export "main") (result i32)
+ (call_ref (i32.const 10) (ref.func $bar))
+ )
+ )
+ */
+ let instance = new WebAssembly.Instance(
+ module("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x0a\x02\x60\x01\x7f\x01\x7f\x60\x00\x01\x7f\x02\x0f\x01\x07\x65\x78\x70\x6f\x72\x74\x73\x03\x62\x61\x72\x00\x00\x03\x02\x01\x01\x07\x08\x01\x04\x6d\x61\x69\x6e\x00\x01\x09\x05\x01\x03\x00\x01\x00\x0a\x09\x01\x07\x00\x41\x0a\xd2\x00\x14\x0b"),
+ barProvider);
+ assert.eq(instance.exports.main(), 29);
+}
+
+async function callFunctionFromJS() {
+ /*
+ (module
+ (import "exports" "bar" (func $bar (param i32) (result i32)))
+ (elem declare funcref (ref.func $bar))
+ (func (export "main") (result i32)
+ (call_ref (i32.const 10) (ref.func $bar))
+ )
+ )
+ */
+ let instance = new WebAssembly.Instance(
+ module("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x0a\x02\x60\x01\x7f\x01\x7f\x60\x00\x01\x7f\x02\x0f\x01\x07\x65\x78\x70\x6f\x72\x74\x73\x03\x62\x61\x72\x00\x00\x03\x02\x01\x01\x07\x08\x01\x04\x6d\x61\x69\x6e\x00\x01\x09\x05\x01\x03\x00\x01\x00\x0a\x09\x01\x07\x00\x41\x0a\xd2\x00\x14\x0b"),
+ {exports: {bar : x => x + 19}});
+ assert.eq(instance.exports.main(), 29);
+}
+
+assert.asyncTest(callFunctionFromTheSameInstance());
+assert.asyncTest(callFunctionFromTheDifferentInstance());
+assert.asyncTest(callFunctionFromJS());
Modified: trunk/JSTests/wasm/wasm.json (276895 => 276896)
--- trunk/JSTests/wasm/wasm.json 2021-05-03 09:29:48 UTC (rev 276895)
+++ trunk/JSTests/wasm/wasm.json 2021-05-03 11:00:43 UTC (rev 276896)
@@ -85,6 +85,7 @@
"data.drop": { "category": "exttable", "value": 252, "return": [], "parameter": [], "immediate": [{"name": "segment_index", "type": "varuint32"}], "description": "shrinks the size of the segment to zero", "extendedOp": 9 },
"call": { "category": "call", "value": 16, "return": ["call"], "parameter": ["call"], "immediate": [{"name": "function_index", "type": "varuint32"}], "description": "call a function by its index" },
"call_indirect": { "category": "call", "value": 17, "return": ["call"], "parameter": ["call"], "immediate": [{"name": "type_index", "type": "varuint32"}, {"name": "table_index","type": "varuint32"}],"description": "call a function indirect with an expected signature" },
+ "call_ref": { "category": "call", "value": 20, "return": ["call"], "parameter": ["call"], "immediate": [], "description": "call a function reference" },
"i32.load8_s": { "category": "memory", "value": 44, "return": ["i32"], "parameter": ["addr"], "immediate": [{"name": "flags", "type": "varuint32"}, {"name": "offset", "type": "varuint32"}], "description": "load from memory" },
"i32.load8_u": { "category": "memory", "value": 45, "return": ["i32"], "parameter": ["addr"], "immediate": [{"name": "flags", "type": "varuint32"}, {"name": "offset", "type": "varuint32"}], "description": "load from memory" },
"i32.load16_s": { "category": "memory", "value": 46, "return": ["i32"], "parameter": ["addr"], "immediate": [{"name": "flags", "type": "varuint32"}, {"name": "offset", "type": "varuint32"}], "description": "load from memory" },
Modified: trunk/JSTests/wasm.yaml (276895 => 276896)
--- trunk/JSTests/wasm.yaml 2021-05-03 09:29:48 UTC (rev 276895)
+++ trunk/JSTests/wasm.yaml 2021-05-03 11:00:43 UTC (rev 276896)
@@ -33,6 +33,8 @@
cmd: runWebAssemblySuite unless parseRunCommands
- path: wasm/references
cmd: runWebAssemblySuite unless parseRunCommands
+- path: wasm/function-references
+ cmd: runWebAssemblySuite unless parseRunCommands
- path: wasm/fuzz
cmd: runWebAssemblySuite unless parseRunCommands
- path: wasm/lowExecutableMemory
Modified: trunk/Source/_javascript_Core/ChangeLog (276895 => 276896)
--- trunk/Source/_javascript_Core/ChangeLog 2021-05-03 09:29:48 UTC (rev 276895)
+++ trunk/Source/_javascript_Core/ChangeLog 2021-05-03 11:00:43 UTC (rev 276896)
@@ -1,3 +1,53 @@
+2021-05-03 Dmitry Bezhetskov <[email protected]>
+
+ [WASM-Function-References] Add call_ref instruction
+ https://bugs.webkit.org/show_bug.cgi?id=222903
+
+ Reviewed by Yusuke Suzuki.
+
+ Add support for call_ref instruction from the typed function
+ references proposal: https://github.com/WebAssembly/function-references/blob/master/proposals/function-references/Overview.md.
+ call_ref calls the given function references from the stack
+ and it does almost the same stuff as call_indirect but
+ it doesn't check signatures because wasm types system guaranties
+ correctness.
+
+ * bytecode/BytecodeList.rb:
+ * dfg/DFGCapabilities.cpp:
+ (JSC::DFG::capabilityLevel):
+ * llint/LowLevelInterpreter.asm:
+ * llint/WebAssembly.asm:
+ * runtime/Gate.h:
+ * wasm/WasmAirIRGenerator.cpp:
+ (JSC::Wasm::AirIRGenerator::addCallIndirect):
+ (JSC::Wasm::AirIRGenerator::addCallRef):
+ (JSC::Wasm::AirIRGenerator::emitIndirectCall):
+ * wasm/WasmB3IRGenerator.cpp:
+ (JSC::Wasm::B3IRGenerator::emitIndirectCall):
+ (JSC::Wasm::B3IRGenerator::addCallIndirect):
+ (JSC::Wasm::B3IRGenerator::addCallRef):
+ * wasm/WasmFunctionParser.h:
+ (JSC::Wasm::FunctionParser<Context>::parseExpression):
+ (JSC::Wasm::FunctionParser<Context>::parseUnreachableExpression):
+ * wasm/WasmLLIntGenerator.cpp:
+ (JSC::Wasm::LLIntGenerator::addCallRef):
+ * wasm/WasmSlowPaths.cpp:
+ (JSC::LLInt::doWasmCallRef):
+ (JSC::LLInt::WASM_SLOW_PATH_DECL):
+ * wasm/WasmSlowPaths.h:
+ * wasm/js/JSWebAssemblyTable.cpp:
+ * wasm/js/WebAssemblyFunction.cpp:
+ (JSC::WebAssemblyFunction::WebAssemblyFunction):
+ * wasm/js/WebAssemblyFunction.h:
+ * wasm/js/WebAssemblyFunctionBase.cpp:
+ (JSC::WebAssemblyFunctionBase::WebAssemblyFunctionBase):
+ * wasm/js/WebAssemblyFunctionBase.h:
+ (JSC::WebAssemblyFunctionBase::offsetOfEntrypointLoadLocation):
+ * wasm/js/WebAssemblyWrapperFunction.cpp:
+ (JSC::WebAssemblyWrapperFunction::WebAssemblyWrapperFunction):
+ * wasm/js/WebAssemblyWrapperFunction.h:
+ * wasm/wasm.json:
+
2021-05-01 Chris Dumez <[email protected]>
Start leveraging std::filesystem in WTF::FileSystem
Modified: trunk/Source/_javascript_Core/bytecode/BytecodeList.rb (276895 => 276896)
--- trunk/Source/_javascript_Core/bytecode/BytecodeList.rb 2021-05-03 09:29:48 UTC (rev 276895)
+++ trunk/Source/_javascript_Core/bytecode/BytecodeList.rb 2021-05-03 11:00:43 UTC (rev 276896)
@@ -1474,6 +1474,8 @@
op :wasm_trampoline_wasm_call_no_tls
op :wasm_trampoline_wasm_call_indirect
op :wasm_trampoline_wasm_call_indirect_no_tls
+op :wasm_trampoline_wasm_call_ref
+op :wasm_trampoline_wasm_call_ref_no_tls
end_section :NativeHelpers
@@ -1495,6 +1497,8 @@
op :call_no_tls_return_location
op :call_indirect_return_location
op :call_indirect_no_tls_return_location
+op :call_ref_return_location
+op :call_ref_no_tls_return_location
# FIXME: Wasm and JS LLInt should share common opcodes
# https://bugs.webkit.org/show_bug.cgi?id=203656
@@ -1686,6 +1690,22 @@
tableIndex: unsigned,
}
+op :call_ref,
+ args: {
+ functionReference: VirtualRegister,
+ signatureIndex: unsigned,
+ stackOffset: unsigned,
+ numberOfStackArgs: unsigned,
+ }
+
+op :call_ref_no_tls,
+ args: {
+ functionReference: VirtualRegister,
+ signatureIndex: unsigned,
+ stackOffset: unsigned,
+ numberOfStackArgs: unsigned,
+ }
+
op :current_memory,
args: {
dst: VirtualRegister,
Modified: trunk/Source/_javascript_Core/dfg/DFGCapabilities.cpp (276895 => 276896)
--- trunk/Source/_javascript_Core/dfg/DFGCapabilities.cpp 2021-05-03 09:29:48 UTC (rev 276895)
+++ trunk/Source/_javascript_Core/dfg/DFGCapabilities.cpp 2021-05-03 11:00:43 UTC (rev 276896)
@@ -368,6 +368,8 @@
case wasm_trampoline_wasm_call_no_tls:
case wasm_trampoline_wasm_call_indirect:
case wasm_trampoline_wasm_call_indirect_no_tls:
+ case wasm_trampoline_wasm_call_ref:
+ case wasm_trampoline_wasm_call_ref_no_tls:
return CannotCompile;
}
return CannotCompile;
Modified: trunk/Source/_javascript_Core/llint/LowLevelInterpreter.asm (276895 => 276896)
--- trunk/Source/_javascript_Core/llint/LowLevelInterpreter.asm 2021-05-03 09:29:48 UTC (rev 276895)
+++ trunk/Source/_javascript_Core/llint/LowLevelInterpreter.asm 2021-05-03 11:00:43 UTC (rev 276896)
@@ -2530,14 +2530,20 @@
_wasm_trampoline_wasm_call_no_tls:
_wasm_trampoline_wasm_call_indirect:
_wasm_trampoline_wasm_call_indirect_no_tls:
+_wasm_trampoline_wasm_call_ref:
+_wasm_trampoline_wasm_call_ref_no_tls:
_wasm_trampoline_wasm_call_wide16:
_wasm_trampoline_wasm_call_no_tls_wide16:
_wasm_trampoline_wasm_call_indirect_wide16:
_wasm_trampoline_wasm_call_indirect_no_tls_wide16:
+_wasm_trampoline_wasm_call_ref_wide16:
+_wasm_trampoline_wasm_call_ref_no_tls_wide16:
_wasm_trampoline_wasm_call_wide32:
_wasm_trampoline_wasm_call_no_tls_wide32:
_wasm_trampoline_wasm_call_indirect_wide32:
_wasm_trampoline_wasm_call_indirect_no_tls_wide32:
+_wasm_trampoline_wasm_call_ref_wide32:
+_wasm_trampoline_wasm_call_ref_no_tls_wide32:
crash()
end
Modified: trunk/Source/_javascript_Core/llint/WebAssembly.asm (276895 => 276896)
--- trunk/Source/_javascript_Core/llint/WebAssembly.asm 2021-05-03 09:29:48 UTC (rev 276895)
+++ trunk/Source/_javascript_Core/llint/WebAssembly.asm 2021-05-03 11:00:43 UTC (rev 276896)
@@ -877,6 +877,14 @@
slowPathForWasmCall(ctx, _slow_path_wasm_call_indirect_no_tls, macro(targetInstance) move targetInstance, wasmInstance end)
end)
+wasmOp(call_ref, WasmCallRef, macro(ctx)
+ slowPathForWasmCall(ctx, _slow_path_wasm_call_ref, storeWasmInstanceToTLS)
+end)
+
+wasmOp(call_ref_no_tls, WasmCallRefNoTls, macro(ctx)
+ slowPathForWasmCall(ctx, _slow_path_wasm_call_ref_no_tls, macro(targetInstance) move targetInstance, wasmInstance end)
+end)
+
wasmOp(current_memory, WasmCurrentMemory, macro(ctx)
loadp Wasm::Instance::m_memory[wasmInstance], t0
loadp Wasm::Memory::m_handle[t0], t0
Modified: trunk/Source/_javascript_Core/runtime/Gate.h (276895 => 276896)
--- trunk/Source/_javascript_Core/runtime/Gate.h 2021-05-03 09:29:48 UTC (rev 276895)
+++ trunk/Source/_javascript_Core/runtime/Gate.h 2021-05-03 11:00:43 UTC (rev 276896)
@@ -68,6 +68,8 @@
v(wasm_call_no_tls, JSEntrySlowPathPtrTag) \
v(wasm_call_indirect, JSEntrySlowPathPtrTag) \
v(wasm_call_indirect_no_tls, JSEntrySlowPathPtrTag) \
+ v(wasm_call_ref, JSEntrySlowPathPtrTag) \
+ v(wasm_call_ref_no_tls, JSEntrySlowPathPtrTag) \
#else
#define JSC_WASM_GATE_OPCODES(v)
Modified: trunk/Source/_javascript_Core/wasm/WasmAirIRGenerator.cpp (276895 => 276896)
--- trunk/Source/_javascript_Core/wasm/WasmAirIRGenerator.cpp 2021-05-03 09:29:48 UTC (rev 276895)
+++ trunk/Source/_javascript_Core/wasm/WasmAirIRGenerator.cpp 2021-05-03 11:00:43 UTC (rev 276896)
@@ -325,7 +325,9 @@
// Calls
PartialResult WARN_UNUSED_RETURN addCall(uint32_t calleeIndex, const Signature&, Vector<ExpressionType>& args, ResultList& results);
PartialResult WARN_UNUSED_RETURN addCallIndirect(unsigned tableIndex, const Signature&, Vector<ExpressionType>& args, ResultList& results);
+ PartialResult WARN_UNUSED_RETURN addCallRef(const Signature&, Vector<ExpressionType>& args, ResultList& results);
PartialResult WARN_UNUSED_RETURN addUnreachable();
+ PartialResult WARN_UNUSED_RETURN emitIndirectCall(TypedTmp calleeInstance, ExpressionType calleeCode, const Signature&, const Vector<ExpressionType>& args, ResultList&);
B3::PatchpointValue* WARN_UNUSED_RETURN emitCallPatchpoint(BasicBlock*, const Signature&, const ResultList& results, const Vector<TypedTmp>& args, Vector<ConstrainedTmp>&& extraArgs = { });
PartialResult addShift(Type, B3::Air::Opcode, ExpressionType value, ExpressionType shift, ExpressionType& result);
@@ -3273,9 +3275,6 @@
// can be to the embedder for our stack check calculation.
m_maxNumJSCallArguments = std::max(m_maxNumJSCallArguments, static_cast<uint32_t>(args.size()));
- auto currentInstance = g64();
- append(Move, instanceValue(), currentInstance);
-
ExpressionType callableFunctionBuffer = g64();
ExpressionType instancesBuffer = g64();
ExpressionType callableFunctionBufferLength = g64();
@@ -3340,15 +3339,42 @@
});
}
+ auto calleeInstance = g64();
+ append(Move, Arg::index(instancesBuffer, calleeIndex, 8, 0), calleeInstance);
+
+ return emitIndirectCall(calleeInstance, calleeCode, signature, args, results);
+}
+
+auto AirIRGenerator::addCallRef(const Signature& signature, Vector<ExpressionType>& args, ResultList& results) -> PartialResult
+{
+ m_makesCalls = true;
+ // Note: call ref can call either WebAssemblyFunction or WebAssemblyWrapperFunction. Because
+ // WebAssemblyWrapperFunction is like calling into the embedder, we conservatively assume all call indirects
+ // can be to the embedder for our stack check calculation.
+ ExpressionType calleeFunction = args.takeLast();
+ m_maxNumJSCallArguments = std::max(m_maxNumJSCallArguments, static_cast<uint32_t>(args.size()));
+
+ ExpressionType calleeCode = g64();
+ append(Move, Arg::addr(calleeFunction, WebAssemblyFunctionBase::offsetOfEntrypointLoadLocation()), calleeCode); // Pointer to callee code.
+
+ auto calleeInstance = g64();
+ append(Move, Arg::addr(calleeFunction, WebAssemblyFunctionBase::offsetOfInstance()), calleeInstance);
+ append(Move, Arg::addr(calleeInstance, JSWebAssemblyInstance::offsetOfInstance()), calleeInstance);
+
+ return emitIndirectCall(calleeInstance, calleeCode, signature, args, results);
+}
+
+auto AirIRGenerator::emitIndirectCall(TypedTmp calleeInstance, ExpressionType calleeCode, const Signature& signature, const Vector<ExpressionType>& args, ResultList& results) -> PartialResult
+{
+ auto currentInstance = g64();
+ append(Move, instanceValue(), currentInstance);
+
// Do a context switch if needed.
{
- auto newContextInstance = g64();
- append(Move, Arg::index(instancesBuffer, calleeIndex, 8, 0), newContextInstance);
-
BasicBlock* doContextSwitch = m_code.addBlock();
BasicBlock* continuation = m_code.addBlock();
- append(Branch64, Arg::relCond(MacroAssembler::Equal), newContextInstance, instanceValue());
+ append(Branch64, Arg::relCond(MacroAssembler::Equal), calleeInstance, currentInstance);
m_currentBlock->setSuccessors(continuation, doContextSwitch);
auto* patchpoint = addPatchpoint(B3::Void);
@@ -3361,26 +3387,26 @@
patchpoint->setGenerator([=] (CCallHelpers& jit, const B3::StackmapGenerationParams& params) {
AllowMacroScratchRegisterUsage allowScratch(jit);
- GPRReg newContextInstance = params[0].gpr();
+ GPRReg calleeInstance = params[0].gpr();
GPRReg oldContextInstance = params[1].gpr();
const PinnedRegisterInfo& pinnedRegs = PinnedRegisterInfo::get();
GPRReg baseMemory = pinnedRegs.baseMemoryPointer;
- ASSERT(newContextInstance != baseMemory);
+ ASSERT(calleeInstance != baseMemory);
jit.loadPtr(CCallHelpers::Address(oldContextInstance, Instance::offsetOfCachedStackLimit()), baseMemory);
- jit.storePtr(baseMemory, CCallHelpers::Address(newContextInstance, Instance::offsetOfCachedStackLimit()));
- jit.storeWasmContextInstance(newContextInstance);
+ jit.storePtr(baseMemory, CCallHelpers::Address(calleeInstance, Instance::offsetOfCachedStackLimit()));
+ jit.storeWasmContextInstance(calleeInstance);
// FIXME: We should support more than one memory size register
// see: https://bugs.webkit.org/show_bug.cgi?id=162952
- ASSERT(pinnedRegs.boundsCheckingSizeRegister != newContextInstance);
+ ASSERT(pinnedRegs.boundsCheckingSizeRegister != calleeInstance);
GPRReg scratch = params.gpScratch(0);
- jit.loadPtr(CCallHelpers::Address(newContextInstance, Instance::offsetOfCachedBoundsCheckingSize()), pinnedRegs.boundsCheckingSizeRegister); // Bound checking size.
- jit.loadPtr(CCallHelpers::Address(newContextInstance, Instance::offsetOfCachedMemory()), baseMemory); // Memory::void*.
+ jit.loadPtr(CCallHelpers::Address(calleeInstance, Instance::offsetOfCachedBoundsCheckingSize()), pinnedRegs.boundsCheckingSizeRegister); // Bound checking size.
+ jit.loadPtr(CCallHelpers::Address(calleeInstance, Instance::offsetOfCachedMemory()), baseMemory); // Memory::void*.
jit.cageConditionallyAndUntag(Gigacage::Primitive, baseMemory, pinnedRegs.boundsCheckingSizeRegister, scratch);
});
- emitPatchpoint(doContextSwitch, patchpoint, Tmp(), newContextInstance, instanceValue());
+ emitPatchpoint(doContextSwitch, patchpoint, Tmp(), calleeInstance, currentInstance);
append(doContextSwitch, Jump);
doContextSwitch->setSuccessors(continuation);
Modified: trunk/Source/_javascript_Core/wasm/WasmB3IRGenerator.cpp (276895 => 276896)
--- trunk/Source/_javascript_Core/wasm/WasmB3IRGenerator.cpp 2021-05-03 09:29:48 UTC (rev 276895)
+++ trunk/Source/_javascript_Core/wasm/WasmB3IRGenerator.cpp 2021-05-03 11:00:43 UTC (rev 276896)
@@ -285,7 +285,9 @@
// Calls
PartialResult WARN_UNUSED_RETURN addCall(uint32_t calleeIndex, const Signature&, Vector<ExpressionType>& args, ResultList& results);
PartialResult WARN_UNUSED_RETURN addCallIndirect(unsigned tableIndex, const Signature&, Vector<ExpressionType>& args, ResultList& results);
+ PartialResult WARN_UNUSED_RETURN addCallRef(const Signature&, Vector<ExpressionType>& args, ResultList& results);
PartialResult WARN_UNUSED_RETURN addUnreachable();
+ PartialResult WARN_UNUSED_RETURN emitIndirectCall(Value* calleeInstance, ExpressionType calleeCode, const Signature&, Vector<ExpressionType>& args, ResultList&);
B3::Value* createCallPatchpoint(BasicBlock*, Origin, const Signature&, Vector<ExpressionType>& args, const ScopedLambda<void(PatchpointValue*)>& patchpointFunctor);
void dump(const ControlStack&, const Stack* expressionStack);
@@ -866,6 +868,95 @@
return { };
}
+auto B3IRGenerator::emitIndirectCall(Value* calleeInstance, ExpressionType calleeCode, const Signature& signature, Vector<ExpressionType>& args, ResultList& results) -> PartialResult
+{
+ // Do a context switch if needed.
+ {
+ BasicBlock* continuation = m_proc.addBlock();
+ BasicBlock* doContextSwitch = m_proc.addBlock();
+
+ Value* isSameContextInstance = m_currentBlock->appendNew<Value>(m_proc, Equal, origin(),
+ calleeInstance, instanceValue());
+ m_currentBlock->appendNewControlValue(m_proc, B3::Branch, origin(),
+ isSameContextInstance, FrequentedBlock(continuation), FrequentedBlock(doContextSwitch));
+
+ PatchpointValue* patchpoint = doContextSwitch->appendNew<PatchpointValue>(m_proc, B3::Void, origin());
+ patchpoint->effects.writesPinned = true;
+ // We pessimistically assume we're calling something with BoundsChecking memory.
+ // FIXME: We shouldn't have to do this: https://bugs.webkit.org/show_bug.cgi?id=172181
+ patchpoint->clobber(PinnedRegisterInfo::get().toSave(MemoryMode::BoundsChecking));
+ patchpoint->clobber(RegisterSet::macroScratchRegisters());
+ patchpoint->append(calleeInstance, ValueRep::SomeRegister);
+ patchpoint->append(instanceValue(), ValueRep::SomeRegister);
+ patchpoint->numGPScratchRegisters = 1;
+
+ patchpoint->setGenerator([=] (CCallHelpers& jit, const B3::StackmapGenerationParams& params) {
+ AllowMacroScratchRegisterUsage allowScratch(jit);
+ GPRReg calleeInstance = params[0].gpr();
+ GPRReg oldContextInstance = params[1].gpr();
+ const PinnedRegisterInfo& pinnedRegs = PinnedRegisterInfo::get();
+ GPRReg baseMemory = pinnedRegs.baseMemoryPointer;
+ ASSERT(calleeInstance != baseMemory);
+ jit.loadPtr(CCallHelpers::Address(oldContextInstance, Instance::offsetOfCachedStackLimit()), baseMemory);
+ jit.storePtr(baseMemory, CCallHelpers::Address(calleeInstance, Instance::offsetOfCachedStackLimit()));
+ jit.storeWasmContextInstance(calleeInstance);
+ ASSERT(pinnedRegs.boundsCheckingSizeRegister != baseMemory);
+ // FIXME: We should support more than one memory size register
+ // see: https://bugs.webkit.org/show_bug.cgi?id=162952
+ ASSERT(pinnedRegs.boundsCheckingSizeRegister != calleeInstance);
+ GPRReg scratch = params.gpScratch(0);
+
+ jit.loadPtr(CCallHelpers::Address(calleeInstance, Instance::offsetOfCachedBoundsCheckingSize()), pinnedRegs.boundsCheckingSizeRegister); // Memory size.
+ jit.loadPtr(CCallHelpers::Address(calleeInstance, Instance::offsetOfCachedMemory()), baseMemory); // Memory::void*.
+
+ jit.cageConditionallyAndUntag(Gigacage::Primitive, baseMemory, pinnedRegs.boundsCheckingSizeRegister, scratch);
+ });
+ doContextSwitch->appendNewControlValue(m_proc, Jump, origin(), continuation);
+
+ m_currentBlock = continuation;
+ }
+
+ B3::Type returnType = toB3ResultType(&signature);
+ ExpressionType callResult = createCallPatchpoint(m_currentBlock, origin(), signature, args,
+ scopedLambdaRef<void(PatchpointValue*)>([=] (PatchpointValue* patchpoint) -> void {
+ patchpoint->effects.writesPinned = true;
+ patchpoint->effects.readsPinned = true;
+ // We need to clobber all potential pinned registers since we might be leaving the instance.
+ // We pessimistically assume we're always calling something that is bounds checking so
+ // because the wasm->wasm thunk unconditionally overrides the size registers.
+ // FIXME: We should not have to do this, but the wasm->wasm stub assumes it can
+ // use all the pinned registers as scratch: https://bugs.webkit.org/show_bug.cgi?id=172181
+ patchpoint->clobberLate(PinnedRegisterInfo::get().toSave(MemoryMode::BoundsChecking));
+
+ patchpoint->append(calleeCode, ValueRep::SomeRegister);
+ patchpoint->setGenerator([=] (CCallHelpers& jit, const B3::StackmapGenerationParams& params) {
+ AllowMacroScratchRegisterUsage allowScratch(jit);
+ jit.call(params[params.proc().resultCount(returnType)].gpr(), WasmEntryPtrTag);
+ });
+ }));
+
+ switch (returnType.kind()) {
+ case B3::Void: {
+ break;
+ }
+ case B3::Tuple: {
+ const Vector<B3::Type>& tuple = m_proc.tupleForType(returnType);
+ for (unsigned i = 0; i < signature.returnCount(); ++i)
+ results.append(m_currentBlock->appendNew<ExtractValue>(m_proc, origin(), tuple[i], callResult, i));
+ break;
+ }
+ default: {
+ results.append(callResult);
+ break;
+ }
+ }
+
+ // The call could have been to another WebAssembly instance, and / or could have modified our Memory.
+ restoreWebAssemblyGlobalState(RestoreCachedStackLimit::Yes, m_info.memory, instanceValue(), m_proc, m_currentBlock);
+
+ return { };
+}
+
auto B3IRGenerator::addGrowMemory(ExpressionType delta, ExpressionType& result) -> PartialResult
{
result = m_currentBlock->appendNew<CCallValue>(m_proc, Int32, origin(),
@@ -2521,100 +2612,41 @@
}
}
- // Do a context switch if needed.
- {
- Value* offset = m_currentBlock->appendNew<Value>(m_proc, Mul, origin(),
- calleeIndex, constant(pointerType(), sizeof(Instance*)));
- Value* newContextInstance = m_currentBlock->appendNew<MemoryValue>(m_proc, Load, pointerType(), origin(),
- m_currentBlock->appendNew<Value>(m_proc, Add, origin(), instancesBuffer, offset));
+ Value* offset = m_currentBlock->appendNew<Value>(m_proc, Mul, origin(),
+ calleeIndex, constant(pointerType(), sizeof(Instance*)));
+ Value* calleeInstance = m_currentBlock->appendNew<MemoryValue>(m_proc, Load, pointerType(), origin(),
+ m_currentBlock->appendNew<Value>(m_proc, Add, origin(), instancesBuffer, offset));
+ ExpressionType calleeCode = m_currentBlock->appendNew<MemoryValue>(m_proc, Load, pointerType(), origin(),
+ m_currentBlock->appendNew<MemoryValue>(m_proc, Load, pointerType(), origin(), callableFunction,
+ safeCast<int32_t>(WasmToWasmImportableFunction::offsetOfEntrypointLoadLocation())));
- BasicBlock* continuation = m_proc.addBlock();
- BasicBlock* doContextSwitch = m_proc.addBlock();
+ return emitIndirectCall(calleeInstance, calleeCode, signature, args, results);
+}
- Value* isSameContextInstance = m_currentBlock->appendNew<Value>(m_proc, Equal, origin(),
- newContextInstance, instanceValue());
- m_currentBlock->appendNewControlValue(m_proc, B3::Branch, origin(),
- isSameContextInstance, FrequentedBlock(continuation), FrequentedBlock(doContextSwitch));
+auto B3IRGenerator::addCallRef(const Signature& signature, Vector<ExpressionType>& args, ResultList& results) -> PartialResult
+{
+ ExpressionType callee = args.takeLast();
+ ASSERT(signature.argumentCount() == args.size());
+ m_makesCalls = true;
- PatchpointValue* patchpoint = doContextSwitch->appendNew<PatchpointValue>(m_proc, B3::Void, origin());
- patchpoint->effects.writesPinned = true;
- // We pessimistically assume we're calling something with BoundsChecking memory.
- // FIXME: We shouldn't have to do this: https://bugs.webkit.org/show_bug.cgi?id=172181
- patchpoint->clobber(PinnedRegisterInfo::get().toSave(MemoryMode::BoundsChecking));
- patchpoint->clobber(RegisterSet::macroScratchRegisters());
- patchpoint->append(newContextInstance, ValueRep::SomeRegister);
- patchpoint->append(instanceValue(), ValueRep::SomeRegister);
- patchpoint->numGPScratchRegisters = 1;
+ // Note: call ref can call either WebAssemblyFunction or WebAssemblyWrapperFunction. Because
+ // WebAssemblyWrapperFunction is like calling into the embedder, we conservatively assume all call indirects
+ // can be to the embedder for our stack check calculation.
+ m_maxNumJSCallArguments = std::max(m_maxNumJSCallArguments, static_cast<uint32_t>(args.size()));
- patchpoint->setGenerator([=] (CCallHelpers& jit, const B3::StackmapGenerationParams& params) {
- AllowMacroScratchRegisterUsage allowScratch(jit);
- GPRReg newContextInstance = params[0].gpr();
- GPRReg oldContextInstance = params[1].gpr();
- const PinnedRegisterInfo& pinnedRegs = PinnedRegisterInfo::get();
- GPRReg baseMemory = pinnedRegs.baseMemoryPointer;
- ASSERT(newContextInstance != baseMemory);
- jit.loadPtr(CCallHelpers::Address(oldContextInstance, Instance::offsetOfCachedStackLimit()), baseMemory);
- jit.storePtr(baseMemory, CCallHelpers::Address(newContextInstance, Instance::offsetOfCachedStackLimit()));
- jit.storeWasmContextInstance(newContextInstance);
- ASSERT(pinnedRegs.boundsCheckingSizeRegister != baseMemory);
- // FIXME: We should support more than one memory size register
- // see: https://bugs.webkit.org/show_bug.cgi?id=162952
- ASSERT(pinnedRegs.boundsCheckingSizeRegister != newContextInstance);
- GPRReg scratch = params.gpScratch(0);
+ Value* jsInstanceOffset = constant(pointerType(), safeCast<int32_t>(WebAssemblyFunctionBase::offsetOfInstance()));
+ Value* jsCalleeInstance = m_currentBlock->appendNew<MemoryValue>(m_proc, Load, pointerType(), origin(),
+ m_currentBlock->appendNew<Value>(m_proc, Add, origin(), callee, jsInstanceOffset));
- jit.loadPtr(CCallHelpers::Address(newContextInstance, Instance::offsetOfCachedBoundsCheckingSize()), pinnedRegs.boundsCheckingSizeRegister); // Memory size.
- jit.loadPtr(CCallHelpers::Address(newContextInstance, Instance::offsetOfCachedMemory()), baseMemory); // Memory::void*.
+ Value* instanceOffset = constant(pointerType(), safeCast<int32_t>(JSWebAssemblyInstance::offsetOfInstance()));
+ Value* calleeInstance = m_currentBlock->appendNew<MemoryValue>(m_proc, Load, pointerType(), origin(),
+ m_currentBlock->appendNew<Value>(m_proc, Add, origin(), jsCalleeInstance, instanceOffset));
- jit.cageConditionallyAndUntag(Gigacage::Primitive, baseMemory, pinnedRegs.boundsCheckingSizeRegister, scratch);
- });
- doContextSwitch->appendNewControlValue(m_proc, Jump, origin(), continuation);
-
- m_currentBlock = continuation;
- }
-
ExpressionType calleeCode = m_currentBlock->appendNew<MemoryValue>(m_proc, Load, pointerType(), origin(),
- m_currentBlock->appendNew<MemoryValue>(m_proc, Load, pointerType(), origin(), callableFunction,
- safeCast<int32_t>(WasmToWasmImportableFunction::offsetOfEntrypointLoadLocation())));
+ m_currentBlock->appendNew<MemoryValue>(m_proc, Load, pointerType(), origin(), callee,
+ safeCast<int32_t>(WebAssemblyFunctionBase::offsetOfEntrypointLoadLocation())));
- B3::Type returnType = toB3ResultType(&signature);
- ExpressionType callResult = createCallPatchpoint(m_currentBlock, origin(), signature, args,
- scopedLambdaRef<void(PatchpointValue*)>([=] (PatchpointValue* patchpoint) -> void {
- patchpoint->effects.writesPinned = true;
- patchpoint->effects.readsPinned = true;
- // We need to clobber all potential pinned registers since we might be leaving the instance.
- // We pessimistically assume we're always calling something that is bounds checking so
- // because the wasm->wasm thunk unconditionally overrides the size registers.
- // FIXME: We should not have to do this, but the wasm->wasm stub assumes it can
- // use all the pinned registers as scratch: https://bugs.webkit.org/show_bug.cgi?id=172181
- patchpoint->clobberLate(PinnedRegisterInfo::get().toSave(MemoryMode::BoundsChecking));
-
- patchpoint->append(calleeCode, ValueRep::SomeRegister);
- patchpoint->setGenerator([=] (CCallHelpers& jit, const B3::StackmapGenerationParams& params) {
- AllowMacroScratchRegisterUsage allowScratch(jit);
- jit.call(params[params.proc().resultCount(returnType)].gpr(), WasmEntryPtrTag);
- });
- }));
-
- switch (returnType.kind()) {
- case B3::Void: {
- break;
- }
- case B3::Tuple: {
- const Vector<B3::Type>& tuple = m_proc.tupleForType(returnType);
- for (unsigned i = 0; i < signature.returnCount(); ++i)
- results.append(m_currentBlock->appendNew<ExtractValue>(m_proc, origin(), tuple[i], callResult, i));
- break;
- }
- default: {
- results.append(callResult);
- break;
- }
- }
-
- // The call could have been to another WebAssembly instance, and / or could have modified our Memory.
- restoreWebAssemblyGlobalState(RestoreCachedStackLimit::Yes, m_info.memory, instanceValue(), m_proc, m_currentBlock);
-
- return { };
+ return emitIndirectCall(calleeInstance, calleeCode, signature, args, results);
}
void B3IRGenerator::unify(const ExpressionType phi, const ExpressionType source)
Modified: trunk/Source/_javascript_Core/wasm/WasmFunctionParser.h (276895 => 276896)
--- trunk/Source/_javascript_Core/wasm/WasmFunctionParser.h 2021-05-03 09:29:48 UTC (rev 276895)
+++ trunk/Source/_javascript_Core/wasm/WasmFunctionParser.h 2021-05-03 11:00:43 UTC (rev 276896)
@@ -1248,6 +1248,37 @@
return { };
}
+
+ case CallRef: {
+ WASM_PARSER_FAIL_IF(!Options::useWebAssemblyTypedFunctionReferences(), "function references are not enabled");
+ WASM_VALIDATOR_FAIL_IF(!m_expressionStack.last().type().isTypeIdx(), "non-funcref call_ref value ", m_expressionStack.last().type().kind);
+
+ const SignatureIndex calleeSignatureIndex = m_expressionStack.last().type().index;
+ const Signature& calleeSignature = SignatureInformation::get(calleeSignatureIndex);
+ size_t argumentCount = calleeSignature.argumentCount() + 1; // Add the callee's value.
+ WASM_PARSER_FAIL_IF(argumentCount > m_expressionStack.size(), "call_ref expects ", argumentCount, " arguments, but the _expression_ stack currently holds ", m_expressionStack.size(), " values");
+
+ Vector<ExpressionType> args;
+ WASM_PARSER_FAIL_IF(!args.tryReserveCapacity(argumentCount + 1), "can't allocate enough memory for ", argumentCount, " call_indirect arguments");
+ size_t firstArgumentIndex = m_expressionStack.size() - argumentCount;
+ for (size_t i = firstArgumentIndex; i < m_expressionStack.size(); ++i) {
+ TypedExpression arg = m_expressionStack.at(i);
+ if (i < m_expressionStack.size() - 1)
+ WASM_VALIDATOR_FAIL_IF(arg.type() != calleeSignature.argument(i - firstArgumentIndex), "argument type mismatch in call_indirect, got ", arg.type().kind, ", expected ", calleeSignature.argument(i - firstArgumentIndex).kind);
+ args.uncheckedAppend(arg);
+ m_context.didPopValueFromStack();
+ }
+ m_expressionStack.shrink(firstArgumentIndex);
+
+ ResultList results;
+ WASM_TRY_ADD_TO_CONTEXT(addCallRef(calleeSignature, args, results));
+
+ for (unsigned i = 0; i < calleeSignature.returnCount(); ++i)
+ m_expressionStack.constructAndAppend(calleeSignature.returnType(i), results[i]);
+
+ return { };
+ }
+
case Block: {
BlockSignature inlineSignature;
WASM_PARSER_FAIL_IF(!parseBlockSignature(m_info, inlineSignature), "can't get block's signature");
@@ -1739,6 +1770,7 @@
// no immediate cases
FOR_EACH_WASM_BINARY_OP(CREATE_CASE)
FOR_EACH_WASM_UNARY_OP(CREATE_CASE)
+ case CallRef:
case Unreachable:
case Nop:
case Return:
Modified: trunk/Source/_javascript_Core/wasm/WasmLLIntGenerator.cpp (276895 => 276896)
--- trunk/Source/_javascript_Core/wasm/WasmLLIntGenerator.cpp 2021-05-03 09:29:48 UTC (rev 276895)
+++ trunk/Source/_javascript_Core/wasm/WasmLLIntGenerator.cpp 2021-05-03 11:00:43 UTC (rev 276896)
@@ -253,6 +253,7 @@
// Calls
PartialResult WARN_UNUSED_RETURN addCall(uint32_t calleeIndex, const Signature&, Vector<ExpressionType>& args, ResultList& results);
PartialResult WARN_UNUSED_RETURN addCallIndirect(unsigned tableIndex, const Signature&, Vector<ExpressionType>& args, ResultList& results);
+ PartialResult WARN_UNUSED_RETURN addCallRef(const Signature&, Vector<ExpressionType>& args, ResultList& results);
PartialResult WARN_UNUSED_RETURN addUnreachable();
void didFinishParsingLocals();
@@ -1104,6 +1105,21 @@
return { };
}
+auto LLIntGenerator::addCallRef(const Signature& signature, Vector<ExpressionType>& args, ResultList& results) -> PartialResult
+{
+ ExpressionType callee = args.takeLast();
+
+ LLIntCallInformation info = callInformationForCaller(signature);
+ unifyValuesWithBlock(info.arguments, args);
+ if (Context::useFastTLS())
+ WasmCallRef::emit(this, callee, m_codeBlock->addSignature(signature), info.stackOffset, info.numberOfStackArguments);
+ else
+ WasmCallRefNoTls::emit(this, callee, m_codeBlock->addSignature(signature), info.stackOffset, info.numberOfStackArguments);
+ info.commitResults(results);
+
+ return { };
+}
+
auto LLIntGenerator::addRefIsNull(ExpressionType value, ExpressionType& result) -> PartialResult
{
result = push();
Modified: trunk/Source/_javascript_Core/wasm/WasmSlowPaths.cpp (276895 => 276896)
--- trunk/Source/_javascript_Core/wasm/WasmSlowPaths.cpp 2021-05-03 09:29:48 UTC (rev 276895)
+++ trunk/Source/_javascript_Core/wasm/WasmSlowPaths.cpp 2021-05-03 11:00:43 UTC (rev 276896)
@@ -29,6 +29,7 @@
#if ENABLE(WEBASSEMBLY)
#include "BytecodeStructs.h"
+#include "JSWebAssemblyInstance.h"
#include "LLIntData.h"
#include "WasmBBQPlan.h"
#include "WasmCallee.h"
@@ -40,6 +41,7 @@
#include "WasmOperations.h"
#include "WasmSignatureInlines.h"
#include "WasmWorklist.h"
+#include "WebAssemblyFunction.h"
namespace JSC { namespace LLInt {
@@ -498,6 +500,40 @@
return doWasmCallIndirect(callFrame, instance, functionIndex, instruction.m_tableIndex, instruction.m_signatureIndex);
}
+inline SlowPathReturnType doWasmCallRef(CallFrame* callFrame, Wasm::Instance* callerInstance, JSValue targetReference, unsigned signatureIndex)
+{
+ UNUSED_PARAM(callFrame);
+
+ ASSERT(targetReference.isObject());
+ JSObject* referenceAsObject = jsCast<JSObject*>(targetReference);
+
+ ASSERT(referenceAsObject->inherits<WebAssemblyFunctionBase>(callerInstance->owner<JSObject>()->vm()));
+ auto* wasmFunction = jsCast<WebAssemblyFunctionBase*>(referenceAsObject);
+ Wasm::WasmToWasmImportableFunction function = wasmFunction->importableFunction();
+ Wasm::Instance* calleeInstance = &wasmFunction->instance()->instance();
+
+ if (calleeInstance != callerInstance)
+ calleeInstance->setCachedStackLimit(callerInstance->cachedStackLimit());
+
+ ASSERT(function.signatureIndex == Wasm::SignatureInformation::get(CODE_BLOCK()->signature(signatureIndex)));
+ UNUSED_PARAM(signatureIndex);
+ WASM_CALL_RETURN(calleeInstance, function.entrypointLoadLocation->executableAddress(), WasmEntryPtrTag);
+}
+
+WASM_SLOW_PATH_DECL(call_ref)
+{
+ auto instruction = pc->as<WasmCallRef, WasmOpcodeTraits>();
+ JSValue reference = JSValue::decode(READ(instruction.m_functionReference).encodedJSValue());
+ return doWasmCallRef(callFrame, instance, reference, instruction.m_signatureIndex);
+}
+
+WASM_SLOW_PATH_DECL(call_ref_no_tls)
+{
+ auto instruction = pc->as<WasmCallRefNoTls, WasmOpcodeTraits>();
+ JSValue reference = JSValue::decode(READ(instruction.m_functionReference).encodedJSValue());
+ return doWasmCallRef(callFrame, instance, reference, instruction.m_signatureIndex);
+}
+
WASM_SLOW_PATH_DECL(set_global_ref)
{
auto instruction = pc->as<WasmSetGlobalRef, WasmOpcodeTraits>();
Modified: trunk/Source/_javascript_Core/wasm/WasmSlowPaths.h (276895 => 276896)
--- trunk/Source/_javascript_Core/wasm/WasmSlowPaths.h 2021-05-03 09:29:48 UTC (rev 276895)
+++ trunk/Source/_javascript_Core/wasm/WasmSlowPaths.h 2021-05-03 11:00:43 UTC (rev 276896)
@@ -76,6 +76,8 @@
WASM_SLOW_PATH_HIDDEN_DECL(call_no_tls);
WASM_SLOW_PATH_HIDDEN_DECL(call_indirect);
WASM_SLOW_PATH_HIDDEN_DECL(call_indirect_no_tls);
+WASM_SLOW_PATH_HIDDEN_DECL(call_ref);
+WASM_SLOW_PATH_HIDDEN_DECL(call_ref_no_tls);
WASM_SLOW_PATH_HIDDEN_DECL(set_global_ref);
WASM_SLOW_PATH_HIDDEN_DECL(set_global_ref_portable_binding);
WASM_SLOW_PATH_HIDDEN_DECL(memory_atomic_wait32);
Modified: trunk/Source/_javascript_Core/wasm/js/JSWebAssemblyTable.cpp (276895 => 276896)
--- trunk/Source/_javascript_Core/wasm/js/JSWebAssemblyTable.cpp 2021-05-03 09:29:48 UTC (rev 276895)
+++ trunk/Source/_javascript_Core/wasm/js/JSWebAssemblyTable.cpp 2021-05-03 11:00:43 UTC (rev 276896)
@@ -105,7 +105,7 @@
m_table->set(index, value);
}
-void JSWebAssemblyTable::set(uint32_t index, WebAssemblyFunction* function)
+void JSWebAssemblyTable::set(uint32_t index, WebAssemblyFunctionBase* function)
{
RELEASE_ASSERT(index < length());
RELEASE_ASSERT(m_table->asFuncrefTable());
@@ -113,14 +113,6 @@
subThis.setFunction(index, function, function->importableFunction(), &function->instance()->instance());
}
-void JSWebAssemblyTable::set(uint32_t index, WebAssemblyWrapperFunction* function)
-{
- RELEASE_ASSERT(index < length());
- RELEASE_ASSERT(m_table->asFuncrefTable());
- auto& subThis = *static_cast<Wasm::FuncRefTable*>(&m_table.get());
- subThis.setFunction(index, function, function->importableFunction(), &function->instance()->instance());
-}
-
void JSWebAssemblyTable::clear(uint32_t index)
{
RELEASE_ASSERT(index < length());
Modified: trunk/Source/_javascript_Core/wasm/js/JSWebAssemblyTable.h (276895 => 276896)
--- trunk/Source/_javascript_Core/wasm/js/JSWebAssemblyTable.h 2021-05-03 09:29:48 UTC (rev 276895)
+++ trunk/Source/_javascript_Core/wasm/js/JSWebAssemblyTable.h 2021-05-03 11:00:43 UTC (rev 276896)
@@ -60,8 +60,7 @@
uint32_t allocatedLength() const { return m_table->allocatedLength(length()); }
bool grow(uint32_t delta, JSValue defaultValue) WARN_UNUSED_RETURN;
JSValue get(uint32_t);
- void set(uint32_t, WebAssemblyFunction*);
- void set(uint32_t, WebAssemblyWrapperFunction*);
+ void set(uint32_t, WebAssemblyFunctionBase*);
void set(uint32_t, JSValue);
void clear(uint32_t);
JSObject* type(JSGlobalObject*);
Modified: trunk/Source/_javascript_Core/wasm/js/WebAssemblyFunction.cpp (276895 => 276896)
--- trunk/Source/_javascript_Core/wasm/js/WebAssemblyFunction.cpp 2021-05-03 09:29:48 UTC (rev 276895)
+++ trunk/Source/_javascript_Core/wasm/js/WebAssemblyFunction.cpp 2021-05-03 11:00:43 UTC (rev 276896)
@@ -454,9 +454,8 @@
}
WebAssemblyFunction::WebAssemblyFunction(VM& vm, NativeExecutable* executable, JSGlobalObject* globalObject, Structure* structure, Wasm::Callee& jsEntrypoint, Wasm::WasmToWasmImportableFunction::LoadLocation wasmToWasmEntrypointLoadLocation, Wasm::SignatureIndex signatureIndex)
- : Base { vm, executable, globalObject, structure }
+ : Base { vm, executable, globalObject, structure, Wasm::WasmToWasmImportableFunction { signatureIndex, wasmToWasmEntrypointLoadLocation } }
, m_jsEntrypoint { jsEntrypoint.entrypoint() }
- , m_importableFunction { signatureIndex, wasmToWasmEntrypointLoadLocation }
{ }
template<typename Visitor>
Modified: trunk/Source/_javascript_Core/wasm/js/WebAssemblyFunction.h (276895 => 276896)
--- trunk/Source/_javascript_Core/wasm/js/WebAssemblyFunction.h 2021-05-03 09:29:48 UTC (rev 276895)
+++ trunk/Source/_javascript_Core/wasm/js/WebAssemblyFunction.h 2021-05-03 11:00:43 UTC (rev 276896)
@@ -39,7 +39,6 @@
class JSGlobalObject;
struct ProtoCallFrame;
class WebAssemblyInstance;
-using Wasm::WasmToWasmImportableFunction;
class WebAssemblyFunction final : public WebAssemblyFunctionBase {
public:
@@ -61,10 +60,6 @@
JS_EXPORT_PRIVATE static WebAssemblyFunction* create(VM&, JSGlobalObject*, Structure*, unsigned, const String&, JSWebAssemblyInstance*, Wasm::Callee& jsEntrypoint, WasmToWasmImportableFunction::LoadLocation, Wasm::SignatureIndex);
static Structure* createStructure(VM&, JSGlobalObject*, JSValue);
- Wasm::SignatureIndex signatureIndex() const { return m_importableFunction.signatureIndex; }
- WasmToWasmImportableFunction::LoadLocation entrypointLoadLocation() const { return m_importableFunction.entrypointLoadLocation; }
- WasmToWasmImportableFunction importableFunction() const { return m_importableFunction; }
-
MacroAssemblerCodePtr<WasmEntryPtrTag> jsEntrypoint(ArityCheckMode arity)
{
if (arity == ArityCheckNotRequired)
@@ -73,8 +68,6 @@
return m_jsEntrypoint;
}
- static ptrdiff_t offsetOfEntrypointLoadLocation() { return OBJECT_OFFSETOF(WebAssemblyFunction, m_importableFunction) + WasmToWasmImportableFunction::offsetOfEntrypointLoadLocation(); }
-
MacroAssemblerCodePtr<JSEntryPtrTag> jsCallEntrypoint()
{
if (m_jsCallEntrypoint)
@@ -95,11 +88,10 @@
RegisterSet calleeSaves() const;
- // It's safe to just hold the raw WasmToWasmImportableFunction/jsEntrypoint because we have a reference
+ // It's safe to just hold the raw jsEntrypoint because we have a reference
// to our Instance, which points to the Module that exported us, which
// ensures that the actual Signature/code doesn't get deallocated.
MacroAssemblerCodePtr<WasmEntryPtrTag> m_jsEntrypoint;
- WasmToWasmImportableFunction m_importableFunction;
WriteBarrier<JSToWasmICCallee> m_jsToWasmICCallee;
// Used for JS calling into Wasm.
MacroAssemblerCodeRef<JSEntryPtrTag> m_jsCallEntrypoint;
Modified: trunk/Source/_javascript_Core/wasm/js/WebAssemblyFunctionBase.cpp (276895 => 276896)
--- trunk/Source/_javascript_Core/wasm/js/WebAssemblyFunctionBase.cpp 2021-05-03 09:29:48 UTC (rev 276895)
+++ trunk/Source/_javascript_Core/wasm/js/WebAssemblyFunctionBase.cpp 2021-05-03 11:00:43 UTC (rev 276896)
@@ -37,8 +37,9 @@
const ClassInfo WebAssemblyFunctionBase::s_info = { "WebAssemblyFunctionBase", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(WebAssemblyFunctionBase) };
-WebAssemblyFunctionBase::WebAssemblyFunctionBase(VM& vm, NativeExecutable* executable, JSGlobalObject* globalObject, Structure* structure)
+WebAssemblyFunctionBase::WebAssemblyFunctionBase(VM& vm, NativeExecutable* executable, JSGlobalObject* globalObject, Structure* structure, WasmToWasmImportableFunction importableFunction)
: Base(vm, executable, globalObject, structure)
+ , m_importableFunction(importableFunction)
{ }
template<typename Visitor>
Modified: trunk/Source/_javascript_Core/wasm/js/WebAssemblyFunctionBase.h (276895 => 276896)
--- trunk/Source/_javascript_Core/wasm/js/WebAssemblyFunctionBase.h 2021-05-03 09:29:48 UTC (rev 276895)
+++ trunk/Source/_javascript_Core/wasm/js/WebAssemblyFunctionBase.h 2021-05-03 11:00:43 UTC (rev 276896)
@@ -33,6 +33,7 @@
class JSGlobalObject;
class JSWebAssemblyInstance;
+using Wasm::WasmToWasmImportableFunction;
class WebAssemblyFunctionBase : public JSFunction {
public:
@@ -43,14 +44,26 @@
DECLARE_INFO;
JSWebAssemblyInstance* instance() const { return m_instance.get(); }
+
+ Wasm::SignatureIndex signatureIndex() const { return m_importableFunction.signatureIndex; }
+ WasmToWasmImportableFunction::LoadLocation entrypointLoadLocation() const { return m_importableFunction.entrypointLoadLocation; }
+ WasmToWasmImportableFunction importableFunction() const { return m_importableFunction; }
+
static ptrdiff_t offsetOfInstance() { return OBJECT_OFFSETOF(WebAssemblyFunctionBase, m_instance); }
+ static ptrdiff_t offsetOfEntrypointLoadLocation() { return OBJECT_OFFSETOF(WebAssemblyFunctionBase, m_importableFunction) + WasmToWasmImportableFunction::offsetOfEntrypointLoadLocation(); }
+
protected:
DECLARE_VISIT_CHILDREN;
void finishCreation(VM&, NativeExecutable*, unsigned length, const String& name, JSWebAssemblyInstance*);
- WebAssemblyFunctionBase(VM&, NativeExecutable*, JSGlobalObject*, Structure*);
+ WebAssemblyFunctionBase(VM&, NativeExecutable*, JSGlobalObject*, Structure*, WasmToWasmImportableFunction);
WriteBarrier<JSWebAssemblyInstance> m_instance;
+
+ // It's safe to just hold the raw WasmToWasmImportableFunction because we have a reference
+ // to our Instance, which points to the CodeBlock, which points to the Module
+ // that exported us, which ensures that the actual Signature/code doesn't get deallocated.
+ WasmToWasmImportableFunction m_importableFunction;
};
} // namespace JSC
Modified: trunk/Source/_javascript_Core/wasm/js/WebAssemblyWrapperFunction.cpp (276895 => 276896)
--- trunk/Source/_javascript_Core/wasm/js/WebAssemblyWrapperFunction.cpp 2021-05-03 09:29:48 UTC (rev 276895)
+++ trunk/Source/_javascript_Core/wasm/js/WebAssemblyWrapperFunction.cpp 2021-05-03 11:00:43 UTC (rev 276896)
@@ -39,8 +39,7 @@
static JSC_DECLARE_HOST_FUNCTION(callWebAssemblyWrapperFunction);
WebAssemblyWrapperFunction::WebAssemblyWrapperFunction(VM& vm, NativeExecutable* executable, JSGlobalObject* globalObject, Structure* structure, Wasm::WasmToWasmImportableFunction importableFunction)
- : Base(vm, executable, globalObject, structure)
- , m_importableFunction(importableFunction)
+ : Base(vm, executable, globalObject, structure, importableFunction)
{ }
WebAssemblyWrapperFunction* WebAssemblyWrapperFunction::create(VM& vm, JSGlobalObject* globalObject, Structure* structure, JSObject* function, unsigned importIndex, JSWebAssemblyInstance* instance, Wasm::SignatureIndex signatureIndex)
Modified: trunk/Source/_javascript_Core/wasm/js/WebAssemblyWrapperFunction.h (276895 => 276896)
--- trunk/Source/_javascript_Core/wasm/js/WebAssemblyWrapperFunction.h 2021-05-03 09:29:48 UTC (rev 276895)
+++ trunk/Source/_javascript_Core/wasm/js/WebAssemblyWrapperFunction.h 2021-05-03 11:00:43 UTC (rev 276896)
@@ -32,8 +32,6 @@
namespace JSC {
-using Wasm::WasmToWasmImportableFunction;
-
class WebAssemblyWrapperFunction final : public WebAssemblyFunctionBase {
public:
using Base = WebAssemblyFunctionBase;
@@ -51,9 +49,6 @@
static WebAssemblyWrapperFunction* create(VM&, JSGlobalObject*, Structure*, JSObject*, unsigned importIndex, JSWebAssemblyInstance*, Wasm::SignatureIndex);
static Structure* createStructure(VM&, JSGlobalObject*, JSValue);
- Wasm::SignatureIndex signatureIndex() const { return m_importableFunction.signatureIndex; }
- WasmToWasmImportableFunction::LoadLocation entrypointLoadLocation() const { return m_importableFunction.entrypointLoadLocation; }
- WasmToWasmImportableFunction importableFunction() const { return m_importableFunction; }
JSObject* function() { return m_function.get(); }
private:
@@ -62,10 +57,6 @@
DECLARE_VISIT_CHILDREN;
WriteBarrier<JSObject> m_function;
- // It's safe to just hold the raw WasmToWasmImportableFunction because we have a reference
- // to our Instance, which points to the CodeBlock, which points to the Module
- // that exported us, which ensures that the actual Signature/code doesn't get deallocated.
- WasmToWasmImportableFunction m_importableFunction;
};
} // namespace JSC
Modified: trunk/Source/_javascript_Core/wasm/wasm.json (276895 => 276896)
--- trunk/Source/_javascript_Core/wasm/wasm.json 2021-05-03 09:29:48 UTC (rev 276895)
+++ trunk/Source/_javascript_Core/wasm/wasm.json 2021-05-03 11:00:43 UTC (rev 276896)
@@ -85,6 +85,7 @@
"data.drop": { "category": "exttable", "value": 252, "return": [], "parameter": [], "immediate": [{"name": "segment_index", "type": "varuint32"}], "description": "shrinks the size of the segment to zero", "extendedOp": 9 },
"call": { "category": "call", "value": 16, "return": ["call"], "parameter": ["call"], "immediate": [{"name": "function_index", "type": "varuint32"}], "description": "call a function by its index" },
"call_indirect": { "category": "call", "value": 17, "return": ["call"], "parameter": ["call"], "immediate": [{"name": "type_index", "type": "varuint32"}, {"name": "table_index","type": "varuint32"}],"description": "call a function indirect with an expected signature" },
+ "call_ref": { "category": "call", "value": 20, "return": ["call"], "parameter": ["call"], "immediate": [], "description": "call a function reference" },
"i32.load8_s": { "category": "memory", "value": 44, "return": ["i32"], "parameter": ["addr"], "immediate": [{"name": "flags", "type": "varuint32"}, {"name": "offset", "type": "varuint32"}], "description": "load from memory" },
"i32.load8_u": { "category": "memory", "value": 45, "return": ["i32"], "parameter": ["addr"], "immediate": [{"name": "flags", "type": "varuint32"}, {"name": "offset", "type": "varuint32"}], "description": "load from memory" },
"i32.load16_s": { "category": "memory", "value": 46, "return": ["i32"], "parameter": ["addr"], "immediate": [{"name": "flags", "type": "varuint32"}, {"name": "offset", "type": "varuint32"}], "description": "load from memory" },