⚠ Archived content — this site is no longer maintained.   Current WebKit documentation is at docs.webkit.org.

Changeset 243886 in webkit


Ignore:
Timestamp:
Apr 4, 2019, 11:54:16 AM (7 years ago)
Author:
sbarati@apple.com
Message:

Teach Call ICs how to call Wasm
https://bugs.webkit.org/show_bug.cgi?id=196387

Reviewed by Filip Pizlo.

JSTests:

  • wasm/function-tests/stack-trace.js:

Source/JavaScriptCore:

This patch teaches JS to call Wasm without going through the native thunk.
Currently, we emit a JIT "JS" callee stub which marshals arguments from
JS to Wasm. Like the native version of this, this thunk is responsible
for saving and restoring the VM's current Wasm context. Instead of emitting
an exception handler, we also teach the unwinder how to read the previous
wasm context to restore it as it unwindws past this frame.

This patch is straight forward, and leaves some areas for perf improvement:

  • We can teach the DFG/FTL to directly use the Wasm calling convention when it knows it's calling a single Wasm function. This way we don't shuffle registers to the stack and then back into registers.
  • We bail out to the slow path for mismatched arity. I opened a bug to fix optimize arity check failures: https://bugs.webkit.org/show_bug.cgi?id=196564
  • We bail out to the slow path Double JSValues flowing into i32 arguments. We should teach this thunk how to do that conversion directly.

This patch also refactors the code to explicitly have a single pinned size register.
We used pretend in some places that we could have more than one pinned size register.
However, there was other code that just asserted the size was one. This patch just rips
out this code since we never moved to having more than one pinned size register. Doing
this refactoring cleans up the various places where we set up the size register.

This patch is a 50-60% progression on JetStream 2's richards-wasm.

  • JavaScriptCore.xcodeproj/project.pbxproj:
  • Sources.txt:
  • assembler/MacroAssemblerCodeRef.h:

(JSC::MacroAssemblerCodeRef::operator=):
(JSC::MacroAssemblerCodeRef::MacroAssemblerCodeRef):

  • interpreter/Interpreter.cpp:

(JSC::UnwindFunctor::operator() const):
(JSC::UnwindFunctor::copyCalleeSavesToEntryFrameCalleeSavesBuffer const):

  • interpreter/StackVisitor.cpp:

(JSC::StackVisitor::Frame::calleeSaveRegistersForUnwinding):
(JSC::StackVisitor::Frame::calleeSaveRegisters): Deleted.

  • interpreter/StackVisitor.h:
  • jit/JITOperations.cpp:
  • jit/RegisterSet.cpp:

(JSC::RegisterSet::runtimeTagRegisters):
(JSC::RegisterSet::specialRegisters):
(JSC::RegisterSet::runtimeRegisters): Deleted.

  • jit/RegisterSet.h:
  • jit/Repatch.cpp:

(JSC::linkPolymorphicCall):

  • runtime/JSFunction.cpp:

(JSC::getCalculatedDisplayName):

  • runtime/JSGlobalObject.cpp:

(JSC::JSGlobalObject::init):
(JSC::JSGlobalObject::visitChildren):

  • runtime/JSGlobalObject.h:

(JSC::JSGlobalObject::jsToWasmICCalleeStructure const):

  • runtime/VM.cpp:

(JSC::VM::VM):

  • runtime/VM.h:
  • wasm/WasmAirIRGenerator.cpp:

(JSC::Wasm::AirIRGenerator::AirIRGenerator):
(JSC::Wasm::AirIRGenerator::restoreWebAssemblyGlobalState):
(JSC::Wasm::AirIRGenerator::addCallIndirect):

  • wasm/WasmB3IRGenerator.cpp:

(JSC::Wasm::B3IRGenerator::B3IRGenerator):
(JSC::Wasm::B3IRGenerator::restoreWebAssemblyGlobalState):
(JSC::Wasm::B3IRGenerator::addCallIndirect):

  • wasm/WasmBinding.cpp:

(JSC::Wasm::wasmToWasm):

  • wasm/WasmContext.h:

(JSC::Wasm::Context::pointerToInstance):

  • wasm/WasmContextInlines.h:

(JSC::Wasm::Context::store):

  • wasm/WasmMemoryInformation.cpp:

(JSC::Wasm::getPinnedRegisters):
(JSC::Wasm::PinnedRegisterInfo::get):
(JSC::Wasm::PinnedRegisterInfo::PinnedRegisterInfo):

  • wasm/WasmMemoryInformation.h:

(JSC::Wasm::PinnedRegisterInfo::toSave const):

  • wasm/WasmOMGPlan.cpp:

(JSC::Wasm::OMGPlan::work):

  • wasm/js/JSToWasm.cpp:

(JSC::Wasm::createJSToWasmWrapper):

  • wasm/js/JSToWasmICCallee.cpp: Added.

(JSC::JSToWasmICCallee::create):
(JSC::JSToWasmICCallee::createStructure):
(JSC::JSToWasmICCallee::visitChildren):

  • wasm/js/JSToWasmICCallee.h: Added.

(JSC::JSToWasmICCallee::function):
(JSC::JSToWasmICCallee::JSToWasmICCallee):

  • wasm/js/WebAssemblyFunction.cpp:

(JSC::WebAssemblyFunction::useTagRegisters const):
(JSC::WebAssemblyFunction::calleeSaves const):
(JSC::WebAssemblyFunction::usedCalleeSaveRegisters const):
(JSC::WebAssemblyFunction::previousInstanceOffset const):
(JSC::WebAssemblyFunction::previousInstance):
(JSC::WebAssemblyFunction::jsCallEntrypointSlow):
(JSC::WebAssemblyFunction::visitChildren):
(JSC::WebAssemblyFunction::destroy):

  • wasm/js/WebAssemblyFunction.h:
  • wasm/js/WebAssemblyFunctionHeapCellType.cpp: Added.

(JSC::WebAssemblyFunctionDestroyFunc::operator() const):
(JSC::WebAssemblyFunctionHeapCellType::WebAssemblyFunctionHeapCellType):
(JSC::WebAssemblyFunctionHeapCellType::~WebAssemblyFunctionHeapCellType):
(JSC::WebAssemblyFunctionHeapCellType::finishSweep):
(JSC::WebAssemblyFunctionHeapCellType::destroy):

  • wasm/js/WebAssemblyFunctionHeapCellType.h: Added.
  • wasm/js/WebAssemblyPrototype.h:
Location:
trunk
Files:
32 edited
4 copied

Legend:

