Changeset 276896 in webkit


Ignore:
Timestamp:
May 3, 2021 4:00:43 AM (15 months ago)
Author:
commit-queue@webkit.org
Message:

[WASM-Function-References] Add call_ref instruction
https://bugs.webkit.org/show_bug.cgi?id=222903

Patch by Dmitry Bezhetskov <dbezhetskov> on 2021-05-03
Reviewed by Yusuke Suzuki.

JSTests:

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:

Source/JavaScriptCore:

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:
Location:
trunk
Files:
2 added
24 edited

Legend:

Unmodified
Added
Removed
  • trunk/JSTests/ChangeLog

    r276719 r276896  
     12021-05-03  Dmitry Bezhetskov  <dbezhetskov@igalia.com>
     2
     3        [WASM-Function-References] Add call_ref instruction
     4        https://bugs.webkit.org/show_bug.cgi?id=222903
     5
     6        Reviewed by Yusuke Suzuki.
     7
     8        Add basic tests for new call_ref instruction:
     9        https://github.com/WebAssembly/function-references/blob/master/proposals/function-references/Overview.md.
     10        Add tests for calling same-instance wasm function, foreign-instance
     11        wasm function and for calling imported js function.
     12
     13        * wasm.yaml:
     14        * wasm/function-references/call_ref.js: Added.
     15        (module):
     16        (async basics):
     17        (async indirectCall):
     18        (async importHostCall):
     19        * wasm/wasm.json:
     20
    1212021-04-28  Mark Lam  <mark.lam@apple.com>
    222
  • trunk/JSTests/wasm.yaml

    r274399 r276896  
    3434- path: wasm/references
    3535  cmd: runWebAssemblySuite unless parseRunCommands
     36- path: wasm/function-references
     37  cmd: runWebAssemblySuite unless parseRunCommands
    3638- path: wasm/fuzz
    3739  cmd: runWebAssemblySuite unless parseRunCommands
  • trunk/JSTests/wasm/wasm.json

    r273962 r276896  
    8686        "call":                { "category": "call",       "value":  16, "return": ["call"],                         "parameter": ["call"],                       "immediate": [{"name": "function_index", "type": "varuint32"}],                                             "description": "call a function by its index" },
    8787        "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" },
     88        "call_ref":            { "category": "call",       "value":  20, "return": ["call"],                         "parameter": ["call"],                       "immediate": [],                                                                                            "description": "call a function reference" },
    8889        "i32.load8_s":         { "category": "memory",     "value":  44, "return": ["i32"],                          "parameter": ["addr"],                       "immediate": [{"name": "flags",          "type": "varuint32"}, {"name": "offset",   "type": "varuint32"}], "description": "load from memory" },
    8990        "i32.load8_u":         { "category": "memory",     "value":  45, "return": ["i32"],                          "parameter": ["addr"],                       "immediate": [{"name": "flags",          "type": "varuint32"}, {"name": "offset",   "type": "varuint32"}], "description": "load from memory" },
  • trunk/Source/JavaScriptCore/ChangeLog

    r276879 r276896  
     12021-05-03  Dmitry Bezhetskov  <dbezhetskov@igalia.com>
     2
     3        [WASM-Function-References] Add call_ref instruction
     4        https://bugs.webkit.org/show_bug.cgi?id=222903
     5
     6        Reviewed by Yusuke Suzuki.
     7
     8        Add support for call_ref instruction from the typed function
     9        references proposal: https://github.com/WebAssembly/function-references/blob/master/proposals/function-references/Overview.md.
     10        call_ref calls the given function references from the stack
     11        and it does almost the same stuff as call_indirect but
     12        it doesn't check signatures because wasm types system guaranties
     13        correctness.
     14
     15        * bytecode/BytecodeList.rb:
     16        * dfg/DFGCapabilities.cpp:
     17        (JSC::DFG::capabilityLevel):
     18        * llint/LowLevelInterpreter.asm:
     19        * llint/WebAssembly.asm:
     20        * runtime/Gate.h:
     21        * wasm/WasmAirIRGenerator.cpp:
     22        (JSC::Wasm::AirIRGenerator::addCallIndirect):
     23        (JSC::Wasm::AirIRGenerator::addCallRef):
     24        (JSC::Wasm::AirIRGenerator::emitIndirectCall):
     25        * wasm/WasmB3IRGenerator.cpp:
     26        (JSC::Wasm::B3IRGenerator::emitIndirectCall):
     27        (JSC::Wasm::B3IRGenerator::addCallIndirect):
     28        (JSC::Wasm::B3IRGenerator::addCallRef):
     29        * wasm/WasmFunctionParser.h:
     30        (JSC::Wasm::FunctionParser<Context>::parseExpression):
     31        (JSC::Wasm::FunctionParser<Context>::parseUnreachableExpression):
     32        * wasm/WasmLLIntGenerator.cpp:
     33        (JSC::Wasm::LLIntGenerator::addCallRef):
     34        * wasm/WasmSlowPaths.cpp:
     35        (JSC::LLInt::doWasmCallRef):
     36        (JSC::LLInt::WASM_SLOW_PATH_DECL):
     37        * wasm/WasmSlowPaths.h:
     38        * wasm/js/JSWebAssemblyTable.cpp:
     39        * wasm/js/WebAssemblyFunction.cpp:
     40        (JSC::WebAssemblyFunction::WebAssemblyFunction):
     41        * wasm/js/WebAssemblyFunction.h:
     42        * wasm/js/WebAssemblyFunctionBase.cpp:
     43        (JSC::WebAssemblyFunctionBase::WebAssemblyFunctionBase):
     44        * wasm/js/WebAssemblyFunctionBase.h:
     45        (JSC::WebAssemblyFunctionBase::offsetOfEntrypointLoadLocation):
     46        * wasm/js/WebAssemblyWrapperFunction.cpp:
     47        (JSC::WebAssemblyWrapperFunction::WebAssemblyWrapperFunction):
     48        * wasm/js/WebAssemblyWrapperFunction.h:
     49        * wasm/wasm.json:
     50
    1512021-05-01  Chris Dumez  <cdumez@apple.com>
    252
  • trunk/Source/JavaScriptCore/bytecode/BytecodeList.rb

    r273225 r276896  
    14751475op :wasm_trampoline_wasm_call_indirect
    14761476op :wasm_trampoline_wasm_call_indirect_no_tls
     1477op :wasm_trampoline_wasm_call_ref
     1478op :wasm_trampoline_wasm_call_ref_no_tls
    14771479
    14781480end_section :NativeHelpers
     
    14961498op :call_indirect_return_location
    14971499op :call_indirect_no_tls_return_location
     1500op :call_ref_return_location
     1501op :call_ref_no_tls_return_location
    14981502
    14991503# FIXME: Wasm and JS LLInt should share common opcodes
     
    16851689        numberOfStackArgs: unsigned,
    16861690        tableIndex: unsigned,
     1691    }
     1692
     1693op :call_ref,
     1694    args: {
     1695        functionReference: VirtualRegister,
     1696        signatureIndex: unsigned,
     1697        stackOffset: unsigned,
     1698        numberOfStackArgs: unsigned,
     1699    }
     1700
     1701op :call_ref_no_tls,
     1702    args: {
     1703        functionReference: VirtualRegister,
     1704        signatureIndex: unsigned,
     1705        stackOffset: unsigned,
     1706        numberOfStackArgs: unsigned,
    16871707    }
    16881708
  • trunk/Source/JavaScriptCore/dfg/DFGCapabilities.cpp

    r276427 r276896  
    369369    case wasm_trampoline_wasm_call_indirect:
    370370    case wasm_trampoline_wasm_call_indirect_no_tls:
     371    case wasm_trampoline_wasm_call_ref:
     372    case wasm_trampoline_wasm_call_ref_no_tls:
    371373        return CannotCompile;
    372374    }
  • trunk/Source/JavaScriptCore/llint/LowLevelInterpreter.asm

    r275797 r276896  
    25312531_wasm_trampoline_wasm_call_indirect:
    25322532_wasm_trampoline_wasm_call_indirect_no_tls:
     2533_wasm_trampoline_wasm_call_ref:
     2534_wasm_trampoline_wasm_call_ref_no_tls:
    25332535_wasm_trampoline_wasm_call_wide16:
    25342536_wasm_trampoline_wasm_call_no_tls_wide16:
    25352537_wasm_trampoline_wasm_call_indirect_wide16:
    25362538_wasm_trampoline_wasm_call_indirect_no_tls_wide16:
     2539_wasm_trampoline_wasm_call_ref_wide16:
     2540_wasm_trampoline_wasm_call_ref_no_tls_wide16:
    25372541_wasm_trampoline_wasm_call_wide32:
    25382542_wasm_trampoline_wasm_call_no_tls_wide32:
    25392543_wasm_trampoline_wasm_call_indirect_wide32:
    25402544_wasm_trampoline_wasm_call_indirect_no_tls_wide32:
     2545_wasm_trampoline_wasm_call_ref_wide32:
     2546_wasm_trampoline_wasm_call_ref_no_tls_wide32:
    25412547    crash()
    25422548
  • trunk/Source/JavaScriptCore/llint/WebAssembly.asm

    r275597 r276896  
    876876wasmOp(call_indirect_no_tls, WasmCallIndirectNoTls, macro(ctx)
    877877    slowPathForWasmCall(ctx, _slow_path_wasm_call_indirect_no_tls, macro(targetInstance) move targetInstance, wasmInstance end)
     878end)
     879
     880wasmOp(call_ref, WasmCallRef, macro(ctx)
     881    slowPathForWasmCall(ctx, _slow_path_wasm_call_ref, storeWasmInstanceToTLS)
     882end)
     883
     884wasmOp(call_ref_no_tls, WasmCallRefNoTls, macro(ctx)
     885    slowPathForWasmCall(ctx, _slow_path_wasm_call_ref_no_tls, macro(targetInstance) move targetInstance, wasmInstance end)
    878886end)
    879887
  • trunk/Source/JavaScriptCore/runtime/Gate.h

    r271332 r276896  
    6969    v(wasm_call_indirect, JSEntrySlowPathPtrTag) \
    7070    v(wasm_call_indirect_no_tls, JSEntrySlowPathPtrTag) \
     71    v(wasm_call_ref, JSEntrySlowPathPtrTag) \
     72    v(wasm_call_ref_no_tls, JSEntrySlowPathPtrTag) \
    7173
    7274#else
  • trunk/Source/JavaScriptCore/wasm/WasmAirIRGenerator.cpp

    r276343 r276896  
    326326    PartialResult WARN_UNUSED_RETURN addCall(uint32_t calleeIndex, const Signature&, Vector<ExpressionType>& args, ResultList& results);
    327327    PartialResult WARN_UNUSED_RETURN addCallIndirect(unsigned tableIndex, const Signature&, Vector<ExpressionType>& args, ResultList& results);
     328    PartialResult WARN_UNUSED_RETURN addCallRef(const Signature&, Vector<ExpressionType>& args, ResultList& results);
    328329    PartialResult WARN_UNUSED_RETURN addUnreachable();
     330    PartialResult WARN_UNUSED_RETURN emitIndirectCall(TypedTmp calleeInstance, ExpressionType calleeCode, const Signature&, const Vector<ExpressionType>& args, ResultList&);
    329331    B3::PatchpointValue* WARN_UNUSED_RETURN emitCallPatchpoint(BasicBlock*, const Signature&, const ResultList& results, const Vector<TypedTmp>& args, Vector<ConstrainedTmp>&& extraArgs = { });
    330332
     
    32743276    m_maxNumJSCallArguments = std::max(m_maxNumJSCallArguments, static_cast<uint32_t>(args.size()));
    32753277
    3276     auto currentInstance = g64();
    3277     append(Move, instanceValue(), currentInstance);
    3278 
    32793278    ExpressionType callableFunctionBuffer = g64();
    32803279    ExpressionType instancesBuffer = g64();
     
    33413340    }
    33423341
     3342    auto calleeInstance = g64();
     3343    append(Move, Arg::index(instancesBuffer, calleeIndex, 8, 0), calleeInstance);
     3344
     3345    return emitIndirectCall(calleeInstance, calleeCode, signature, args, results);
     3346}
     3347
     3348auto AirIRGenerator::addCallRef(const Signature& signature, Vector<ExpressionType>& args, ResultList& results) -> PartialResult
     3349{
     3350    m_makesCalls = true;
     3351    // Note: call ref can call either WebAssemblyFunction or WebAssemblyWrapperFunction. Because
     3352    // WebAssemblyWrapperFunction is like calling into the embedder, we conservatively assume all call indirects
     3353    // can be to the embedder for our stack check calculation.
     3354    ExpressionType calleeFunction = args.takeLast();
     3355    m_maxNumJSCallArguments = std::max(m_maxNumJSCallArguments, static_cast<uint32_t>(args.size()));
     3356
     3357    ExpressionType calleeCode = g64();
     3358    append(Move, Arg::addr(calleeFunction, WebAssemblyFunctionBase::offsetOfEntrypointLoadLocation()), calleeCode); // Pointer to callee code.
     3359
     3360    auto calleeInstance = g64();
     3361    append(Move, Arg::addr(calleeFunction, WebAssemblyFunctionBase::offsetOfInstance()), calleeInstance);
     3362    append(Move, Arg::addr(calleeInstance, JSWebAssemblyInstance::offsetOfInstance()), calleeInstance);
     3363
     3364    return emitIndirectCall(calleeInstance, calleeCode, signature, args, results);
     3365}
     3366
     3367auto AirIRGenerator::emitIndirectCall(TypedTmp calleeInstance, ExpressionType calleeCode, const Signature& signature, const Vector<ExpressionType>& args, ResultList& results) -> PartialResult
     3368{
     3369    auto currentInstance = g64();
     3370    append(Move, instanceValue(), currentInstance);
     3371
    33433372    // Do a context switch if needed.
    33443373    {
    3345         auto newContextInstance = g64();
    3346         append(Move, Arg::index(instancesBuffer, calleeIndex, 8, 0), newContextInstance);
    3347 
    33483374        BasicBlock* doContextSwitch = m_code.addBlock();
    33493375        BasicBlock* continuation = m_code.addBlock();
    33503376
    3351         append(Branch64, Arg::relCond(MacroAssembler::Equal), newContextInstance, instanceValue());
     3377        append(Branch64, Arg::relCond(MacroAssembler::Equal), calleeInstance, currentInstance);
    33523378        m_currentBlock->setSuccessors(continuation, doContextSwitch);
    33533379
     
    33623388        patchpoint->setGenerator([=] (CCallHelpers& jit, const B3::StackmapGenerationParams& params) {
    33633389            AllowMacroScratchRegisterUsage allowScratch(jit);
    3364             GPRReg newContextInstance = params[0].gpr();
     3390            GPRReg calleeInstance = params[0].gpr();
    33653391            GPRReg oldContextInstance = params[1].gpr();
    33663392            const PinnedRegisterInfo& pinnedRegs = PinnedRegisterInfo::get();
    33673393            GPRReg baseMemory = pinnedRegs.baseMemoryPointer;
    3368             ASSERT(newContextInstance != baseMemory);
     3394            ASSERT(calleeInstance != baseMemory);
    33693395            jit.loadPtr(CCallHelpers::Address(oldContextInstance, Instance::offsetOfCachedStackLimit()), baseMemory);
    3370             jit.storePtr(baseMemory, CCallHelpers::Address(newContextInstance, Instance::offsetOfCachedStackLimit()));
    3371             jit.storeWasmContextInstance(newContextInstance);
     3396            jit.storePtr(baseMemory, CCallHelpers::Address(calleeInstance, Instance::offsetOfCachedStackLimit()));
     3397            jit.storeWasmContextInstance(calleeInstance);
    33723398            // FIXME: We should support more than one memory size register
    33733399            //   see: https://bugs.webkit.org/show_bug.cgi?id=162952
    3374             ASSERT(pinnedRegs.boundsCheckingSizeRegister != newContextInstance);
     3400            ASSERT(pinnedRegs.boundsCheckingSizeRegister != calleeInstance);
    33753401            GPRReg scratch = params.gpScratch(0);
    33763402
    3377             jit.loadPtr(CCallHelpers::Address(newContextInstance, Instance::offsetOfCachedBoundsCheckingSize()), pinnedRegs.boundsCheckingSizeRegister); // Bound checking size.
    3378             jit.loadPtr(CCallHelpers::Address(newContextInstance, Instance::offsetOfCachedMemory()), baseMemory); // Memory::void*.
     3403            jit.loadPtr(CCallHelpers::Address(calleeInstance, Instance::offsetOfCachedBoundsCheckingSize()), pinnedRegs.boundsCheckingSizeRegister); // Bound checking size.
     3404            jit.loadPtr(CCallHelpers::Address(calleeInstance, Instance::offsetOfCachedMemory()), baseMemory); // Memory::void*.
    33793405
    33803406            jit.cageConditionallyAndUntag(Gigacage::Primitive, baseMemory, pinnedRegs.boundsCheckingSizeRegister, scratch);
    33813407        });
    33823408
    3383         emitPatchpoint(doContextSwitch, patchpoint, Tmp(), newContextInstance, instanceValue());
     3409        emitPatchpoint(doContextSwitch, patchpoint, Tmp(), calleeInstance, currentInstance);
    33843410        append(doContextSwitch, Jump);
    33853411        doContextSwitch->setSuccessors(continuation);
  • trunk/Source/JavaScriptCore/wasm/WasmB3IRGenerator.cpp

    r276343 r276896  
    286286    PartialResult WARN_UNUSED_RETURN addCall(uint32_t calleeIndex, const Signature&, Vector<ExpressionType>& args, ResultList& results);
    287287    PartialResult WARN_UNUSED_RETURN addCallIndirect(unsigned tableIndex, const Signature&, Vector<ExpressionType>& args, ResultList& results);
     288    PartialResult WARN_UNUSED_RETURN addCallRef(const Signature&, Vector<ExpressionType>& args, ResultList& results);
    288289    PartialResult WARN_UNUSED_RETURN addUnreachable();
     290    PartialResult WARN_UNUSED_RETURN emitIndirectCall(Value* calleeInstance, ExpressionType calleeCode, const Signature&, Vector<ExpressionType>& args, ResultList&);
    289291    B3::Value* createCallPatchpoint(BasicBlock*, Origin, const Signature&, Vector<ExpressionType>& args, const ScopedLambda<void(PatchpointValue*)>& patchpointFunctor);
    290292
     
    864866    });
    865867    unreachable->effects.terminal = true;
     868    return { };
     869}
     870
     871auto B3IRGenerator::emitIndirectCall(Value* calleeInstance, ExpressionType calleeCode, const Signature& signature, Vector<ExpressionType>& args, ResultList& results) -> PartialResult
     872{
     873    // Do a context switch if needed.
     874    {
     875        BasicBlock* continuation = m_proc.addBlock();
     876        BasicBlock* doContextSwitch = m_proc.addBlock();
     877
     878        Value* isSameContextInstance = m_currentBlock->appendNew<Value>(m_proc, Equal, origin(),
     879            calleeInstance, instanceValue());
     880        m_currentBlock->appendNewControlValue(m_proc, B3::Branch, origin(),
     881            isSameContextInstance, FrequentedBlock(continuation), FrequentedBlock(doContextSwitch));
     882
     883        PatchpointValue* patchpoint = doContextSwitch->appendNew<PatchpointValue>(m_proc, B3::Void, origin());
     884        patchpoint->effects.writesPinned = true;
     885        // We pessimistically assume we're calling something with BoundsChecking memory.
     886        // FIXME: We shouldn't have to do this: https://bugs.webkit.org/show_bug.cgi?id=172181
     887        patchpoint->clobber(PinnedRegisterInfo::get().toSave(MemoryMode::BoundsChecking));
     888        patchpoint->clobber(RegisterSet::macroScratchRegisters());
     889        patchpoint->append(calleeInstance, ValueRep::SomeRegister);
     890        patchpoint->append(instanceValue(), ValueRep::SomeRegister);
     891        patchpoint->numGPScratchRegisters = 1;
     892
     893        patchpoint->setGenerator([=] (CCallHelpers& jit, const B3::StackmapGenerationParams& params) {
     894            AllowMacroScratchRegisterUsage allowScratch(jit);
     895            GPRReg calleeInstance = params[0].gpr();
     896            GPRReg oldContextInstance = params[1].gpr();
     897            const PinnedRegisterInfo& pinnedRegs = PinnedRegisterInfo::get();
     898            GPRReg baseMemory = pinnedRegs.baseMemoryPointer;
     899            ASSERT(calleeInstance != baseMemory);
     900            jit.loadPtr(CCallHelpers::Address(oldContextInstance, Instance::offsetOfCachedStackLimit()), baseMemory);
     901            jit.storePtr(baseMemory, CCallHelpers::Address(calleeInstance, Instance::offsetOfCachedStackLimit()));
     902            jit.storeWasmContextInstance(calleeInstance);
     903            ASSERT(pinnedRegs.boundsCheckingSizeRegister != baseMemory);
     904            // FIXME: We should support more than one memory size register
     905            //   see: https://bugs.webkit.org/show_bug.cgi?id=162952
     906            ASSERT(pinnedRegs.boundsCheckingSizeRegister != calleeInstance);
     907            GPRReg scratch = params.gpScratch(0);
     908
     909            jit.loadPtr(CCallHelpers::Address(calleeInstance, Instance::offsetOfCachedBoundsCheckingSize()), pinnedRegs.boundsCheckingSizeRegister); // Memory size.
     910            jit.loadPtr(CCallHelpers::Address(calleeInstance, Instance::offsetOfCachedMemory()), baseMemory); // Memory::void*.
     911
     912            jit.cageConditionallyAndUntag(Gigacage::Primitive, baseMemory, pinnedRegs.boundsCheckingSizeRegister, scratch);
     913        });
     914        doContextSwitch->appendNewControlValue(m_proc, Jump, origin(), continuation);
     915
     916        m_currentBlock = continuation;
     917    }
     918
     919    B3::Type returnType = toB3ResultType(&signature);
     920    ExpressionType callResult = createCallPatchpoint(m_currentBlock, origin(), signature, args,
     921        scopedLambdaRef<void(PatchpointValue*)>([=] (PatchpointValue* patchpoint) -> void {
     922            patchpoint->effects.writesPinned = true;
     923            patchpoint->effects.readsPinned = true;
     924            // We need to clobber all potential pinned registers since we might be leaving the instance.
     925            // We pessimistically assume we're always calling something that is bounds checking so
     926            // because the wasm->wasm thunk unconditionally overrides the size registers.
     927            // FIXME: We should not have to do this, but the wasm->wasm stub assumes it can
     928            // use all the pinned registers as scratch: https://bugs.webkit.org/show_bug.cgi?id=172181
     929            patchpoint->clobberLate(PinnedRegisterInfo::get().toSave(MemoryMode::BoundsChecking));
     930
     931            patchpoint->append(calleeCode, ValueRep::SomeRegister);
     932            patchpoint->setGenerator([=] (CCallHelpers& jit, const B3::StackmapGenerationParams& params) {
     933                AllowMacroScratchRegisterUsage allowScratch(jit);
     934                jit.call(params[params.proc().resultCount(returnType)].gpr(), WasmEntryPtrTag);
     935            });
     936        }));
     937
     938    switch (returnType.kind()) {
     939    case B3::Void: {
     940        break;
     941    }
     942    case B3::Tuple: {
     943        const Vector<B3::Type>& tuple = m_proc.tupleForType(returnType);
     944        for (unsigned i = 0; i < signature.returnCount(); ++i)
     945            results.append(m_currentBlock->appendNew<ExtractValue>(m_proc, origin(), tuple[i], callResult, i));
     946        break;
     947    }
     948    default: {
     949        results.append(callResult);
     950        break;
     951    }
     952    }
     953
     954    // The call could have been to another WebAssembly instance, and / or could have modified our Memory.
     955    restoreWebAssemblyGlobalState(RestoreCachedStackLimit::Yes, m_info.memory, instanceValue(), m_proc, m_currentBlock);
     956
    866957    return { };
    867958}
     
    25222613    }
    25232614
    2524     // Do a context switch if needed.
    2525     {
    2526         Value* offset = m_currentBlock->appendNew<Value>(m_proc, Mul, origin(),
    2527             calleeIndex, constant(pointerType(), sizeof(Instance*)));
    2528         Value* newContextInstance = m_currentBlock->appendNew<MemoryValue>(m_proc, Load, pointerType(), origin(),
    2529             m_currentBlock->appendNew<Value>(m_proc, Add, origin(), instancesBuffer, offset));
    2530 
    2531         BasicBlock* continuation = m_proc.addBlock();
    2532         BasicBlock* doContextSwitch = m_proc.addBlock();
    2533 
    2534         Value* isSameContextInstance = m_currentBlock->appendNew<Value>(m_proc, Equal, origin(),
    2535             newContextInstance, instanceValue());
    2536         m_currentBlock->appendNewControlValue(m_proc, B3::Branch, origin(),
    2537             isSameContextInstance, FrequentedBlock(continuation), FrequentedBlock(doContextSwitch));
    2538 
    2539         PatchpointValue* patchpoint = doContextSwitch->appendNew<PatchpointValue>(m_proc, B3::Void, origin());
    2540         patchpoint->effects.writesPinned = true;
    2541         // We pessimistically assume we're calling something with BoundsChecking memory.
    2542         // FIXME: We shouldn't have to do this: https://bugs.webkit.org/show_bug.cgi?id=172181
    2543         patchpoint->clobber(PinnedRegisterInfo::get().toSave(MemoryMode::BoundsChecking));
    2544         patchpoint->clobber(RegisterSet::macroScratchRegisters());
    2545         patchpoint->append(newContextInstance, ValueRep::SomeRegister);
    2546         patchpoint->append(instanceValue(), ValueRep::SomeRegister);
    2547         patchpoint->numGPScratchRegisters = 1;
    2548 
    2549         patchpoint->setGenerator([=] (CCallHelpers& jit, const B3::StackmapGenerationParams& params) {
    2550             AllowMacroScratchRegisterUsage allowScratch(jit);
    2551             GPRReg newContextInstance = params[0].gpr();
    2552             GPRReg oldContextInstance = params[1].gpr();
    2553             const PinnedRegisterInfo& pinnedRegs = PinnedRegisterInfo::get();
    2554             GPRReg baseMemory = pinnedRegs.baseMemoryPointer;
    2555             ASSERT(newContextInstance != baseMemory);
    2556             jit.loadPtr(CCallHelpers::Address(oldContextInstance, Instance::offsetOfCachedStackLimit()), baseMemory);
    2557             jit.storePtr(baseMemory, CCallHelpers::Address(newContextInstance, Instance::offsetOfCachedStackLimit()));
    2558             jit.storeWasmContextInstance(newContextInstance);
    2559             ASSERT(pinnedRegs.boundsCheckingSizeRegister != baseMemory);
    2560             // FIXME: We should support more than one memory size register
    2561             //   see: https://bugs.webkit.org/show_bug.cgi?id=162952
    2562             ASSERT(pinnedRegs.boundsCheckingSizeRegister != newContextInstance);
    2563             GPRReg scratch = params.gpScratch(0);
    2564 
    2565             jit.loadPtr(CCallHelpers::Address(newContextInstance, Instance::offsetOfCachedBoundsCheckingSize()), pinnedRegs.boundsCheckingSizeRegister); // Memory size.
    2566             jit.loadPtr(CCallHelpers::Address(newContextInstance, Instance::offsetOfCachedMemory()), baseMemory); // Memory::void*.
    2567 
    2568             jit.cageConditionallyAndUntag(Gigacage::Primitive, baseMemory, pinnedRegs.boundsCheckingSizeRegister, scratch);
    2569         });
    2570         doContextSwitch->appendNewControlValue(m_proc, Jump, origin(), continuation);
    2571 
    2572         m_currentBlock = continuation;
    2573     }
    2574 
     2615    Value* offset = m_currentBlock->appendNew<Value>(m_proc, Mul, origin(),
     2616        calleeIndex, constant(pointerType(), sizeof(Instance*)));
     2617    Value* calleeInstance = m_currentBlock->appendNew<MemoryValue>(m_proc, Load, pointerType(), origin(),
     2618        m_currentBlock->appendNew<Value>(m_proc, Add, origin(), instancesBuffer, offset));
    25752619    ExpressionType calleeCode = m_currentBlock->appendNew<MemoryValue>(m_proc, Load, pointerType(), origin(),
    25762620        m_currentBlock->appendNew<MemoryValue>(m_proc, Load, pointerType(), origin(), callableFunction,
    25772621            safeCast<int32_t>(WasmToWasmImportableFunction::offsetOfEntrypointLoadLocation())));
    25782622
    2579     B3::Type returnType = toB3ResultType(&signature);
    2580     ExpressionType callResult = createCallPatchpoint(m_currentBlock, origin(), signature, args,
    2581         scopedLambdaRef<void(PatchpointValue*)>([=] (PatchpointValue* patchpoint) -> void {
    2582             patchpoint->effects.writesPinned = true;
    2583             patchpoint->effects.readsPinned = true;
    2584             // We need to clobber all potential pinned registers since we might be leaving the instance.
    2585             // We pessimistically assume we're always calling something that is bounds checking so
    2586             // because the wasm->wasm thunk unconditionally overrides the size registers.
    2587             // FIXME: We should not have to do this, but the wasm->wasm stub assumes it can
    2588             // use all the pinned registers as scratch: https://bugs.webkit.org/show_bug.cgi?id=172181
    2589             patchpoint->clobberLate(PinnedRegisterInfo::get().toSave(MemoryMode::BoundsChecking));
    2590 
    2591             patchpoint->append(calleeCode, ValueRep::SomeRegister);
    2592             patchpoint->setGenerator([=] (CCallHelpers& jit, const B3::StackmapGenerationParams& params) {
    2593                 AllowMacroScratchRegisterUsage allowScratch(jit);
    2594                 jit.call(params[params.proc().resultCount(returnType)].gpr(), WasmEntryPtrTag);
    2595             });
    2596         }));
    2597 
    2598     switch (returnType.kind()) {
    2599     case B3::Void: {
    2600         break;
    2601     }
    2602     case B3::Tuple: {
    2603         const Vector<B3::Type>& tuple = m_proc.tupleForType(returnType);
    2604         for (unsigned i = 0; i < signature.returnCount(); ++i)
    2605             results.append(m_currentBlock->appendNew<ExtractValue>(m_proc, origin(), tuple[i], callResult, i));
    2606         break;
    2607     }
    2608     default: {
    2609         results.append(callResult);
    2610         break;
    2611     }
    2612     }
    2613 
    2614     // The call could have been to another WebAssembly instance, and / or could have modified our Memory.
    2615     restoreWebAssemblyGlobalState(RestoreCachedStackLimit::Yes, m_info.memory, instanceValue(), m_proc, m_currentBlock);
    2616 
    2617     return { };
     2623    return emitIndirectCall(calleeInstance, calleeCode, signature, args, results);
     2624}
     2625
     2626auto B3IRGenerator::addCallRef(const Signature& signature, Vector<ExpressionType>& args, ResultList& results) -> PartialResult
     2627{
     2628    ExpressionType callee = args.takeLast();
     2629    ASSERT(signature.argumentCount() == args.size());
     2630    m_makesCalls = true;
     2631
     2632    // Note: call ref can call either WebAssemblyFunction or WebAssemblyWrapperFunction. Because
     2633    // WebAssemblyWrapperFunction is like calling into the embedder, we conservatively assume all call indirects
     2634    // can be to the embedder for our stack check calculation.
     2635    m_maxNumJSCallArguments = std::max(m_maxNumJSCallArguments, static_cast<uint32_t>(args.size()));
     2636
     2637    Value* jsInstanceOffset = constant(pointerType(), safeCast<int32_t>(WebAssemblyFunctionBase::offsetOfInstance()));
     2638    Value* jsCalleeInstance = m_currentBlock->appendNew<MemoryValue>(m_proc, Load, pointerType(), origin(),
     2639        m_currentBlock->appendNew<Value>(m_proc, Add, origin(), callee, jsInstanceOffset));
     2640
     2641    Value* instanceOffset = constant(pointerType(), safeCast<int32_t>(JSWebAssemblyInstance::offsetOfInstance()));
     2642    Value* calleeInstance = m_currentBlock->appendNew<MemoryValue>(m_proc, Load, pointerType(), origin(),
     2643        m_currentBlock->appendNew<Value>(m_proc, Add, origin(), jsCalleeInstance, instanceOffset));
     2644
     2645    ExpressionType calleeCode = m_currentBlock->appendNew<MemoryValue>(m_proc, Load, pointerType(), origin(),
     2646        m_currentBlock->appendNew<MemoryValue>(m_proc, Load, pointerType(), origin(), callee,
     2647            safeCast<int32_t>(WebAssemblyFunctionBase::offsetOfEntrypointLoadLocation())));
     2648
     2649    return emitIndirectCall(calleeInstance, calleeCode, signature, args, results);
    26182650}
    26192651
  • trunk/Source/JavaScriptCore/wasm/WasmFunctionParser.h

    r273962 r276896  
    12491249        return { };
    12501250    }
     1251
     1252    case CallRef: {
     1253        WASM_PARSER_FAIL_IF(!Options::useWebAssemblyTypedFunctionReferences(), "function references are not enabled");
     1254        WASM_VALIDATOR_FAIL_IF(!m_expressionStack.last().type().isTypeIdx(), "non-funcref call_ref value ", m_expressionStack.last().type().kind);
     1255
     1256        const SignatureIndex calleeSignatureIndex = m_expressionStack.last().type().index;
     1257        const Signature& calleeSignature = SignatureInformation::get(calleeSignatureIndex);
     1258        size_t argumentCount = calleeSignature.argumentCount() + 1; // Add the callee's value.
     1259        WASM_PARSER_FAIL_IF(argumentCount > m_expressionStack.size(), "call_ref expects ", argumentCount, " arguments, but the expression stack currently holds ", m_expressionStack.size(), " values");
     1260
     1261        Vector<ExpressionType> args;
     1262        WASM_PARSER_FAIL_IF(!args.tryReserveCapacity(argumentCount + 1), "can't allocate enough memory for ", argumentCount, " call_indirect arguments");
     1263        size_t firstArgumentIndex = m_expressionStack.size() - argumentCount;
     1264        for (size_t i = firstArgumentIndex; i < m_expressionStack.size(); ++i) {
     1265            TypedExpression arg = m_expressionStack.at(i);
     1266            if (i < m_expressionStack.size() - 1)
     1267                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);
     1268            args.uncheckedAppend(arg);
     1269            m_context.didPopValueFromStack();
     1270        }
     1271        m_expressionStack.shrink(firstArgumentIndex);
     1272
     1273        ResultList results;
     1274        WASM_TRY_ADD_TO_CONTEXT(addCallRef(calleeSignature, args, results));
     1275
     1276        for (unsigned i = 0; i < calleeSignature.returnCount(); ++i)
     1277            m_expressionStack.constructAndAppend(calleeSignature.returnType(i), results[i]);
     1278
     1279        return { };
     1280    }
     1281
    12511282    case Block: {
    12521283        BlockSignature inlineSignature;
     
    17401771    FOR_EACH_WASM_BINARY_OP(CREATE_CASE)
    17411772    FOR_EACH_WASM_UNARY_OP(CREATE_CASE)
     1773    case CallRef:
    17421774    case Unreachable:
    17431775    case Nop:
  • trunk/Source/JavaScriptCore/wasm/WasmLLIntGenerator.cpp

    r276609 r276896  
    254254    PartialResult WARN_UNUSED_RETURN addCall(uint32_t calleeIndex, const Signature&, Vector<ExpressionType>& args, ResultList& results);
    255255    PartialResult WARN_UNUSED_RETURN addCallIndirect(unsigned tableIndex, const Signature&, Vector<ExpressionType>& args, ResultList& results);
     256    PartialResult WARN_UNUSED_RETURN addCallRef(const Signature&, Vector<ExpressionType>& args, ResultList& results);
    256257    PartialResult WARN_UNUSED_RETURN addUnreachable();
    257258
     
    11051106}
    11061107
     1108auto LLIntGenerator::addCallRef(const Signature& signature, Vector<ExpressionType>& args, ResultList& results) -> PartialResult
     1109{
     1110    ExpressionType callee = args.takeLast();
     1111
     1112    LLIntCallInformation info = callInformationForCaller(signature);
     1113    unifyValuesWithBlock(info.arguments, args);
     1114    if (Context::useFastTLS())
     1115        WasmCallRef::emit(this, callee, m_codeBlock->addSignature(signature), info.stackOffset, info.numberOfStackArguments);
     1116    else
     1117        WasmCallRefNoTls::emit(this, callee, m_codeBlock->addSignature(signature), info.stackOffset, info.numberOfStackArguments);
     1118    info.commitResults(results);
     1119
     1120    return { };
     1121}
     1122
    11071123auto LLIntGenerator::addRefIsNull(ExpressionType value, ExpressionType& result) -> PartialResult
    11081124{
  • trunk/Source/JavaScriptCore/wasm/WasmSlowPaths.cpp

    r271775 r276896  
    3030
    3131#include "BytecodeStructs.h"
     32#include "JSWebAssemblyInstance.h"
    3233#include "LLIntData.h"
    3334#include "WasmBBQPlan.h"
     
    4142#include "WasmSignatureInlines.h"
    4243#include "WasmWorklist.h"
     44#include "WebAssemblyFunction.h"
    4345
    4446namespace JSC { namespace LLInt {
     
    499501}
    500502
     503inline SlowPathReturnType doWasmCallRef(CallFrame* callFrame, Wasm::Instance* callerInstance, JSValue targetReference, unsigned signatureIndex)
     504{
     505    UNUSED_PARAM(callFrame);
     506
     507    ASSERT(targetReference.isObject());
     508    JSObject* referenceAsObject = jsCast<JSObject*>(targetReference);
     509
     510    ASSERT(referenceAsObject->inherits<WebAssemblyFunctionBase>(callerInstance->owner<JSObject>()->vm()));
     511    auto* wasmFunction = jsCast<WebAssemblyFunctionBase*>(referenceAsObject);
     512    Wasm::WasmToWasmImportableFunction function = wasmFunction->importableFunction();
     513    Wasm::Instance* calleeInstance = &wasmFunction->instance()->instance();
     514
     515    if (calleeInstance != callerInstance)
     516        calleeInstance->setCachedStackLimit(callerInstance->cachedStackLimit());
     517
     518    ASSERT(function.signatureIndex == Wasm::SignatureInformation::get(CODE_BLOCK()->signature(signatureIndex)));
     519    UNUSED_PARAM(signatureIndex);
     520    WASM_CALL_RETURN(calleeInstance, function.entrypointLoadLocation->executableAddress(), WasmEntryPtrTag);
     521}
     522
     523WASM_SLOW_PATH_DECL(call_ref)
     524{
     525    auto instruction = pc->as<WasmCallRef, WasmOpcodeTraits>();
     526    JSValue reference = JSValue::decode(READ(instruction.m_functionReference).encodedJSValue());
     527    return doWasmCallRef(callFrame, instance, reference, instruction.m_signatureIndex);
     528}
     529
     530WASM_SLOW_PATH_DECL(call_ref_no_tls)
     531{
     532    auto instruction = pc->as<WasmCallRefNoTls, WasmOpcodeTraits>();
     533    JSValue reference = JSValue::decode(READ(instruction.m_functionReference).encodedJSValue());
     534    return doWasmCallRef(callFrame, instance, reference, instruction.m_signatureIndex);
     535}
     536
    501537WASM_SLOW_PATH_DECL(set_global_ref)
    502538{
  • trunk/Source/JavaScriptCore/wasm/WasmSlowPaths.h

    r271775 r276896  
    7777WASM_SLOW_PATH_HIDDEN_DECL(call_indirect);
    7878WASM_SLOW_PATH_HIDDEN_DECL(call_indirect_no_tls);
     79WASM_SLOW_PATH_HIDDEN_DECL(call_ref);
     80WASM_SLOW_PATH_HIDDEN_DECL(call_ref_no_tls);
    7981WASM_SLOW_PATH_HIDDEN_DECL(set_global_ref);
    8082WASM_SLOW_PATH_HIDDEN_DECL(set_global_ref_portable_binding);
  • trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyTable.cpp

    r276384 r276896  
    106106}
    107107
    108 void JSWebAssemblyTable::set(uint32_t index, WebAssemblyFunction* function)
    109 {
    110     RELEASE_ASSERT(index < length());
    111     RELEASE_ASSERT(m_table->asFuncrefTable());
    112     auto& subThis = *static_cast<Wasm::FuncRefTable*>(&m_table.get());
    113     subThis.setFunction(index, function, function->importableFunction(), &function->instance()->instance());
    114 }
    115 
    116 void JSWebAssemblyTable::set(uint32_t index, WebAssemblyWrapperFunction* function)
     108void JSWebAssemblyTable::set(uint32_t index, WebAssemblyFunctionBase* function)
    117109{
    118110    RELEASE_ASSERT(index < length());
  • trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyTable.h

    r275438 r276896  
    6161    bool grow(uint32_t delta, JSValue defaultValue) WARN_UNUSED_RETURN;
    6262    JSValue get(uint32_t);
    63     void set(uint32_t, WebAssemblyFunction*);
    64     void set(uint32_t, WebAssemblyWrapperFunction*);
     63    void set(uint32_t, WebAssemblyFunctionBase*);
    6564    void set(uint32_t, JSValue);
    6665    void clear(uint32_t);
  • trunk/Source/JavaScriptCore/wasm/js/WebAssemblyFunction.cpp

    r275190 r276896  
    455455
    456456WebAssemblyFunction::WebAssemblyFunction(VM& vm, NativeExecutable* executable, JSGlobalObject* globalObject, Structure* structure, Wasm::Callee& jsEntrypoint, Wasm::WasmToWasmImportableFunction::LoadLocation wasmToWasmEntrypointLoadLocation, Wasm::SignatureIndex signatureIndex)
    457     : Base { vm, executable, globalObject, structure }
     457    : Base { vm, executable, globalObject, structure, Wasm::WasmToWasmImportableFunction { signatureIndex, wasmToWasmEntrypointLoadLocation } }
    458458    , m_jsEntrypoint { jsEntrypoint.entrypoint() }
    459     , m_importableFunction { signatureIndex, wasmToWasmEntrypointLoadLocation }
    460459{ }
    461460
  • trunk/Source/JavaScriptCore/wasm/js/WebAssemblyFunction.h

    r274699 r276896  
    4040struct ProtoCallFrame;
    4141class WebAssemblyInstance;
    42 using Wasm::WasmToWasmImportableFunction;
    4342
    4443class WebAssemblyFunction final : public WebAssemblyFunctionBase {
     
    6261    static Structure* createStructure(VM&, JSGlobalObject*, JSValue);
    6362
    64     Wasm::SignatureIndex signatureIndex() const { return m_importableFunction.signatureIndex; }
    65     WasmToWasmImportableFunction::LoadLocation entrypointLoadLocation() const { return m_importableFunction.entrypointLoadLocation; }
    66     WasmToWasmImportableFunction importableFunction() const { return m_importableFunction; }
    67 
    6863    MacroAssemblerCodePtr<WasmEntryPtrTag> jsEntrypoint(ArityCheckMode arity)
    6964    {
     
    7368        return m_jsEntrypoint;
    7469    }
    75 
    76     static ptrdiff_t offsetOfEntrypointLoadLocation() { return OBJECT_OFFSETOF(WebAssemblyFunction, m_importableFunction) + WasmToWasmImportableFunction::offsetOfEntrypointLoadLocation(); }
    7770
    7871    MacroAssemblerCodePtr<JSEntryPtrTag> jsCallEntrypoint()
     
    9689    RegisterSet calleeSaves() const;
    9790
    98     // It's safe to just hold the raw WasmToWasmImportableFunction/jsEntrypoint because we have a reference
     91    // It's safe to just hold the raw jsEntrypoint because we have a reference
    9992    // to our Instance, which points to the Module that exported us, which
    10093    // ensures that the actual Signature/code doesn't get deallocated.
    10194    MacroAssemblerCodePtr<WasmEntryPtrTag> m_jsEntrypoint;
    102     WasmToWasmImportableFunction m_importableFunction;
    10395    WriteBarrier<JSToWasmICCallee> m_jsToWasmICCallee;
    10496    // Used for JS calling into Wasm.
  • trunk/Source/JavaScriptCore/wasm/js/WebAssemblyFunctionBase.cpp

    r273138 r276896  
    3838const ClassInfo WebAssemblyFunctionBase::s_info = { "WebAssemblyFunctionBase", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(WebAssemblyFunctionBase) };
    3939
    40 WebAssemblyFunctionBase::WebAssemblyFunctionBase(VM& vm, NativeExecutable* executable, JSGlobalObject* globalObject, Structure* structure)
     40WebAssemblyFunctionBase::WebAssemblyFunctionBase(VM& vm, NativeExecutable* executable, JSGlobalObject* globalObject, Structure* structure, WasmToWasmImportableFunction importableFunction)
    4141    : Base(vm, executable, globalObject, structure)
     42    , m_importableFunction(importableFunction)
    4243{ }
    4344
  • trunk/Source/JavaScriptCore/wasm/js/WebAssemblyFunctionBase.h

    r273138 r276896  
    3434class JSGlobalObject;
    3535class JSWebAssemblyInstance;
     36using Wasm::WasmToWasmImportableFunction;
    3637
    3738class WebAssemblyFunctionBase : public JSFunction {
     
    4445
    4546    JSWebAssemblyInstance* instance() const { return m_instance.get(); }
     47
     48    Wasm::SignatureIndex signatureIndex() const { return m_importableFunction.signatureIndex; }
     49    WasmToWasmImportableFunction::LoadLocation entrypointLoadLocation() const { return m_importableFunction.entrypointLoadLocation; }
     50    WasmToWasmImportableFunction importableFunction() const { return m_importableFunction; }
     51
    4652    static ptrdiff_t offsetOfInstance() { return OBJECT_OFFSETOF(WebAssemblyFunctionBase, m_instance); }
     53
     54    static ptrdiff_t offsetOfEntrypointLoadLocation() { return OBJECT_OFFSETOF(WebAssemblyFunctionBase, m_importableFunction) + WasmToWasmImportableFunction::offsetOfEntrypointLoadLocation(); }
    4755
    4856protected:
    4957    DECLARE_VISIT_CHILDREN;
    5058    void finishCreation(VM&, NativeExecutable*, unsigned length, const String& name, JSWebAssemblyInstance*);
    51     WebAssemblyFunctionBase(VM&, NativeExecutable*, JSGlobalObject*, Structure*);
     59    WebAssemblyFunctionBase(VM&, NativeExecutable*, JSGlobalObject*, Structure*, WasmToWasmImportableFunction);
    5260
    5361    WriteBarrier<JSWebAssemblyInstance> m_instance;
     62
     63    // It's safe to just hold the raw WasmToWasmImportableFunction because we have a reference
     64    // to our Instance, which points to the CodeBlock, which points to the Module
     65    // that exported us, which ensures that the actual Signature/code doesn't get deallocated.
     66    WasmToWasmImportableFunction m_importableFunction;
    5467};
    5568
  • trunk/Source/JavaScriptCore/wasm/js/WebAssemblyWrapperFunction.cpp

    r273138 r276896  
    4040
    4141WebAssemblyWrapperFunction::WebAssemblyWrapperFunction(VM& vm, NativeExecutable* executable, JSGlobalObject* globalObject, Structure* structure, Wasm::WasmToWasmImportableFunction importableFunction)
    42     : Base(vm, executable, globalObject, structure)
    43     , m_importableFunction(importableFunction)
     42    : Base(vm, executable, globalObject, structure, importableFunction)
    4443{ }
    4544
  • trunk/Source/JavaScriptCore/wasm/js/WebAssemblyWrapperFunction.h

    r273138 r276896  
    3333namespace JSC {
    3434
    35 using Wasm::WasmToWasmImportableFunction;
    36 
    3735class WebAssemblyWrapperFunction final : public WebAssemblyFunctionBase {
    3836public:
     
    5250    static Structure* createStructure(VM&, JSGlobalObject*, JSValue);
    5351
    54     Wasm::SignatureIndex signatureIndex() const { return m_importableFunction.signatureIndex; }
    55     WasmToWasmImportableFunction::LoadLocation  entrypointLoadLocation() const { return m_importableFunction.entrypointLoadLocation; }
    56     WasmToWasmImportableFunction importableFunction() const { return m_importableFunction; }
    5752    JSObject* function() { return m_function.get(); }
    5853
     
    6358
    6459    WriteBarrier<JSObject> m_function;
    65     // It's safe to just hold the raw WasmToWasmImportableFunction because we have a reference
    66     // to our Instance, which points to the CodeBlock, which points to the Module
    67     // that exported us, which ensures that the actual Signature/code doesn't get deallocated.
    68     WasmToWasmImportableFunction m_importableFunction;
    6960};
    7061
  • trunk/Source/JavaScriptCore/wasm/wasm.json

    r273962 r276896  
    8686        "call":                { "category": "call",       "value":  16, "return": ["call"],                         "parameter": ["call"],                       "immediate": [{"name": "function_index", "type": "varuint32"}],                                             "description": "call a function by its index" },
    8787        "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" },
     88        "call_ref":            { "category": "call",       "value":  20, "return": ["call"],                         "parameter": ["call"],                       "immediate": [],                                                                                            "description": "call a function reference" },
    8889        "i32.load8_s":         { "category": "memory",     "value":  44, "return": ["i32"],                          "parameter": ["addr"],                       "immediate": [{"name": "flags",          "type": "varuint32"}, {"name": "offset",   "type": "varuint32"}], "description": "load from memory" },
    8990        "i32.load8_u":         { "category": "memory",     "value":  45, "return": ["i32"],                          "parameter": ["addr"],                       "immediate": [{"name": "flags",          "type": "varuint32"}, {"name": "offset",   "type": "varuint32"}], "description": "load from memory" },
Note: See TracChangeset for help on using the changeset viewer.