Unmodified
Added
Removed
  • trunk/JSTests/ChangeLog

    r243875 r243886  
     12019-04-04  Saam barati  <sbarati@apple.com>
     2
     3        Teach Call ICs how to call Wasm
     4        https://bugs.webkit.org/show_bug.cgi?id=196387
     5
     6        Reviewed by Filip Pizlo.
     7
     8        * wasm/function-tests/stack-trace.js:
     9
    1102019-04-04  Caio Lima  <ticaiolima@gmail.com>
    211
  • trunk/JSTests/wasm/function-tests/stack-trace.js

    r225550 r243886  
    4444    assert.truthy(stacktrace[0].indexOf("imp") !== -1); // the arrow function import named "imp".
    4545    assert.eq(stacktrace[1], "wasm-stub@[wasm code]"); // the wasm->js stub
    46     assert.eq(stacktrace[2], "<?>.wasm-function[4]@[wasm code]");
    47     assert.eq(stacktrace[3], "<?>.wasm-function[2]@[wasm code]");
    48     assert.eq(stacktrace[4], "<?>.wasm-function[3]@[wasm code]");
    49     assert.eq(stacktrace[5], "<?>.wasm-function[1]@[wasm code]");
    50     assert.eq(stacktrace[6], "wasm-stub@[wasm code]"); // wasm entry
    51 
     46    let found = false;
     47    for (let i = 0; i < stacktrace.length; ++i) {
     48        let str = stacktrace[i];
     49        if (str !== "<?>.wasm-function[4]@[wasm code]")
     50            continue;
     51        found = true;
     52        assert.eq(stacktrace[i + 1], "<?>.wasm-function[2]@[wasm code]");
     53        assert.eq(stacktrace[i + 2], "<?>.wasm-function[3]@[wasm code]");
     54        assert.eq(stacktrace[i + 3], "<?>.wasm-function[1]@[wasm code]");
     55    }
     56    assert.truthy(found);
    5257    stacktrace = null;
    5358}
  • trunk/Source/JavaScriptCore/CMakeLists.txt

    r243833 r243886  
    101101
    102102    wasm/js/JSWebAssembly.cpp
     103    wasm/js/JSToWasmICCallee.cpp
    103104    wasm/js/WebAssemblyCompileErrorConstructor.cpp
    104105    wasm/js/WebAssemblyCompileErrorPrototype.cpp
     106    wasm/js/WebAssemblyFunctionHeapCellType.cpp
    105107    wasm/js/WebAssemblyInstanceConstructor.cpp
    106108    wasm/js/WebAssemblyInstancePrototype.cpp
  • trunk/Source/JavaScriptCore/ChangeLog

    r243885 r243886  
     12019-04-04  Saam barati  <sbarati@apple.com>
     2
     3        Teach Call ICs how to call Wasm
     4        https://bugs.webkit.org/show_bug.cgi?id=196387
     5
     6        Reviewed by Filip Pizlo.
     7
     8        This patch teaches JS to call Wasm without going through the native thunk.
     9        Currently, we emit a JIT "JS" callee stub which marshals arguments from
     10        JS to Wasm. Like the native version of this, this thunk is responsible
     11        for saving and restoring the VM's current Wasm context. Instead of emitting
     12        an exception handler, we also teach the unwinder how to read the previous
     13        wasm context to restore it as it unwindws past this frame.
     14       
     15        This patch is straight forward, and leaves some areas for perf improvement:
     16        - We can teach the DFG/FTL to directly use the Wasm calling convention when
     17          it knows it's calling a single Wasm function. This way we don't shuffle
     18          registers to the stack and then back into registers.
     19        - We bail out to the slow path for mismatched arity. I opened a bug to fix
     20          optimize arity check failures: https://bugs.webkit.org/show_bug.cgi?id=196564
     21        - We bail out to the slow path Double JSValues flowing into i32 arguments.
     22          We should teach this thunk how to do that conversion directly.
     23       
     24        This patch also refactors the code to explicitly have a single pinned size register.
     25        We used pretend in some places that we could have more than one pinned size register.
     26        However, there was other code that just asserted the size was one. This patch just rips
     27        out this code since we never moved to having more than one pinned size register. Doing
     28        this refactoring cleans up the various places where we set up the size register.
     29       
     30        This patch is a 50-60% progression on JetStream 2's richards-wasm.
     31
     32        * JavaScriptCore.xcodeproj/project.pbxproj:
     33        * Sources.txt:
     34        * assembler/MacroAssemblerCodeRef.h:
     35        (JSC::MacroAssemblerCodeRef::operator=):
     36        (JSC::MacroAssemblerCodeRef::MacroAssemblerCodeRef):
     37        * interpreter/Interpreter.cpp:
     38        (JSC::UnwindFunctor::operator() const):
     39        (JSC::UnwindFunctor::copyCalleeSavesToEntryFrameCalleeSavesBuffer const):
     40        * interpreter/StackVisitor.cpp:
     41        (JSC::StackVisitor::Frame::calleeSaveRegistersForUnwinding):
     42        (JSC::StackVisitor::Frame::calleeSaveRegisters): Deleted.
     43        * interpreter/StackVisitor.h:
     44        * jit/JITOperations.cpp:
     45        * jit/RegisterSet.cpp:
     46        (JSC::RegisterSet::runtimeTagRegisters):
     47        (JSC::RegisterSet::specialRegisters):
     48        (JSC::RegisterSet::runtimeRegisters): Deleted.
     49        * jit/RegisterSet.h:
     50        * jit/Repatch.cpp:
     51        (JSC::linkPolymorphicCall):
     52        * runtime/JSFunction.cpp:
     53        (JSC::getCalculatedDisplayName):
     54        * runtime/JSGlobalObject.cpp:
     55        (JSC::JSGlobalObject::init):
     56        (JSC::JSGlobalObject::visitChildren):
     57        * runtime/JSGlobalObject.h:
     58        (JSC::JSGlobalObject::jsToWasmICCalleeStructure const):
     59        * runtime/VM.cpp:
     60        (JSC::VM::VM):
     61        * runtime/VM.h:
     62        * wasm/WasmAirIRGenerator.cpp:
     63        (JSC::Wasm::AirIRGenerator::AirIRGenerator):
     64        (JSC::Wasm::AirIRGenerator::restoreWebAssemblyGlobalState):
     65        (JSC::Wasm::AirIRGenerator::addCallIndirect):
     66        * wasm/WasmB3IRGenerator.cpp:
     67        (JSC::Wasm::B3IRGenerator::B3IRGenerator):
     68        (JSC::Wasm::B3IRGenerator::restoreWebAssemblyGlobalState):
     69        (JSC::Wasm::B3IRGenerator::addCallIndirect):
     70        * wasm/WasmBinding.cpp:
     71        (JSC::Wasm::wasmToWasm):
     72        * wasm/WasmContext.h:
     73        (JSC::Wasm::Context::pointerToInstance):
     74        * wasm/WasmContextInlines.h:
     75        (JSC::Wasm::Context::store):
     76        * wasm/WasmMemoryInformation.cpp:
     77        (JSC::Wasm::getPinnedRegisters):
     78        (JSC::Wasm::PinnedRegisterInfo::get):
     79        (JSC::Wasm::PinnedRegisterInfo::PinnedRegisterInfo):
     80        * wasm/WasmMemoryInformation.h:
     81        (JSC::Wasm::PinnedRegisterInfo::toSave const):
     82        * wasm/WasmOMGPlan.cpp:
     83        (JSC::Wasm::OMGPlan::work):
     84        * wasm/js/JSToWasm.cpp:
     85        (JSC::Wasm::createJSToWasmWrapper):
     86        * wasm/js/JSToWasmICCallee.cpp: Added.
     87        (JSC::JSToWasmICCallee::create):
     88        (JSC::JSToWasmICCallee::createStructure):
     89        (JSC::JSToWasmICCallee::visitChildren):
     90        * wasm/js/JSToWasmICCallee.h: Added.
     91        (JSC::JSToWasmICCallee::function):
     92        (JSC::JSToWasmICCallee::JSToWasmICCallee):
     93        * wasm/js/WebAssemblyFunction.cpp:
     94        (JSC::WebAssemblyFunction::useTagRegisters const):
     95        (JSC::WebAssemblyFunction::calleeSaves const):
     96        (JSC::WebAssemblyFunction::usedCalleeSaveRegisters const):
     97        (JSC::WebAssemblyFunction::previousInstanceOffset const):
     98        (JSC::WebAssemblyFunction::previousInstance):
     99        (JSC::WebAssemblyFunction::jsCallEntrypointSlow):
     100        (JSC::WebAssemblyFunction::visitChildren):
     101        (JSC::WebAssemblyFunction::destroy):
     102        * wasm/js/WebAssemblyFunction.h:
     103        * wasm/js/WebAssemblyFunctionHeapCellType.cpp: Added.
     104        (JSC::WebAssemblyFunctionDestroyFunc::operator() const):
     105        (JSC::WebAssemblyFunctionHeapCellType::WebAssemblyFunctionHeapCellType):
     106        (JSC::WebAssemblyFunctionHeapCellType::~WebAssemblyFunctionHeapCellType):
     107        (JSC::WebAssemblyFunctionHeapCellType::finishSweep):
     108        (JSC::WebAssemblyFunctionHeapCellType::destroy):
     109        * wasm/js/WebAssemblyFunctionHeapCellType.h: Added.
     110        * wasm/js/WebAssemblyPrototype.h:
     111
    11122019-04-04  Yusuke Suzuki  <ysuzuki@apple.com>
    2113
  • trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj

    r243851 r243886  
    874874                521131F71F82BF14007CCEEE /* PolyProtoAccessChain.h in Headers */ = {isa = PBXBuildFile; fileRef = 521131F61F82BF11007CCEEE /* PolyProtoAccessChain.h */; settings = {ATTRIBUTES = (Private, ); }; };
    875875                521322461ECBCE8200F65615 /* WebAssemblyFunctionBase.h in Headers */ = {isa = PBXBuildFile; fileRef = 521322441ECBCE8200F65615 /* WebAssemblyFunctionBase.h */; };
     876                523FD88E225566C9003B3DCC /* WebAssemblyFunctionHeapCellType.h in Headers */ = {isa = PBXBuildFile; fileRef = 523FD88C225566C3003B3DCC /* WebAssemblyFunctionHeapCellType.h */; };
    876877                524E9D7322092B5200A6BEEE /* AirAllocateRegistersAndStackAndGenerateCode.h in Headers */ = {isa = PBXBuildFile; fileRef = 524E9D7222092B4600A6BEEE /* AirAllocateRegistersAndStackAndGenerateCode.h */; };
    877878                5250D2D21E8DA05A0029A932 /* WasmThunks.h in Headers */ = {isa = PBXBuildFile; fileRef = 5250D2D01E8DA05A0029A932 /* WasmThunks.h */; settings = {ATTRIBUTES = (Private, ); }; };
     
    881882                52678F911A04177C006A306D /* ControlFlowProfiler.h in Headers */ = {isa = PBXBuildFile; fileRef = 52678F901A04177C006A306D /* ControlFlowProfiler.h */; settings = {ATTRIBUTES = (Private, ); }; };
    882883                526AC4B71E977C5D003500E1 /* WasmCodeBlock.h in Headers */ = {isa = PBXBuildFile; fileRef = 526AC4B51E977C5D003500E1 /* WasmCodeBlock.h */; settings = {ATTRIBUTES = (Private, ); }; };
     884                527CE35422555FE500C6F382 /* JSToWasmICCallee.h in Headers */ = {isa = PBXBuildFile; fileRef = 527CE35322555FDD00C6F382 /* JSToWasmICCallee.h */; };
    883885                52847ADC21FFB8690061A9DB /* WasmAirIRGenerator.h in Headers */ = {isa = PBXBuildFile; fileRef = 52847ADA21FFB8630061A9DB /* WasmAirIRGenerator.h */; };
    884886                52B310FB1974AE610080857C /* FunctionHasExecutedCache.h in Headers */ = {isa = PBXBuildFile; fileRef = 52B310FA1974AE610080857C /* FunctionHasExecutedCache.h */; settings = {ATTRIBUTES = (Private, ); }; };
     
    33783380                521322431ECBCE8200F65615 /* WebAssemblyFunctionBase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = WebAssemblyFunctionBase.cpp; path = js/WebAssemblyFunctionBase.cpp; sourceTree = "<group>"; };
    33793381                521322441ECBCE8200F65615 /* WebAssemblyFunctionBase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = WebAssemblyFunctionBase.h; path = js/WebAssemblyFunctionBase.h; sourceTree = "<group>"; };
     3382                523FD88C225566C3003B3DCC /* WebAssemblyFunctionHeapCellType.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = WebAssemblyFunctionHeapCellType.h; path = js/WebAssemblyFunctionHeapCellType.h; sourceTree = "<group>"; };
     3383                523FD88D225566C4003B3DCC /* WebAssemblyFunctionHeapCellType.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = WebAssemblyFunctionHeapCellType.cpp; path = js/WebAssemblyFunctionHeapCellType.cpp; sourceTree = "<group>"; };
    33803384                524E9D7122092B4500A6BEEE /* AirAllocateRegistersAndStackAndGenerateCode.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = AirAllocateRegistersAndStackAndGenerateCode.cpp; path = b3/air/AirAllocateRegistersAndStackAndGenerateCode.cpp; sourceTree = "<group>"; };
    33813385                524E9D7222092B4600A6BEEE /* AirAllocateRegistersAndStackAndGenerateCode.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = AirAllocateRegistersAndStackAndGenerateCode.h; path = b3/air/AirAllocateRegistersAndStackAndGenerateCode.h; sourceTree = "<group>"; };
     
    33903394                526AC4B51E977C5D003500E1 /* WasmCodeBlock.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WasmCodeBlock.h; sourceTree = "<group>"; };
    33913395                527773DD1AAF83AC00BDE7E8 /* RuntimeType.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RuntimeType.cpp; sourceTree = "<group>"; };
     3396                527CE35222555FDD00C6F382 /* JSToWasmICCallee.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = JSToWasmICCallee.cpp; path = js/JSToWasmICCallee.cpp; sourceTree = "<group>"; };
     3397                527CE35322555FDD00C6F382 /* JSToWasmICCallee.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = JSToWasmICCallee.h; path = js/JSToWasmICCallee.h; sourceTree = "<group>"; };
    33923398                52847AD921FFB8630061A9DB /* WasmAirIRGenerator.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = WasmAirIRGenerator.cpp; sourceTree = "<group>"; };
    33933399                52847ADA21FFB8630061A9DB /* WasmAirIRGenerator.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WasmAirIRGenerator.h; sourceTree = "<group>"; };
     
    82698275                                AD8DD6D01F6708A30004EB52 /* JSToWasm.cpp */,
    82708276                                AD8DD6CF1F67089F0004EB52 /* JSToWasm.h */,
     8277                                527CE35222555FDD00C6F382 /* JSToWasmICCallee.cpp */,
     8278                                527CE35322555FDD00C6F382 /* JSToWasmICCallee.h */,
    82718279                                ADD09AF21F624829001313C2 /* JSWebAssembly.cpp */,
    82728280                                ADD09AF31F62482E001313C2 /* JSWebAssembly.h */,
     
    82988306                                AD4937C91DDD27340077C807 /* WebAssemblyFunction.cpp */,
    82998307                                AD4937CA1DDD27340077C807 /* WebAssemblyFunction.h */,
     8308                                523FD88D225566C4003B3DCC /* WebAssemblyFunctionHeapCellType.cpp */,
     8309                                523FD88C225566C3003B3DCC /* WebAssemblyFunctionHeapCellType.h */,
    83008310                                521322431ECBCE8200F65615 /* WebAssemblyFunctionBase.cpp */,
    83018311                                521322441ECBCE8200F65615 /* WebAssemblyFunctionBase.h */,
     
    86158625                                DC69B99D1D15F914002E3C00 /* B3InferSwitches.h in Headers */,
    86168626                                0FEC85BA1BE1462F0080FF74 /* B3InsertionSet.h in Headers */,
     8627                                523FD88E225566C9003B3DCC /* WebAssemblyFunctionHeapCellType.h in Headers */,
    86178628                                0FEC85BB1BE1462F0080FF74 /* B3InsertionSetInlines.h in Headers */,
    86188629                                0FDF67D21D9C6D27001B9825 /* B3Kind.h in Headers */,
     
    88078818                                0FBB73BB1DEF8645002C009E /* DeleteAllCodeEffort.h in Headers */,
    88088819                                0F96303C1D4192CD005609D9 /* DestructionMode.h in Headers */,
     8820                                527CE35422555FE500C6F382 /* JSToWasmICCallee.h in Headers */,
    88098821                                A77A423E17A0BBFD00A8DB81 /* DFGAbstractHeap.h in Headers */,
    88108822                                A704D90317A0BAA8006BA554 /* DFGAbstractInterpreter.h in Headers */,
  • trunk/Source/JavaScriptCore/Sources.txt

    r243851 r243886  
    10151015wasm/js/JSToWasm.cpp
    10161016wasm/js/JSToWasm.h
     1017wasm/js/JSToWasmICCallee.cpp
    10171018wasm/js/JSWebAssembly.cpp
    10181019wasm/js/JSWebAssemblyCodeBlock.cpp
     
    10311032wasm/js/WebAssemblyFunction.cpp
    10321033wasm/js/WebAssemblyFunctionBase.cpp
     1034wasm/js/WebAssemblyFunctionHeapCellType.cpp
    10331035wasm/js/WebAssemblyInstanceConstructor.cpp
    10341036wasm/js/WebAssemblyInstancePrototype.cpp
  • trunk/Source/JavaScriptCore/assembler/MacroAssemblerCodeRef.h

    r242100 r243886  
    381381        ASSERT(m_codePtr);
    382382    }
     383
     384    template<PtrTag otherTag>
     385    MacroAssemblerCodeRef& operator=(const MacroAssemblerCodeRef<otherTag>& otherCodeRef)
     386    {
     387        m_codePtr = MacroAssemblerCodePtr<tag>::createFromExecutableAddress(otherCodeRef.code().template retaggedExecutableAddress<tag>());
     388        m_executableMemory = otherCodeRef.m_executableMemory;
     389        return *this;
     390    }
    383391   
    384392    // Use this only when you know that the codePtr refers to code that is
     
    444452    template<PtrTag otherTag>
    445453    MacroAssemblerCodeRef(const MacroAssemblerCodeRef<otherTag>& otherCodeRef)
    446         : m_codePtr(MacroAssemblerCodePtr<tag>::createFromExecutableAddress(otherCodeRef.code().template retaggedExecutableAddress<tag>()))
    447         , m_executableMemory(otherCodeRef.m_executableMemory)
    448     { }
     454    {
     455        *this = otherCodeRef;
     456    }
    449457
    450458    MacroAssemblerCodePtr<tag> m_codePtr;
  • trunk/Source/JavaScriptCore/interpreter/Interpreter.cpp

    r242636 r243886  
    550550        }
    551551
     552#if ENABLE(WEBASSEMBLY)
     553        if (visitor->callee().isCell()) {
     554            if (auto* jsToWasmICCallee = jsDynamicCast<JSToWasmICCallee*>(m_vm, visitor->callee().asCell()))
     555                m_vm.wasmContext.store(jsToWasmICCallee->function()->previousInstance(m_callFrame), m_vm.softStackLimit());
     556        }
     557#endif
     558
    552559        notifyDebuggerOfUnwinding(m_vm, m_callFrame);
    553560
     
    565572    {
    566573#if !ENABLE(C_LOOP) && NUMBER_OF_CALLEE_SAVES_REGISTERS > 0
    567         const RegisterAtOffsetList* currentCalleeSaves = visitor->calleeSaveRegisters();
     574        Optional<RegisterAtOffsetList> currentCalleeSaves = visitor->calleeSaveRegistersForUnwinding();
    568575
    569576        if (!currentCalleeSaves)
  • trunk/Source/JavaScriptCore/interpreter/StackVisitor.cpp

    r243232 r243886  
    3434#include "WasmCallee.h"
    3535#include "WasmIndexOrName.h"
     36#include "WebAssemblyFunction.h"
    3637#include <wtf/text/StringBuilder.h>
    3738
     
    253254}
    254255
    255 const RegisterAtOffsetList* StackVisitor::Frame::calleeSaveRegisters()
     256Optional<RegisterAtOffsetList> StackVisitor::Frame::calleeSaveRegistersForUnwinding()
    256257{
    257258    if (isInlinedFrame())
    258         return nullptr;
     259        return WTF::nullopt;
    259260
    260261#if !ENABLE(C_LOOP) && NUMBER_OF_CALLEE_SAVES_REGISTERS > 0
     
    264265        if (callee().isCell()) {
    265266            RELEASE_ASSERT(isWebAssemblyToJSCallee(callee().asCell()));
    266             return nullptr;
     267            return WTF::nullopt;
    267268        }
    268269        Wasm::Callee* wasmCallee = callee().asWasmCallee();
    269         return wasmCallee->calleeSaveRegisters();
     270        return *wasmCallee->calleeSaveRegisters();
     271    }
     272
     273    if (callee().isCell()) {
     274        if (auto* jsToWasmICCallee = jsDynamicCast<JSToWasmICCallee*>(*callee().asCell()->vm(), callee().asCell()))
     275            return jsToWasmICCallee->function()->usedCalleeSaveRegisters();
    270276    }
    271277#endif // ENABLE(WEBASSEMBLY)
    272278
    273279    if (CodeBlock* codeBlock = this->codeBlock())
    274         return codeBlock->calleeSaveRegisters();
     280        return *codeBlock->calleeSaveRegisters();
    275281
    276282#endif // !ENABLE(C_LOOP) && NUMBER_OF_CALLEE_SAVES_REGISTERS > 0
    277283
    278     return nullptr;
     284    return WTF::nullopt;
    279285}
    280286
  • trunk/Source/JavaScriptCore/interpreter/StackVisitor.h

    r243232 r243886  
    9595        JS_EXPORT_PRIVATE void computeLineAndColumn(unsigned& line, unsigned& column) const;
    9696
    97         const RegisterAtOffsetList* calleeSaveRegisters();
     97        Optional<RegisterAtOffsetList> calleeSaveRegistersForUnwinding();
    9898
    9999        ClonedArguments* createArguments();
  • trunk/Source/JavaScriptCore/jit/JITOperations.cpp

    r242991 r243886  
    7777#include "TypeProfilerLog.h"
    7878#include "VMInlines.h"
     79#include "WebAssemblyFunction.h"
    7980#include <wtf/InlineASM.h>
    8081
     
    10371038    MacroAssemblerCodePtr<JSEntryPtrTag> codePtr;
    10381039    CodeBlock* codeBlock = nullptr;
    1039     if (executable->isHostFunction())
    1040         codePtr = executable->entrypointFor(kind, MustCheckArity);
    1041     else {
     1040    if (executable->isHostFunction()) {
     1041        codePtr = jsToWasmICCodePtr(*vm, kind, callee);
     1042        if (!codePtr)
     1043            codePtr = executable->entrypointFor(kind, MustCheckArity);
     1044    } else {
    10421045        FunctionExecutable* functionExecutable = static_cast<FunctionExecutable*>(executable);
    10431046
     
    10651068        codePtr = functionExecutable->entrypointFor(kind, arity);
    10661069    }
     1070
    10671071    if (!callLinkInfo->seenOnce())
    10681072        callLinkInfo->setSeen();
  • trunk/Source/JavaScriptCore/jit/RegisterSet.cpp

    r240432 r243886  
    5959}
    6060
    61 RegisterSet RegisterSet::runtimeRegisters()
     61RegisterSet RegisterSet::runtimeTagRegisters()
    6262{
    6363#if USE(JSVALUE64)
     
    7171{
    7272    return RegisterSet(
    73         stackRegisters(), reservedHardwareRegisters(), runtimeRegisters());
     73        stackRegisters(), reservedHardwareRegisters(), runtimeTagRegisters());
    7474}
    7575
  • trunk/Source/JavaScriptCore/jit/RegisterSet.h

    r236381 r243886  
    5151    JS_EXPORT_PRIVATE static RegisterSet stackRegisters();
    5252    JS_EXPORT_PRIVATE static RegisterSet reservedHardwareRegisters();
    53     static RegisterSet runtimeRegisters();
     53    static RegisterSet runtimeTagRegisters();
    5454    static RegisterSet specialRegisters(); // The union of stack, reserved hardware, and runtime registers.
    5555    JS_EXPORT_PRIVATE static RegisterSet calleeSaveRegisters();
  • trunk/Source/JavaScriptCore/jit/Repatch.cpp

    r243626 r243886  
    976976        list = stub->variants();
    977977    else if (JSObject* oldCallee = callLinkInfo.callee())
    978         list = CallVariantList{ CallVariant(oldCallee) };
     978        list = CallVariantList { CallVariant(oldCallee) };
    979979   
    980980    list = variantListWithVariant(list, newVariant);
     
    11381138        if (variant.executable()) {
    11391139            ASSERT(variant.executable()->hasJITCodeForCall());
    1140             codePtr = variant.executable()->generatedJITCodeForCall()->addressForCall(ArityCheckNotRequired);
     1140           
     1141            codePtr = jsToWasmICCodePtr(vm, callLinkInfo.specializationKind(), variant.function());
     1142            if (!codePtr)
     1143                codePtr = variant.executable()->generatedJITCodeForCall()->addressForCall(ArityCheckNotRequired);
    11411144        } else {
    11421145            ASSERT(variant.internalFunction());
     
    12781281}
    12791282
     1283MacroAssemblerCodePtr<JSEntryPtrTag> jsToWasmICCodePtr(VM& vm, CodeSpecializationKind kind, JSObject* callee)
     1284{
     1285#if ENABLE(WEBASSEMBLY)
     1286    if (!callee)
     1287        return nullptr;
     1288    if (kind != CodeForCall)
     1289        return nullptr;
     1290    if (auto* wasmFunction = jsDynamicCast<WebAssemblyFunction*>(vm, callee))
     1291        return wasmFunction->jsCallEntrypoint();
     1292#else
     1293    UNUSED_PARAM(vm);
     1294    UNUSED_PARAM(kind);
     1295    UNUSED_PARAM(callee);
     1296#endif
     1297    return nullptr;
     1298}
     1299
    12801300} // namespace JSC
    12811301
  • trunk/Source/JavaScriptCore/jit/Repatch.h

    r232047 r243886  
    5858void resetInstanceOf(StructureStubInfo&);
    5959void ftlThunkAwareRepatchCall(CodeBlock*, CodeLocationCall<JSInternalPtrTag>, FunctionPtr<CFunctionPtrTag> newCalleeFunction);
     60MacroAssemblerCodePtr<JSEntryPtrTag> jsToWasmICCodePtr(VM&, CodeSpecializationKind, JSObject* callee);
     61
    6062
    6163} // namespace JSC
  • trunk/Source/JavaScriptCore/runtime/JSFunction.cpp

    r242991 r243886  
    4949#include "PropertyNameArray.h"
    5050#include "StackVisitor.h"
     51#include "WebAssemblyFunction.h"
    5152
    5253namespace JSC {
     
    628629String getCalculatedDisplayName(VM& vm, JSObject* object)
    629630{
     631#if ENABLE(WEBASSEMBLY)
     632    if (jsDynamicCast<JSToWasmICCallee*>(vm, object))
     633        return "wasm-stub"_s;
     634#endif
     635
    630636    if (!jsDynamicCast<JSFunction*>(vm, object) && !jsDynamicCast<InternalFunction*>(vm, object))
    631637        return emptyString();
    632 
    633638
    634639    Structure* structure = object->structure(vm);
  • trunk/Source/JavaScriptCore/runtime/JSGlobalObject.cpp

    r243560 r243886  
    10541054                init.set(WebAssemblyFunction::createStructure(init.vm, init.owner, init.owner->m_functionPrototype.get()));
    10551055            });
     1056        m_jsToWasmICCalleeStructure.initLater(
     1057            [] (const Initializer<Structure>& init) {
     1058                init.set(JSToWasmICCallee::createStructure(init.vm, init.owner, JSValue()));
     1059            });
    10561060        m_webAssemblyWrapperFunctionStructure.initLater(
    10571061            [] (const Initializer<Structure>& init) {
     
    17521756    thisObject->m_webAssemblyModuleRecordStructure.visit(visitor);
    17531757    thisObject->m_webAssemblyFunctionStructure.visit(visitor);
     1758    thisObject->m_jsToWasmICCalleeStructure.visit(visitor);
    17541759    thisObject->m_webAssemblyWrapperFunctionStructure.visit(visitor);
    17551760    thisObject->m_webAssemblyToJSCalleeStructure.visit(visitor);
  • trunk/Source/JavaScriptCore/runtime/JSGlobalObject.h

    r243617 r243886  
    401401    LazyProperty<JSGlobalObject, Structure> m_webAssemblyModuleRecordStructure;
    402402    LazyProperty<JSGlobalObject, Structure> m_webAssemblyFunctionStructure;
     403    LazyProperty<JSGlobalObject, Structure> m_jsToWasmICCalleeStructure;
    403404    LazyProperty<JSGlobalObject, Structure> m_webAssemblyWrapperFunctionStructure;
    404405    LazyProperty<JSGlobalObject, Structure> m_webAssemblyToJSCalleeStructure;
     
    765766    Structure* webAssemblyModuleRecordStructure() const { return m_webAssemblyModuleRecordStructure.get(this); }
    766767    Structure* webAssemblyFunctionStructure() const { return m_webAssemblyFunctionStructure.get(this); }
     768    Structure* jsToWasmICCalleeStructure() const { return m_jsToWasmICCalleeStructure.get(this); }
    767769    Structure* webAssemblyWrapperFunctionStructure() const { return m_webAssemblyWrapperFunctionStructure.get(this); }
    768770    Structure* webAssemblyToJSCalleeStructure() const { return m_webAssemblyToJSCalleeStructure.get(this); }
  • trunk/Source/JavaScriptCore/runtime/VM.cpp

    r243832 r243886  
    149149#include "WeakGCMapInlines.h"
    150150#include "WebAssemblyFunction.h"
     151#include "WebAssemblyFunctionHeapCellType.h"
    151152#include "WebAssemblyWrapperFunction.h"
    152153#include <wtf/ProcessID.h>
     
    281282#if ENABLE(WEBASSEMBLY)
    282283    , webAssemblyCodeBlockHeapCellType(std::make_unique<JSWebAssemblyCodeBlockHeapCellType>())
     284    , webAssemblyFunctionHeapCellType(std::make_unique<WebAssemblyFunctionHeapCellType>())
    283285#endif
    284286    , primitiveGigacageAuxiliarySpace("Primitive Gigacage Auxiliary", heap, auxiliaryHeapCellType.get(), primitiveGigacageAllocator.get())
     
    12651267#if ENABLE(WEBASSEMBLY)
    12661268DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER_SLOW(webAssemblyCodeBlockSpace, webAssemblyCodeBlockHeapCellType.get(), JSWebAssemblyCodeBlock)
    1267 DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER_SLOW(webAssemblyFunctionSpace, cellHeapCellType.get(), WebAssemblyFunction)
     1269DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER_SLOW(webAssemblyFunctionSpace, webAssemblyFunctionHeapCellType.get(), WebAssemblyFunction)
    12681270DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER_SLOW(webAssemblyWrapperFunctionSpace, cellHeapCellType.get(), WebAssemblyWrapperFunction)
    12691271#endif
  • trunk/Source/JavaScriptCore/runtime/VM.h

    r243832 r243886  
    159159class Watchpoint;
    160160class WatchpointSet;
     161class WebAssemblyFunctionHeapCellType;
    161162
    162163#if ENABLE(FTL_JIT)
     
    338339#if ENABLE(WEBASSEMBLY)
    339340    std::unique_ptr<JSWebAssemblyCodeBlockHeapCellType> webAssemblyCodeBlockHeapCellType;
     341    std::unique_ptr<WebAssemblyFunctionHeapCellType> webAssemblyFunctionHeapCellType;
    340342#endif
    341343   
  • trunk/Source/JavaScriptCore/wasm/WasmAirIRGenerator.cpp

    r243514 r243886  
    681681
    682682    if (mode != MemoryMode::Signaling) {
    683         ASSERT(!pinnedRegs.sizeRegisters[0].sizeOffset);
    684         m_memorySizeGPR = pinnedRegs.sizeRegisters[0].sizeRegister;
    685         for (const PinnedSizeRegisterInfo& regInfo : pinnedRegs.sizeRegisters)
    686             m_code.pinRegister(regInfo.sizeRegister);
     683        m_memorySizeGPR = pinnedRegs.sizeRegister;
     684        m_code.pinRegister(m_memorySizeGPR);
    687685    }
    688686
     
    824822        RegisterSet clobbers;
    825823        clobbers.set(pinnedRegs->baseMemoryPointer);
    826         for (auto info : pinnedRegs->sizeRegisters)
    827             clobbers.set(info.sizeRegister);
     824        clobbers.set(pinnedRegs->sizeRegister);
    828825
    829826        auto* patchpoint = addPatchpoint(B3::Void);
     
    835832
    836833        patchpoint->setGenerator([pinnedRegs] (CCallHelpers& jit, const B3::StackmapGenerationParams& params) {
    837             GPRReg baseMemory = pinnedRegs->baseMemoryPointer;
    838             const auto& sizeRegs = pinnedRegs->sizeRegisters;
    839             ASSERT(sizeRegs.size() >= 1);
    840             ASSERT(!sizeRegs[0].sizeOffset); // The following code assumes we start at 0, and calculates subsequent size registers relative to 0.
    841             jit.loadPtr(CCallHelpers::Address(params[0].gpr(), Instance::offsetOfCachedMemorySize()), sizeRegs[0].sizeRegister);
    842             jit.loadPtr(CCallHelpers::Address(params[0].gpr(), Instance::offsetOfCachedMemory()), baseMemory);
    843             for (unsigned i = 1; i < sizeRegs.size(); ++i)
    844                 jit.add64(CCallHelpers::TrustedImm32(-sizeRegs[i].sizeOffset), sizeRegs[0].sizeRegister, sizeRegs[i].sizeRegister);
     834            jit.loadPtr(CCallHelpers::Address(params[0].gpr(), Instance::offsetOfCachedMemorySize()), pinnedRegs->sizeRegister);
     835            jit.loadPtr(CCallHelpers::Address(params[0].gpr(), Instance::offsetOfCachedMemory()), pinnedRegs->baseMemoryPointer);
    845836        });
    846837
     
    18561847            GPRReg oldContextInstance = params[1].gpr();
    18571848            const PinnedRegisterInfo& pinnedRegs = PinnedRegisterInfo::get();
    1858             const auto& sizeRegs = pinnedRegs.sizeRegisters;
    18591849            GPRReg baseMemory = pinnedRegs.baseMemoryPointer;
    18601850            ASSERT(newContextInstance != baseMemory);
     
    18621852            jit.storePtr(baseMemory, CCallHelpers::Address(newContextInstance, Instance::offsetOfCachedStackLimit()));
    18631853            jit.storeWasmContextInstance(newContextInstance);
    1864             ASSERT(sizeRegs[0].sizeRegister != baseMemory);
    18651854            // FIXME: We should support more than one memory size register
    18661855            //   see: https://bugs.webkit.org/show_bug.cgi?id=162952
    1867             ASSERT(sizeRegs.size() == 1);
    1868             ASSERT(sizeRegs[0].sizeRegister != newContextInstance);
    1869             ASSERT(!sizeRegs[0].sizeOffset);
    1870             jit.loadPtr(CCallHelpers::Address(newContextInstance, Instance::offsetOfCachedMemorySize()), sizeRegs[0].sizeRegister); // Memory size.
     1856            ASSERT(pinnedRegs.sizeRegister != newContextInstance);
     1857            jit.loadPtr(CCallHelpers::Address(newContextInstance, Instance::offsetOfCachedMemorySize()), pinnedRegs.sizeRegister); // Memory size.
    18711858            jit.loadPtr(CCallHelpers::Address(newContextInstance, Instance::offsetOfCachedMemory()), baseMemory); // Memory::void*.
    18721859        });
  • trunk/Source/JavaScriptCore/wasm/WasmB3IRGenerator.cpp

    r243163 r243886  
    347347
    348348    if (mode != MemoryMode::Signaling) {
    349         ASSERT(!pinnedRegs.sizeRegisters[0].sizeOffset);
    350         m_memorySizeGPR = pinnedRegs.sizeRegisters[0].sizeRegister;
    351         for (const PinnedSizeRegisterInfo& regInfo : pinnedRegs.sizeRegisters)
    352             m_proc.pinRegister(regInfo.sizeRegister);
     349        m_memorySizeGPR = pinnedRegs.sizeRegister;
     350        m_proc.pinRegister(m_memorySizeGPR);
    353351    }
    354352
     
    470468        RegisterSet clobbers;
    471469        clobbers.set(pinnedRegs->baseMemoryPointer);
    472         for (auto info : pinnedRegs->sizeRegisters)
    473             clobbers.set(info.sizeRegister);
     470        clobbers.set(pinnedRegs->sizeRegister);
    474471
    475472        B3::PatchpointValue* patchpoint = block->appendNew<B3::PatchpointValue>(proc, B3::Void, origin());
     
    484481        patchpoint->setGenerator([pinnedRegs] (CCallHelpers& jit, const B3::StackmapGenerationParams& params) {
    485482            GPRReg baseMemory = pinnedRegs->baseMemoryPointer;
    486             const auto& sizeRegs = pinnedRegs->sizeRegisters;
    487             ASSERT(sizeRegs.size() >= 1);
    488             ASSERT(!sizeRegs[0].sizeOffset); // The following code assumes we start at 0, and calculates subsequent size registers relative to 0.
    489             jit.loadPtr(CCallHelpers::Address(params[0].gpr(), Instance::offsetOfCachedMemorySize()), sizeRegs[0].sizeRegister);
     483            jit.loadPtr(CCallHelpers::Address(params[0].gpr(), Instance::offsetOfCachedMemorySize()), pinnedRegs->sizeRegister);
    490484            jit.loadPtr(CCallHelpers::Address(params[0].gpr(), Instance::offsetOfCachedMemory()), baseMemory);
    491             for (unsigned i = 1; i < sizeRegs.size(); ++i)
    492                 jit.add64(CCallHelpers::TrustedImm32(-sizeRegs[i].sizeOffset), sizeRegs[0].sizeRegister, sizeRegs[i].sizeRegister);
    493485        });
    494486    }
     
    12831275            GPRReg oldContextInstance = params[1].gpr();
    12841276            const PinnedRegisterInfo& pinnedRegs = PinnedRegisterInfo::get();
    1285             const auto& sizeRegs = pinnedRegs.sizeRegisters;
    12861277            GPRReg baseMemory = pinnedRegs.baseMemoryPointer;
    12871278            ASSERT(newContextInstance != baseMemory);
     
    12891280            jit.storePtr(baseMemory, CCallHelpers::Address(newContextInstance, Instance::offsetOfCachedStackLimit()));
    12901281            jit.storeWasmContextInstance(newContextInstance);
    1291             ASSERT(sizeRegs[0].sizeRegister != baseMemory);
     1282            ASSERT(pinnedRegs.sizeRegister != baseMemory);
    12921283            // FIXME: We should support more than one memory size register
    12931284            //   see: https://bugs.webkit.org/show_bug.cgi?id=162952
    1294             ASSERT(sizeRegs.size() == 1);
    1295             ASSERT(sizeRegs[0].sizeRegister != newContextInstance);
    1296             ASSERT(!sizeRegs[0].sizeOffset);
    1297             jit.loadPtr(CCallHelpers::Address(newContextInstance, Instance::offsetOfCachedMemorySize()), sizeRegs[0].sizeRegister); // Memory size.
     1285            ASSERT(pinnedRegs.sizeRegister != newContextInstance);
     1286            jit.loadPtr(CCallHelpers::Address(newContextInstance, Instance::offsetOfCachedMemorySize()), pinnedRegs.sizeRegister); // Memory size.
    12981287            jit.loadPtr(CCallHelpers::Address(newContextInstance, Instance::offsetOfCachedMemory()), baseMemory); // Memory::void*.
    12991288        });
  • trunk/Source/JavaScriptCore/wasm/WasmBinding.cpp

    r242100 r243886  
    4949    GPRReg baseMemory = pinnedRegs.baseMemoryPointer;
    5050    ASSERT(baseMemory != scratch);
    51     const auto& sizeRegs = pinnedRegs.sizeRegisters;
    52     ASSERT(sizeRegs.size() >= 1);
    53     ASSERT(sizeRegs[0].sizeRegister != baseMemory);
    54     ASSERT(sizeRegs[0].sizeRegister != scratch);
    55     GPRReg sizeRegAsScratch = sizeRegs[0].sizeRegister;
     51    ASSERT(pinnedRegs.sizeRegister != baseMemory);
     52    ASSERT(pinnedRegs.sizeRegister != scratch);
     53    GPRReg sizeRegAsScratch = pinnedRegs.sizeRegister;
    5654
    5755    // B3's call codegen ensures that the JSCell is a WebAssemblyFunction.
     
    6866    // FIXME the following code assumes that all Wasm::Instance have the same pinned registers. https://bugs.webkit.org/show_bug.cgi?id=162952
    6967    // Set up the callee's baseMemory register as well as the memory size registers.
    70     ASSERT(!sizeRegs[0].sizeOffset); // The following code assumes we start at 0, and calculates subsequent size registers relative to 0.
    71     jit.loadPtr(JIT::Address(baseMemory, Wasm::Instance::offsetOfCachedMemorySize()), sizeRegs[0].sizeRegister); // Memory size.
     68    jit.loadPtr(JIT::Address(baseMemory, Wasm::Instance::offsetOfCachedMemorySize()), pinnedRegs.sizeRegister); // Memory size.
    7269    jit.loadPtr(JIT::Address(baseMemory, Wasm::Instance::offsetOfCachedMemory()), baseMemory); // Wasm::Memory::void*.
    73     for (unsigned i = 1; i < sizeRegs.size(); ++i) {
    74         ASSERT(sizeRegs[i].sizeRegister != baseMemory);
    75         ASSERT(sizeRegs[i].sizeRegister != scratch);
    76         jit.add64(JIT::TrustedImm32(-sizeRegs[i].sizeOffset), sizeRegs[0].sizeRegister, sizeRegs[i].sizeRegister);
    77     }
    7870
    7971    // Tail call into the callee WebAssembly function.
  • trunk/Source/JavaScriptCore/wasm/WasmContext.h

    r224020 r243886  
    3333
    3434struct Context {
    35     Instance* instance { nullptr };
    36 
    3735    Instance* load() const;
    3836    void store(Instance*, void* softStackLimit);
    3937
    4038    static bool useFastTLS();
     39
     40    Instance** pointerToInstance()
     41    {
     42        ASSERT(!useFastTLS());
     43        return &instance;
     44    }
     45
     46private:
     47    Instance* instance { nullptr };
    4148};
    4249
  • trunk/Source/JavaScriptCore/wasm/WasmContextInlines.h

    r235989 r243886  
    5656inline void Context::store(Instance* inst, void* softStackLimit)
    5757{
     58    if (inst)
     59        inst->setCachedStackLimit(softStackLimit);
     60
    5861#if ENABLE(FAST_TLS_JIT)
    5962    if (useFastTLS())
    6063        _pthread_setspecific_direct(WTF_WASM_CONTEXT_KEY, bitwise_cast<void*>(inst));
     64    else
    6165#endif
    62     instance = inst;
    63     if (instance)
    64         instance->setCachedStackLimit(softStackLimit);
     66        instance = inst;
    6567}
    6668
  • trunk/Source/JavaScriptCore/wasm/WasmMemoryInformation.cpp

    r235989 r243886  
    4545        if (!remainingPinnedRegisters || RegisterSet::stackRegisters().get(reg))
    4646            return;
     47        if (RegisterSet::runtimeTagRegisters().get(reg)) {
     48            // Since we don't need to, we currently don't pick from the tag registers to allow
     49            // JS->Wasm stubs to freely use these registers.
     50            return;
     51        }
    4752        --remainingPinnedRegisters;
    4853        registers.append(gpr);
     
    5661    static std::once_flag staticPinnedRegisterInfoFlag;
    5762    std::call_once(staticPinnedRegisterInfoFlag, [] () {
    58         Vector<PinnedSizeRegisterInfo> sizeRegisters;
    59         GPRReg baseMemoryPointer = InvalidGPRReg;
    60         GPRReg wasmContextInstancePointer = InvalidGPRReg;
    61 
    62         // FIXME: We should support more than one memory size register, and we should allow different
    63         //        WebAssembly.Instance to have different pins. Right now we take a vector with only one entry.
    64         //        If we have more than one size register, we can have one for each load size class.
    65         //        see: https://bugs.webkit.org/show_bug.cgi?id=162952
    66         Vector<unsigned> pinnedSizes = { 0 };
    67         unsigned numberOfPinnedRegisters = pinnedSizes.size() + 1;
     63        unsigned numberOfPinnedRegisters = 2;
    6864        if (!Context::useFastTLS())
    6965            ++numberOfPinnedRegisters;
    7066        Vector<GPRReg> pinnedRegs = getPinnedRegisters(numberOfPinnedRegisters);
    7167
    72         baseMemoryPointer = pinnedRegs.takeLast();
     68        GPRReg baseMemoryPointer = pinnedRegs.takeLast();
     69        GPRReg sizeRegister = pinnedRegs.takeLast();
     70        GPRReg wasmContextInstancePointer = InvalidGPRReg;
    7371        if (!Context::useFastTLS())
    7472            wasmContextInstancePointer = pinnedRegs.takeLast();
    7573
    76         ASSERT(pinnedSizes.size() == pinnedRegs.size());
    77         for (unsigned i = 0; i < pinnedSizes.size(); ++i)
    78             sizeRegisters.append({ pinnedRegs[i], pinnedSizes[i] });
    79         staticPinnedRegisterInfo.construct(WTFMove(sizeRegisters), baseMemoryPointer, wasmContextInstancePointer);
     74        staticPinnedRegisterInfo.construct(sizeRegister, baseMemoryPointer, wasmContextInstancePointer);
    8075    });
    8176
     
    8378}
    8479
    85 PinnedRegisterInfo::PinnedRegisterInfo(Vector<PinnedSizeRegisterInfo>&& sizeRegisters, GPRReg baseMemoryPointer, GPRReg wasmContextInstancePointer)
    86     : sizeRegisters(WTFMove(sizeRegisters))
     80PinnedRegisterInfo::PinnedRegisterInfo(GPRReg sizeRegister, GPRReg baseMemoryPointer, GPRReg wasmContextInstancePointer)
     81    : sizeRegister(sizeRegister)
    8782    , baseMemoryPointer(baseMemoryPointer)
    8883    , wasmContextInstancePointer(wasmContextInstancePointer)
  • trunk/Source/JavaScriptCore/wasm/WasmMemoryInformation.h

    r237823 r243886  
    4646class PinnedRegisterInfo {
    4747public:
    48     PinnedRegisterInfo(Vector<PinnedSizeRegisterInfo>&&, GPRReg, GPRReg);
     48    PinnedRegisterInfo(GPRReg, GPRReg, GPRReg);
    4949
    5050    static const PinnedRegisterInfo& get();
     
    5656        if (wasmContextInstancePointer != InvalidGPRReg)
    5757            result.set(wasmContextInstancePointer);
    58         if (mode != MemoryMode::Signaling) {
    59             for (const auto& info : sizeRegisters)
    60                 result.set(info.sizeRegister);
    61         }
     58        if (mode != MemoryMode::Signaling)
     59            result.set(sizeRegister);
    6260        return result;
    6361    }
    6462
    65     Vector<PinnedSizeRegisterInfo> sizeRegisters;
     63    GPRReg sizeRegister;
    6664    GPRReg baseMemoryPointer;
    6765    GPRReg wasmContextInstancePointer;
  • trunk/Source/JavaScriptCore/wasm/WasmOMGPlan.cpp

    r235786 r243886  
    139139        LockHolder holder(m_codeBlock->m_lock);
    140140
    141         auto repatchCalls = [&] (const Vector<UnlinkedWasmToWasmCall>&  callsites) {
     141        auto repatchCalls = [&] (const Vector<UnlinkedWasmToWasmCall>& callsites) {
    142142            for (auto& call : callsites) {
    143143                dataLogLnIf(WasmOMGPlanInternal::verbose, "Considering repatching call at: ", RawPointer(call.callLocation.dataLocation()), " that targets ", call.functionIndexSpace);
  • trunk/Source/JavaScriptCore/wasm/js/JSToWasm.cpp

    r242123 r243886  
    214214
    215215        GPRReg currentInstanceGPR = Context::useFastTLS() ? baseMemory : wasmContextInstanceGPR;
    216         if (mode != MemoryMode::Signaling) {
    217             const auto& sizeRegs = pinnedRegs.sizeRegisters;
    218             ASSERT(sizeRegs.size() >= 1);
    219             ASSERT(!sizeRegs[0].sizeOffset); // The following code assumes we start at 0, and calculates subsequent size registers relative to 0.
    220             jit.loadPtr(CCallHelpers::Address(currentInstanceGPR, Wasm::Instance::offsetOfCachedMemorySize()), sizeRegs[0].sizeRegister);
    221             for (unsigned i = 1; i < sizeRegs.size(); ++i)
    222                 jit.add64(CCallHelpers::TrustedImm32(-sizeRegs[i].sizeOffset), sizeRegs[0].sizeRegister, sizeRegs[i].sizeRegister);
    223         }
     216        if (mode != MemoryMode::Signaling)
     217            jit.loadPtr(CCallHelpers::Address(currentInstanceGPR, Wasm::Instance::offsetOfCachedMemorySize()), pinnedRegs.sizeRegister);
    224218
    225219        jit.loadPtr(CCallHelpers::Address(currentInstanceGPR, Wasm::Instance::offsetOfCachedMemory()), baseMemory);
  • trunk/Source/JavaScriptCore/wasm/js/JSToWasmICCallee.cpp

    r243885 r243886  
    11/*
    2  * Copyright (C) 2016 Apple Inc. All rights reserved.
    3  * Copyright (C) 2018 Oleksandr Skachkov <gskachkov@gmail.com>.
     2 * Copyright (C) 2019 Apple Inc. All rights reserved.
    43 *
    54 * Redistribution and use in source and binary forms, with or without
     
    2524 */
    2625
    27 #pragma once
     26#include "config.h"
     27#include "JSToWasmICCallee.h"
    2828
    2929#if ENABLE(WEBASSEMBLY)
    3030
    31 #include "JSDestructibleObject.h"
    32 #include "JSObject.h"
     31#include "WebAssemblyFunction.h"
    3332
    3433namespace JSC {
    3534
    36 class WebAssemblyPrototype final : public JSNonFinalObject {
    37 public:
    38     typedef JSNonFinalObject Base;
    39     static const unsigned StructureFlags = Base::StructureFlags | HasStaticPropertyTable;
     35const ClassInfo JSToWasmICCallee::s_info = { "JSToWasmICCallee", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSToWasmICCallee) };
    4036
    41     static WebAssemblyPrototype* create(VM&, JSGlobalObject*, Structure*);
    42     static Structure* createStructure(VM&, JSGlobalObject*, JSValue);
    43     JS_EXPORT_PRIVATE static void webAssemblyModuleValidateAsync(ExecState*, JSPromiseDeferred*, Vector<uint8_t>&&);
    44     JS_EXPORT_PRIVATE static void webAssemblyModuleInstantinateAsync(ExecState*, JSPromiseDeferred*, Vector<uint8_t>&&, JSObject*);
     37JSToWasmICCallee* JSToWasmICCallee::create(VM& vm, JSGlobalObject* globalObject, WebAssemblyFunction* function)
     38{
     39    auto* structure = globalObject->jsToWasmICCalleeStructure();
     40    JSToWasmICCallee* result = new (NotNull, allocateCell<JSToWasmICCallee>(vm.heap)) JSToWasmICCallee(vm, globalObject, structure);
     41    result->finishCreation(vm);
     42    result->m_function.set(vm, result, function);
     43    return result;
     44}
    4545
    46     DECLARE_INFO;
     46Structure* JSToWasmICCallee::createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
     47{
     48    return Structure::create(vm, globalObject, prototype, TypeInfo(JSCalleeType, StructureFlags), info());
     49}
    4750
    48     static JSValue instantiate(ExecState*, JSPromiseDeferred*, const Identifier&, JSValue);
     51void JSToWasmICCallee::visitChildren(JSCell* cell, SlotVisitor& visitor)
     52{
     53    JSToWasmICCallee* thisObject = jsCast<JSToWasmICCallee*>(cell);
     54    ASSERT_GC_OBJECT_INHERITS(thisObject, info());
    4955
    50 protected:
    51     void finishCreation(VM&, JSGlobalObject*);
    52 
    53 private:
    54     WebAssemblyPrototype(VM&, Structure*);
    55 };
    56 
    57 EncodedJSValue JSC_HOST_CALL webAssemblyCompileStreamingInternal(ExecState*);
    58 EncodedJSValue JSC_HOST_CALL webAssemblyInstantiateStreamingInternal(ExecState*);
     56    Base::visitChildren(thisObject, visitor);
     57    visitor.append(thisObject->m_function);
     58}
    5959
    6060} // namespace JSC
  • trunk/Source/JavaScriptCore/wasm/js/JSToWasmICCallee.h

    r243885 r243886  
    11/*
    2  * Copyright (C) 2017 Apple Inc. All rights reserved.
     2 * Copyright (C) 2019 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    2626#pragma once
    2727
     28#include "JSCallee.h"
     29
     30namespace JSC {
     31
    2832#if ENABLE(WEBASSEMBLY)
    2933
    30 namespace JSC { namespace Wasm {
     34class WebAssemblyFunction;
    3135
    32 class Instance;
     36class JSToWasmICCallee : public JSCallee {
     37    using Base = JSCallee;
     38public:
     39    DECLARE_INFO;
    3340
    34 struct Context {
    35     Instance* instance { nullptr };
     41    static JSToWasmICCallee* create(VM&, JSGlobalObject*, WebAssemblyFunction*);
     42    static Structure* createStructure(VM&, JSGlobalObject*, JSValue);
    3643
    37     Instance* load() const;
    38     void store(Instance*, void* softStackLimit);
     44    WebAssemblyFunction* function() { return m_function.get(); }
    3945
    40     static bool useFastTLS();
     46private:
     47    JSToWasmICCallee(VM& vm, JSGlobalObject* globalObject, Structure* structure)
     48        : Base(vm, globalObject, structure)
     49    { }
     50    static void visitChildren(JSCell*, SlotVisitor&);
     51
     52    WriteBarrier<WebAssemblyFunction> m_function;
    4153};
    4254
    43 } } // namespace JSC::Wasm
     55#endif // ENABLE(WEBASSEMBLY)
    4456
    45 #endif // ENABLE(WEBASSEMBLY)
     57} // namespace JSC
  • trunk/Source/JavaScriptCore/wasm/js/WebAssemblyFunction.cpp

    r243051 r243886  
    3737#include "JSWebAssemblyRuntimeError.h"
    3838#include "LLIntThunks.h"
     39#include "LinkBuffer.h"
    3940#include "ProtoCallFrame.h"
    4041#include "VM.h"
    4142#include "WasmCallee.h"
     43#include "WasmCallingConvention.h"
    4244#include "WasmContextInlines.h"
    4345#include "WasmFormat.h"
    4446#include "WasmMemory.h"
     47#include "WasmMemoryInformation.h"
     48#include "WasmModuleInformation.h"
    4549#include "WasmSignatureInlines.h"
    4650#include <wtf/FastTLS.h>
     
    149153}
    150154
     155bool WebAssemblyFunction::useTagRegisters() const
     156{
     157    const auto& signature = Wasm::SignatureInformation::get(signatureIndex());
     158    return signature.argumentCount() || signature.returnType() != Wasm::Void;
     159}
     160
     161RegisterSet WebAssemblyFunction::calleeSaves() const
     162{
     163    RegisterSet toSave = Wasm::PinnedRegisterInfo::get().toSave(instance()->memoryMode());
     164    if (useTagRegisters()) {
     165        RegisterSet tagRegisters = RegisterSet::runtimeTagRegisters();
     166        // We rely on these being disjoint sets.
     167#if !ASSERT_DISABLED
     168        for (Reg reg : tagRegisters)
     169            ASSERT(!toSave.contains(reg));
     170#endif
     171        toSave.merge(tagRegisters);
     172    }
     173    return toSave;
     174}
     175
     176RegisterAtOffsetList WebAssemblyFunction::usedCalleeSaveRegisters() const
     177{
     178    return RegisterAtOffsetList { calleeSaves(), RegisterAtOffsetList::OffsetBaseType::FramePointerBased };
     179}
     180
     181ptrdiff_t WebAssemblyFunction::previousInstanceOffset() const
     182{
     183    ptrdiff_t result = calleeSaves().numberOfSetRegisters() * sizeof(CPURegister);
     184    result = -result - sizeof(CPURegister);
     185#if !ASSERT_DISABLED
     186    ptrdiff_t minOffset = 1;
     187    for (const RegisterAtOffset& regAtOffset : usedCalleeSaveRegisters()) {
     188        ptrdiff_t offset = regAtOffset.offset();
     189        ASSERT(offset < 0);
     190        minOffset = std::min(offset, minOffset);
     191    }
     192    ASSERT(minOffset - static_cast<ptrdiff_t>(sizeof(CPURegister)) == result);
     193#endif
     194    return result;
     195}
     196
     197Wasm::Instance* WebAssemblyFunction::previousInstance(CallFrame* callFrame)
     198{
     199    ASSERT(callFrame->callee().rawPtr() == m_jsToWasmICCallee.get());
     200    auto* result = *bitwise_cast<Wasm::Instance**>(bitwise_cast<char*>(callFrame) + previousInstanceOffset());
     201    return result;
     202}
     203
     204MacroAssemblerCodePtr<JSEntryPtrTag> WebAssemblyFunction::jsCallEntrypointSlow()
     205{
     206    VM& vm = *this->vm();
     207    CCallHelpers jit;
     208
     209    const auto& signature = Wasm::SignatureInformation::get(signatureIndex());
     210    const auto& pinnedRegs = Wasm::PinnedRegisterInfo::get();
     211    RegisterAtOffsetList registersToSpill = usedCalleeSaveRegisters();
     212
     213    auto& moduleInformation = instance()->instance().module().moduleInformation();
     214
     215    unsigned totalFrameSize = registersToSpill.size() * sizeof(CPURegister);
     216    totalFrameSize += sizeof(CPURegister); // Slot for the VM's previous wasm instance.
     217    totalFrameSize += Wasm::WasmCallingConvention::headerSizeInBytes();
     218    totalFrameSize -= sizeof(CallerFrameAndPC);
     219
     220    unsigned numGPRs = 0;
     221    unsigned numFPRs = 0;
     222    bool argumentsIncludeI64 = false;
     223    for (unsigned i = 0; i < signature.argumentCount(); i++) {
     224        switch (signature.argument(i)) {
     225        case Wasm::I64:
     226            argumentsIncludeI64 = true;
     227            break;
     228        case Wasm::I32:
     229            if (numGPRs >= Wasm::wasmCallingConvention().m_gprArgs.size())
     230                totalFrameSize += sizeof(CPURegister);
     231            ++numGPRs;
     232            break;
     233        case Wasm::F32:
     234        case Wasm::F64:
     235            if (numFPRs >= Wasm::wasmCallingConvention().m_fprArgs.size())
     236                totalFrameSize += sizeof(CPURegister);
     237            ++numFPRs;
     238            break;
     239        default:
     240            RELEASE_ASSERT_NOT_REACHED();
     241        }
     242    }
     243
     244    if (argumentsIncludeI64)
     245        return nullptr;
     246
     247    totalFrameSize = WTF::roundUpToMultipleOf(stackAlignmentBytes(), totalFrameSize);
     248
     249    jit.emitFunctionPrologue();
     250    jit.subPtr(MacroAssembler::TrustedImm32(totalFrameSize), MacroAssembler::stackPointerRegister);
     251    jit.store64(CCallHelpers::TrustedImm64(0), CCallHelpers::addressFor(CallFrameSlot::codeBlock));
     252
     253    for (const RegisterAtOffset& regAtOffset : registersToSpill) {
     254        GPRReg reg = regAtOffset.reg().gpr();
     255        ptrdiff_t offset = regAtOffset.offset();
     256        jit.storePtr(reg, CCallHelpers::Address(GPRInfo::callFrameRegister, offset));
     257    }
     258
     259    GPRReg scratchGPR = Wasm::wasmCallingConventionAir().prologueScratch(1);
     260    GPRReg scratch2GPR = Wasm::wasmCallingConventionAir().prologueScratch(0);
     261    jit.loadPtr(vm.addressOfSoftStackLimit(), scratch2GPR);
     262
     263    CCallHelpers::JumpList slowPath;
     264    slowPath.append(jit.branchPtr(CCallHelpers::Above, MacroAssembler::stackPointerRegister, GPRInfo::callFrameRegister));
     265    slowPath.append(jit.branchPtr(CCallHelpers::Below, MacroAssembler::stackPointerRegister, scratch2GPR));
     266
     267    // Ensure:
     268    // argCountPlusThis - 1 >= signature.argumentCount()
     269    // argCountPlusThis >= signature.argumentCount() + 1
     270    // FIXME: We should handle mismatched arity
     271    // https://bugs.webkit.org/show_bug.cgi?id=196564
     272    slowPath.append(jit.branch32(CCallHelpers::Below,
     273        CCallHelpers::payloadFor(CallFrameSlot::argumentCount), CCallHelpers::TrustedImm32(signature.argumentCount() + 1)));
     274
     275    if (useTagRegisters())
     276        jit.emitMaterializeTagCheckRegisters();
     277
     278    // First we do stack slots for FPRs so we can use FPR argument registers as scratch.
     279    // After that, we handle FPR argument registers.
     280    // We also handle all GPR types here as we have GPR scratch registers.
     281    {
     282        CCallHelpers::Address calleeFrame = CCallHelpers::Address(MacroAssembler::stackPointerRegister, -static_cast<ptrdiff_t>(sizeof(CallerFrameAndPC)));
     283        numGPRs = 0;
     284        numFPRs = 0;
     285        FPRReg scratchFPR = Wasm::wasmCallingConvention().m_fprArgs[0].fpr();
     286
     287        ptrdiff_t jsOffset = CallFrameSlot::firstArgument * sizeof(EncodedJSValue);
     288
     289        ptrdiff_t wasmOffset = CallFrame::headerSizeInRegisters * sizeof(CPURegister);
     290        for (unsigned i = 0; i < signature.argumentCount(); i++) {
     291            switch (signature.argument(i)) {
     292            case Wasm::I32:
     293                jit.load64(CCallHelpers::Address(GPRInfo::callFrameRegister, jsOffset), scratchGPR);
     294                slowPath.append(jit.branchIfNotInt32(scratchGPR));
     295                if (numGPRs >= Wasm::wasmCallingConvention().m_gprArgs.size()) {
     296                    jit.store32(scratchGPR, calleeFrame.withOffset(wasmOffset));
     297                    wasmOffset += sizeof(CPURegister);
     298                } else {
     299                    jit.zeroExtend32ToPtr(scratchGPR, Wasm::wasmCallingConvention().m_gprArgs[numGPRs].gpr());
     300                    ++numGPRs;
     301                }
     302                break;
     303            case Wasm::F32:
     304            case Wasm::F64:
     305                if (numFPRs >= Wasm::wasmCallingConvention().m_fprArgs.size()) {
     306                    jit.load64(CCallHelpers::Address(GPRInfo::callFrameRegister, jsOffset), scratchGPR);
     307                    slowPath.append(jit.branchIfNotNumber(scratchGPR));
     308                    auto isInt32 = jit.branchIfInt32(scratchGPR);
     309                    if (signature.argument(i) == Wasm::F32) {
     310                        jit.unboxDouble(scratchGPR, scratchGPR, scratchFPR);
     311                        jit.convertDoubleToFloat(scratchFPR, scratchFPR);
     312                        jit.storeFloat(scratchFPR, calleeFrame.withOffset(wasmOffset));
     313                    } else {
     314                        jit.add64(GPRInfo::tagTypeNumberRegister, scratchGPR, scratchGPR);
     315                        jit.store64(scratchGPR, calleeFrame.withOffset(wasmOffset));
     316                    }
     317                    auto done = jit.jump();
     318
     319                    isInt32.link(&jit);
     320                    if (signature.argument(i) == Wasm::F32) {
     321                        jit.convertInt32ToFloat(scratchGPR, scratchFPR);
     322                        jit.storeFloat(scratchFPR, calleeFrame.withOffset(wasmOffset));
     323                    } else {
     324                        jit.convertInt32ToDouble(scratchGPR, scratchFPR);
     325                        jit.storeDouble(scratchFPR, calleeFrame.withOffset(wasmOffset));
     326                    }
     327                    done.link(&jit);
     328
     329                    wasmOffset += sizeof(CPURegister);
     330                } else
     331                    ++numFPRs;
     332                break;
     333            default:
     334                RELEASE_ASSERT_NOT_REACHED();
     335            }
     336
     337            jsOffset += sizeof(EncodedJSValue);
     338        }
     339    }
     340
     341    // Now handle FPR arguments in registers.
     342    {
     343        numFPRs = 0;
     344        ptrdiff_t jsOffset = CallFrameSlot::firstArgument * sizeof(EncodedJSValue);
     345        for (unsigned i = 0; i < signature.argumentCount(); i++) {
     346            switch (signature.argument(i)) {
     347            case Wasm::F32:
     348            case Wasm::F64:
     349                if (numFPRs < Wasm::wasmCallingConvention().m_fprArgs.size()) {
     350                    FPRReg argFPR = Wasm::wasmCallingConvention().m_fprArgs[numFPRs].fpr();
     351                    jit.load64(CCallHelpers::Address(GPRInfo::callFrameRegister, jsOffset), scratchGPR);
     352                    slowPath.append(jit.branchIfNotNumber(scratchGPR));
     353                    auto isInt32 = jit.branchIfInt32(scratchGPR);
     354                    jit.unboxDouble(scratchGPR, scratchGPR, argFPR);
     355                    if (signature.argument(i) == Wasm::F32)
     356                        jit.convertDoubleToFloat(argFPR, argFPR);
     357                    auto done = jit.jump();
     358
     359                    isInt32.link(&jit);
     360                    if (signature.argument(i) == Wasm::F32)
     361                        jit.convertInt32ToFloat(scratchGPR, argFPR);
     362                    else
     363                        jit.convertInt32ToDouble(scratchGPR, argFPR);
     364
     365                    done.link(&jit);
     366                    ++numFPRs;
     367                }
     368                break;
     369            default:
     370                break;
     371            }
     372
     373            jsOffset += sizeof(EncodedJSValue);
     374        }
     375    }
     376
     377    // At this point, we're committed to doing a fast call.
     378
     379    if (Wasm::Context::useFastTLS())
     380        jit.loadWasmContextInstance(scratchGPR);
     381    else
     382        jit.loadPtr(vm.wasmContext.pointerToInstance(), scratchGPR);
     383    ptrdiff_t previousInstanceOffset = this->previousInstanceOffset();
     384    jit.storePtr(scratchGPR, CCallHelpers::Address(GPRInfo::callFrameRegister, previousInstanceOffset));
     385
     386    jit.move(CCallHelpers::TrustedImmPtr(&instance()->instance()), scratchGPR);
     387    if (Wasm::Context::useFastTLS())
     388        jit.storeWasmContextInstance(scratchGPR);
     389    else {
     390        jit.move(scratchGPR, pinnedRegs.wasmContextInstancePointer);
     391        jit.storePtr(scratchGPR, vm.wasmContext.pointerToInstance());
     392    }
     393    // This contains the cached stack limit still.
     394    jit.storePtr(scratch2GPR, CCallHelpers::Address(scratchGPR, Wasm::Instance::offsetOfCachedStackLimit()));
     395
     396    if (!!moduleInformation.memory) {
     397        GPRReg baseMemory = pinnedRegs.baseMemoryPointer;
     398
     399        if (instance()->memoryMode() != Wasm::MemoryMode::Signaling) {
     400            ASSERT(pinnedRegs.sizeRegister != scratchGPR);
     401            jit.loadPtr(CCallHelpers::Address(scratchGPR, Wasm::Instance::offsetOfCachedMemorySize()), pinnedRegs.sizeRegister);
     402        }
     403
     404        jit.loadPtr(CCallHelpers::Address(scratchGPR, Wasm::Instance::offsetOfCachedMemory()), baseMemory);
     405    }
     406
     407    // We use this callee to indicate how to unwind past these types of frames:
     408    // 1. We need to know where to get callee saves.
     409    // 2. We need to know to restore the previous wasm context.
     410    if (!m_jsToWasmICCallee)
     411        m_jsToWasmICCallee.set(vm, this, JSToWasmICCallee::create(vm, globalObject(), this));
     412    jit.storePtr(CCallHelpers::TrustedImmPtr(m_jsToWasmICCallee.get()), CCallHelpers::addressFor(CallFrameSlot::callee));
     413
     414    {
     415        // FIXME: Currently we just do an indirect jump. But we should teach the Module
     416        // how to repatch us:
     417        // https://bugs.webkit.org/show_bug.cgi?id=196570
     418        jit.loadPtr(entrypointLoadLocation(), scratchGPR);
     419        jit.call(scratchGPR, WasmEntryPtrTag);
     420    }
     421
     422    ASSERT(!RegisterSet::runtimeTagRegisters().contains(GPRInfo::nonPreservedNonReturnGPR));
     423    jit.loadPtr(CCallHelpers::Address(GPRInfo::callFrameRegister, previousInstanceOffset), GPRInfo::nonPreservedNonReturnGPR);
     424    if (Wasm::Context::useFastTLS())
     425        jit.storeWasmContextInstance(GPRInfo::nonPreservedNonReturnGPR);
     426    else
     427        jit.storePtr(GPRInfo::nonPreservedNonReturnGPR, vm.wasmContext.pointerToInstance());
     428
     429    switch (signature.returnType()) {
     430    case Wasm::Void:
     431        jit.moveTrustedValue(jsUndefined(), JSValueRegs { GPRInfo::returnValueGPR });
     432        break;
     433    case Wasm::I32:
     434        jit.zeroExtend32ToPtr(GPRInfo::returnValueGPR, GPRInfo::returnValueGPR);
     435        jit.boxInt32(GPRInfo::returnValueGPR, JSValueRegs { GPRInfo::returnValueGPR });
     436        break;
     437    case Wasm::F32:
     438        jit.convertFloatToDouble(FPRInfo::returnValueFPR, FPRInfo::returnValueFPR);
     439        FALLTHROUGH;
     440    case Wasm::F64: {
     441        jit.moveTrustedValue(jsNumber(pureNaN()), JSValueRegs { GPRInfo::returnValueGPR });
     442        auto isNaN = jit.branchIfNaN(FPRInfo::returnValueFPR);
     443        jit.boxDouble(FPRInfo::returnValueFPR, JSValueRegs { GPRInfo::returnValueGPR });
     444        isNaN.link(&jit);
     445        break;
     446    }
     447    case Wasm::I64:
     448    case Wasm::Func:
     449    case Wasm::Anyfunc:
     450        return nullptr;
     451    default:
     452        break;
     453    }
     454
     455    auto emitRestoreCalleeSaves = [&] {
     456        for (const RegisterAtOffset& regAtOffset : registersToSpill) {
     457            GPRReg reg = regAtOffset.reg().gpr();
     458            ASSERT(reg != GPRInfo::returnValueGPR);
     459            ptrdiff_t offset = regAtOffset.offset();
     460            jit.loadPtr(CCallHelpers::Address(GPRInfo::callFrameRegister, offset), reg);
     461        }
     462    };
     463
     464    emitRestoreCalleeSaves();
     465
     466    jit.emitFunctionEpilogue();
     467    jit.ret();
     468
     469    slowPath.link(&jit);
     470    emitRestoreCalleeSaves();
     471    jit.move(CCallHelpers::TrustedImmPtr(this), GPRInfo::regT0);
     472    jit.emitFunctionEpilogue();
     473    auto jumpToHostCallThunk = jit.jump();
     474
     475    LinkBuffer linkBuffer(jit, nullptr, JITCompilationCanFail);
     476    if (UNLIKELY(linkBuffer.didFailToAllocate()))
     477        return nullptr;
     478
     479    linkBuffer.link(jumpToHostCallThunk, CodeLocationLabel<JSEntryPtrTag>(executable()->entrypointFor(CodeForCall, MustCheckArity).executableAddress()));
     480    m_jsCallEntrypoint = FINALIZE_CODE(linkBuffer, WasmEntryPtrTag, "JS->Wasm IC");
     481    return m_jsCallEntrypoint.code();
     482}
     483
    151484WebAssemblyFunction* WebAssemblyFunction::create(VM& vm, JSGlobalObject* globalObject, Structure* structure, unsigned length, const String& name, JSWebAssemblyInstance* instance, Wasm::Callee& jsEntrypoint, Wasm::WasmToWasmImportableFunction::LoadLocation wasmToWasmEntrypointLoadLocation, Wasm::SignatureIndex signatureIndex)
    152485{
     
    170503{ }
    171504
     505void WebAssemblyFunction::visitChildren(JSCell* cell, SlotVisitor& visitor)
     506{
     507    WebAssemblyFunction* thisObject = jsCast<WebAssemblyFunction*>(cell);
     508    ASSERT_GC_OBJECT_INHERITS(thisObject, info());
     509
     510    Base::visitChildren(thisObject, visitor);
     511    visitor.append(thisObject->m_jsToWasmICCallee);
     512}
     513
     514void WebAssemblyFunction::destroy(JSCell* cell)
     515{
     516    static_cast<WebAssemblyFunction*>(cell)->WebAssemblyFunction::~WebAssemblyFunction();
     517}
     518
    172519} // namespace JSC
    173520
  • trunk/Source/JavaScriptCore/wasm/js/WebAssemblyFunction.h

    r243051 r243886  
    2828#if ENABLE(WEBASSEMBLY)
    2929
     30#include "JSToWasmICCallee.h"
    3031#include "MacroAssemblerCodeRef.h"
    3132#include "WasmCallee.h"
     
    4950
    5051    const static unsigned StructureFlags = Base::StructureFlags;
     52
     53    static const bool needsDestruction = true;
     54    static void destroy(JSCell*);
    5155
    5256    template<typename CellType, SubspaceAccess mode>
     
    7579    static ptrdiff_t offsetOfEntrypointLoadLocation() { return OBJECT_OFFSETOF(WebAssemblyFunction, m_importableFunction) + WasmToWasmImportableFunction::offsetOfEntrypointLoadLocation(); }
    7680
     81    MacroAssemblerCodePtr<JSEntryPtrTag> jsCallEntrypoint()
     82    {
     83        if (m_jsCallEntrypoint)
     84            return m_jsCallEntrypoint.code();
     85        return jsCallEntrypointSlow();
     86    }
     87
     88    RegisterAtOffsetList usedCalleeSaveRegisters() const;
     89    Wasm::Instance* previousInstance(CallFrame*);
     90
    7791private:
     92    static void visitChildren(JSCell*, SlotVisitor&);
    7893    WebAssemblyFunction(VM&, JSGlobalObject*, Structure*, Wasm::Callee& jsEntrypoint, WasmToWasmImportableFunction::LoadLocation entrypointLoadLocation, Wasm::SignatureIndex);
     94
     95    MacroAssemblerCodePtr<JSEntryPtrTag> jsCallEntrypointSlow();
     96    ptrdiff_t previousInstanceOffset() const;
     97    bool useTagRegisters() const;
     98
     99    RegisterSet calleeSaves() const;
    79100
    80101    // It's safe to just hold the raw WasmToWasmImportableFunction/jsEntrypoint because we have a reference
     
    83104    MacroAssemblerCodePtr<WasmEntryPtrTag> m_jsEntrypoint;
    84105    WasmToWasmImportableFunction m_importableFunction;
     106    WriteBarrier<JSToWasmICCallee> m_jsToWasmICCallee;
     107    // Used for JS calling into Wasm.
     108    MacroAssemblerCodeRef<JSEntryPtrTag> m_jsCallEntrypoint;
    85109};
    86110
  • trunk/Source/JavaScriptCore/wasm/js/WebAssemblyFunctionHeapCellType.cpp

    r243885 r243886  
    11/*
    2  * Copyright (C) 2017 Apple Inc. All rights reserved.
     2 * Copyright (C) 2019 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    2121 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    2222 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
    23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
    2424 */
    2525
    26 #pragma once
     26#include "config.h"
     27#include "WebAssemblyFunctionHeapCellType.h"
    2728
    2829#if ENABLE(WEBASSEMBLY)
    2930
    30 #include "Options.h"
    31 #include "WasmContext.h"
    32 #include "WasmInstance.h"
    33 #include <mutex>
    34 #include <wtf/FastTLS.h>
     31#include "JSCInlines.h"
     32#include "MarkedBlockInlines.h"
     33#include "WebAssemblyFunction.h"
    3534
    36 namespace JSC { namespace Wasm {
     35namespace JSC {
    3736
    38 inline bool Context::useFastTLS()
     37struct WebAssemblyFunctionDestroyFunc {
     38    ALWAYS_INLINE void operator()(VM&, JSCell* cell) const
     39    {
     40        static_assert(std::is_final<WebAssemblyFunction>::value, "Otherwise, this code would not be correct.");
     41        WebAssemblyFunction::info()->methodTable.destroy(cell);
     42    }
     43};
     44
     45WebAssemblyFunctionHeapCellType::WebAssemblyFunctionHeapCellType()
     46    : HeapCellType(CellAttributes(NeedsDestruction, HeapCell::JSCell))
    3947{
    40 #if ENABLE(FAST_TLS_JIT)
    41     return Options::useFastTLSForWasmContext();
    42 #else
    43     return false;
    44 #endif
    4548}
    4649
    47 inline Instance* Context::load() const
     50WebAssemblyFunctionHeapCellType::~WebAssemblyFunctionHeapCellType()
    4851{
    49 #if ENABLE(FAST_TLS_JIT)
    50     if (useFastTLS())
    51         return bitwise_cast<Instance*>(_pthread_getspecific_direct(WTF_WASM_CONTEXT_KEY));
    52 #endif
    53     return instance;
    5452}
    5553
    56 inline void Context::store(Instance* inst, void* softStackLimit)
     54void WebAssemblyFunctionHeapCellType::finishSweep(MarkedBlock::Handle& handle, FreeList* freeList)
    5755{
    58 #if ENABLE(FAST_TLS_JIT)
    59     if (useFastTLS())
    60         _pthread_setspecific_direct(WTF_WASM_CONTEXT_KEY, bitwise_cast<void*>(inst));
    61 #endif
    62     instance = inst;
    63     if (instance)
    64         instance->setCachedStackLimit(softStackLimit);
     56    handle.finishSweepKnowingHeapCellType(freeList, WebAssemblyFunctionDestroyFunc());
    6557}
    6658
    67 } } // namespace JSC::Wasm
     59void WebAssemblyFunctionHeapCellType::destroy(VM& vm, JSCell* cell)
     60{
     61    WebAssemblyFunctionDestroyFunc()(vm, cell);
     62}
     63
     64} // namespace JSC
    6865
    6966#endif // ENABLE(WEBASSEMBLY)
  • trunk/Source/JavaScriptCore/wasm/js/WebAssemblyFunctionHeapCellType.h

    r243885 r243886  
    11/*
    2  * Copyright (C) 2017 Apple Inc. All rights reserved.
     2 * Copyright (C) 2019 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    2121 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    2222 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
    23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
    2424 */
    2525
     
    2828#if ENABLE(WEBASSEMBLY)
    2929
    30 namespace JSC { namespace Wasm {
     30#include "HeapCellType.h"
    3131
    32 class Instance;
     32namespace JSC {
    3333
    34 struct Context {
    35     Instance* instance { nullptr };
    36 
    37     Instance* load() const;
    38     void store(Instance*, void* softStackLimit);
    39 
    40     static bool useFastTLS();
     34class WebAssemblyFunctionHeapCellType : public HeapCellType {
     35public:
     36    WebAssemblyFunctionHeapCellType();
     37    virtual ~WebAssemblyFunctionHeapCellType();
     38   
     39    void finishSweep(MarkedBlock::Handle&, FreeList*) override;
     40    void destroy(VM&, JSCell*) override;
    4141};
    4242
    43 } } // namespace JSC::Wasm
     43} // namespace JSC
    4444
    4545#endif // ENABLE(WEBASSEMBLY)
  • trunk/Source/JavaScriptCore/wasm/js/WebAssemblyPrototype.h

    r231194 r243886  
    3434namespace JSC {
    3535
     36class JSPromiseDeferred;
     37
    3638class WebAssemblyPrototype final : public JSNonFinalObject {
    3739public:
Note: See TracChangeset for help on using the changeset viewer.