Teach Call ICs how to call Wasm
authorsbarati@apple.com <sbarati@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 4 Apr 2019 18:54:16 +0000 (18:54 +0000)
committersbarati@apple.com <sbarati@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 4 Apr 2019 18:54:16 +0000 (18:54 +0000)
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:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@243886 268f45cc-cd09-0410-ab3c-d52691b4dbfc

36 files changed:
JSTests/ChangeLog
JSTests/wasm/function-tests/stack-trace.js
Source/JavaScriptCore/CMakeLists.txt
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
Source/JavaScriptCore/Sources.txt
Source/JavaScriptCore/assembler/MacroAssemblerCodeRef.h
Source/JavaScriptCore/interpreter/Interpreter.cpp
Source/JavaScriptCore/interpreter/StackVisitor.cpp
Source/JavaScriptCore/interpreter/StackVisitor.h
Source/JavaScriptCore/jit/JITOperations.cpp
Source/JavaScriptCore/jit/RegisterSet.cpp
Source/JavaScriptCore/jit/RegisterSet.h
Source/JavaScriptCore/jit/Repatch.cpp
Source/JavaScriptCore/jit/Repatch.h
Source/JavaScriptCore/runtime/JSFunction.cpp
Source/JavaScriptCore/runtime/JSGlobalObject.cpp
Source/JavaScriptCore/runtime/JSGlobalObject.h
Source/JavaScriptCore/runtime/VM.cpp
Source/JavaScriptCore/runtime/VM.h
Source/JavaScriptCore/wasm/WasmAirIRGenerator.cpp
Source/JavaScriptCore/wasm/WasmB3IRGenerator.cpp
Source/JavaScriptCore/wasm/WasmBinding.cpp
Source/JavaScriptCore/wasm/WasmContext.h
Source/JavaScriptCore/wasm/WasmContextInlines.h
Source/JavaScriptCore/wasm/WasmMemoryInformation.cpp
Source/JavaScriptCore/wasm/WasmMemoryInformation.h
Source/JavaScriptCore/wasm/WasmOMGPlan.cpp
Source/JavaScriptCore/wasm/js/JSToWasm.cpp
Source/JavaScriptCore/wasm/js/JSToWasmICCallee.cpp [new file with mode: 0644]
Source/JavaScriptCore/wasm/js/JSToWasmICCallee.h [new file with mode: 0644]
Source/JavaScriptCore/wasm/js/WebAssemblyFunction.cpp
Source/JavaScriptCore/wasm/js/WebAssemblyFunction.h
Source/JavaScriptCore/wasm/js/WebAssemblyFunctionHeapCellType.cpp [new file with mode: 0644]
Source/JavaScriptCore/wasm/js/WebAssemblyFunctionHeapCellType.h [new file with mode: 0644]
Source/JavaScriptCore/wasm/js/WebAssemblyPrototype.h

index b240f6f..bf3bbfb 100644 (file)
@@ -1,3 +1,12 @@
+2019-04-04  Saam barati  <sbarati@apple.com>
+
+        Teach Call ICs how to call Wasm
+        https://bugs.webkit.org/show_bug.cgi?id=196387
+
+        Reviewed by Filip Pizlo.
+
+        * wasm/function-tests/stack-trace.js:
+
 2019-04-04  Caio Lima  <ticaiolima@gmail.com>
 
         [JSC] We should consider moving UnlinkedFunctionExecutable::m_parentScopeTDZVariables to RareData
 2019-04-04  Caio Lima  <ticaiolima@gmail.com>
 
         [JSC] We should consider moving UnlinkedFunctionExecutable::m_parentScopeTDZVariables to RareData
index 76e849d..7a36604 100644 (file)
@@ -43,11 +43,16 @@ for (let i = 0; i < 10000; ++i) {
     stacktrace = stacktrace.split("\n");
     assert.truthy(stacktrace[0].indexOf("imp") !== -1); // the arrow function import named "imp".
     assert.eq(stacktrace[1], "wasm-stub@[wasm code]"); // the wasm->js stub
     stacktrace = stacktrace.split("\n");
     assert.truthy(stacktrace[0].indexOf("imp") !== -1); // the arrow function import named "imp".
     assert.eq(stacktrace[1], "wasm-stub@[wasm code]"); // the wasm->js stub
-    assert.eq(stacktrace[2], "<?>.wasm-function[4]@[wasm code]");
-    assert.eq(stacktrace[3], "<?>.wasm-function[2]@[wasm code]");
-    assert.eq(stacktrace[4], "<?>.wasm-function[3]@[wasm code]");
-    assert.eq(stacktrace[5], "<?>.wasm-function[1]@[wasm code]");
-    assert.eq(stacktrace[6], "wasm-stub@[wasm code]"); // wasm entry
-
+    let found = false;
+    for (let i = 0; i < stacktrace.length; ++i) {
+        let str = stacktrace[i];
+        if (str !== "<?>.wasm-function[4]@[wasm code]")
+            continue;
+        found = true;
+        assert.eq(stacktrace[i + 1], "<?>.wasm-function[2]@[wasm code]");
+        assert.eq(stacktrace[i + 2], "<?>.wasm-function[3]@[wasm code]");
+        assert.eq(stacktrace[i + 3], "<?>.wasm-function[1]@[wasm code]");
+    }
+    assert.truthy(found);
     stacktrace = null;
 }
     stacktrace = null;
 }
index e8c56f0..3395144 100644 (file)
@@ -100,8 +100,10 @@ set(JavaScriptCore_OBJECT_LUT_SOURCES
     runtime/SymbolPrototype.cpp
 
     wasm/js/JSWebAssembly.cpp
     runtime/SymbolPrototype.cpp
 
     wasm/js/JSWebAssembly.cpp
+    wasm/js/JSToWasmICCallee.cpp
     wasm/js/WebAssemblyCompileErrorConstructor.cpp
     wasm/js/WebAssemblyCompileErrorPrototype.cpp
     wasm/js/WebAssemblyCompileErrorConstructor.cpp
     wasm/js/WebAssemblyCompileErrorPrototype.cpp
+    wasm/js/WebAssemblyFunctionHeapCellType.cpp
     wasm/js/WebAssemblyInstanceConstructor.cpp
     wasm/js/WebAssemblyInstancePrototype.cpp
     wasm/js/WebAssemblyLinkErrorConstructor.cpp
     wasm/js/WebAssemblyInstanceConstructor.cpp
     wasm/js/WebAssemblyInstancePrototype.cpp
     wasm/js/WebAssemblyLinkErrorConstructor.cpp
index 3eae3a8..790a993 100644 (file)
@@ -1,3 +1,114 @@
+2019-04-04  Saam barati  <sbarati@apple.com>
+
+        Teach Call ICs how to call Wasm
+        https://bugs.webkit.org/show_bug.cgi?id=196387
+
+        Reviewed by Filip Pizlo.
+
+        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:
+
 2019-04-04  Yusuke Suzuki  <ysuzuki@apple.com>
 
         [JSC] Pass CodeOrigin to FuzzerAgent
 2019-04-04  Yusuke Suzuki  <ysuzuki@apple.com>
 
         [JSC] Pass CodeOrigin to FuzzerAgent
index f44d036..d3ff105 100644 (file)
                4BAA07CEB81F49A296E02203 /* WasmSignatureInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = 30A5F403F11C4F599CD596D5 /* WasmSignatureInlines.h */; settings = {ATTRIBUTES = (Private, ); }; };
                521131F71F82BF14007CCEEE /* PolyProtoAccessChain.h in Headers */ = {isa = PBXBuildFile; fileRef = 521131F61F82BF11007CCEEE /* PolyProtoAccessChain.h */; settings = {ATTRIBUTES = (Private, ); }; };
                521322461ECBCE8200F65615 /* WebAssemblyFunctionBase.h in Headers */ = {isa = PBXBuildFile; fileRef = 521322441ECBCE8200F65615 /* WebAssemblyFunctionBase.h */; };
                4BAA07CEB81F49A296E02203 /* WasmSignatureInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = 30A5F403F11C4F599CD596D5 /* WasmSignatureInlines.h */; settings = {ATTRIBUTES = (Private, ); }; };
                521131F71F82BF14007CCEEE /* PolyProtoAccessChain.h in Headers */ = {isa = PBXBuildFile; fileRef = 521131F61F82BF11007CCEEE /* PolyProtoAccessChain.h */; settings = {ATTRIBUTES = (Private, ); }; };
                521322461ECBCE8200F65615 /* WebAssemblyFunctionBase.h in Headers */ = {isa = PBXBuildFile; fileRef = 521322441ECBCE8200F65615 /* WebAssemblyFunctionBase.h */; };
+               523FD88E225566C9003B3DCC /* WebAssemblyFunctionHeapCellType.h in Headers */ = {isa = PBXBuildFile; fileRef = 523FD88C225566C3003B3DCC /* WebAssemblyFunctionHeapCellType.h */; };
                524E9D7322092B5200A6BEEE /* AirAllocateRegistersAndStackAndGenerateCode.h in Headers */ = {isa = PBXBuildFile; fileRef = 524E9D7222092B4600A6BEEE /* AirAllocateRegistersAndStackAndGenerateCode.h */; };
                5250D2D21E8DA05A0029A932 /* WasmThunks.h in Headers */ = {isa = PBXBuildFile; fileRef = 5250D2D01E8DA05A0029A932 /* WasmThunks.h */; settings = {ATTRIBUTES = (Private, ); }; };
                525C0DDA1E935847002184CD /* WasmCallee.h in Headers */ = {isa = PBXBuildFile; fileRef = 525C0DD81E935847002184CD /* WasmCallee.h */; settings = {ATTRIBUTES = (Private, ); }; };
                524E9D7322092B5200A6BEEE /* AirAllocateRegistersAndStackAndGenerateCode.h in Headers */ = {isa = PBXBuildFile; fileRef = 524E9D7222092B4600A6BEEE /* AirAllocateRegistersAndStackAndGenerateCode.h */; };
                5250D2D21E8DA05A0029A932 /* WasmThunks.h in Headers */ = {isa = PBXBuildFile; fileRef = 5250D2D01E8DA05A0029A932 /* WasmThunks.h */; settings = {ATTRIBUTES = (Private, ); }; };
                525C0DDA1E935847002184CD /* WasmCallee.h in Headers */ = {isa = PBXBuildFile; fileRef = 525C0DD81E935847002184CD /* WasmCallee.h */; settings = {ATTRIBUTES = (Private, ); }; };
                52678F8F1A031009006A306D /* BasicBlockLocation.h in Headers */ = {isa = PBXBuildFile; fileRef = 52678F8D1A031009006A306D /* BasicBlockLocation.h */; settings = {ATTRIBUTES = (Private, ); }; };
                52678F911A04177C006A306D /* ControlFlowProfiler.h in Headers */ = {isa = PBXBuildFile; fileRef = 52678F901A04177C006A306D /* ControlFlowProfiler.h */; settings = {ATTRIBUTES = (Private, ); }; };
                526AC4B71E977C5D003500E1 /* WasmCodeBlock.h in Headers */ = {isa = PBXBuildFile; fileRef = 526AC4B51E977C5D003500E1 /* WasmCodeBlock.h */; settings = {ATTRIBUTES = (Private, ); }; };
                52678F8F1A031009006A306D /* BasicBlockLocation.h in Headers */ = {isa = PBXBuildFile; fileRef = 52678F8D1A031009006A306D /* BasicBlockLocation.h */; settings = {ATTRIBUTES = (Private, ); }; };
                52678F911A04177C006A306D /* ControlFlowProfiler.h in Headers */ = {isa = PBXBuildFile; fileRef = 52678F901A04177C006A306D /* ControlFlowProfiler.h */; settings = {ATTRIBUTES = (Private, ); }; };
                526AC4B71E977C5D003500E1 /* WasmCodeBlock.h in Headers */ = {isa = PBXBuildFile; fileRef = 526AC4B51E977C5D003500E1 /* WasmCodeBlock.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               527CE35422555FE500C6F382 /* JSToWasmICCallee.h in Headers */ = {isa = PBXBuildFile; fileRef = 527CE35322555FDD00C6F382 /* JSToWasmICCallee.h */; };
                52847ADC21FFB8690061A9DB /* WasmAirIRGenerator.h in Headers */ = {isa = PBXBuildFile; fileRef = 52847ADA21FFB8630061A9DB /* WasmAirIRGenerator.h */; };
                52B310FB1974AE610080857C /* FunctionHasExecutedCache.h in Headers */ = {isa = PBXBuildFile; fileRef = 52B310FA1974AE610080857C /* FunctionHasExecutedCache.h */; settings = {ATTRIBUTES = (Private, ); }; };
                52B311011975B4670080857C /* TypeLocationCache.h in Headers */ = {isa = PBXBuildFile; fileRef = 52B311001975B4670080857C /* TypeLocationCache.h */; settings = {ATTRIBUTES = (Private, ); }; };
                52847ADC21FFB8690061A9DB /* WasmAirIRGenerator.h in Headers */ = {isa = PBXBuildFile; fileRef = 52847ADA21FFB8630061A9DB /* WasmAirIRGenerator.h */; };
                52B310FB1974AE610080857C /* FunctionHasExecutedCache.h in Headers */ = {isa = PBXBuildFile; fileRef = 52B310FA1974AE610080857C /* FunctionHasExecutedCache.h */; settings = {ATTRIBUTES = (Private, ); }; };
                52B311011975B4670080857C /* TypeLocationCache.h in Headers */ = {isa = PBXBuildFile; fileRef = 52B311001975B4670080857C /* TypeLocationCache.h */; settings = {ATTRIBUTES = (Private, ); }; };
                521131F61F82BF11007CCEEE /* PolyProtoAccessChain.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PolyProtoAccessChain.h; sourceTree = "<group>"; };
                521322431ECBCE8200F65615 /* WebAssemblyFunctionBase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = WebAssemblyFunctionBase.cpp; path = js/WebAssemblyFunctionBase.cpp; sourceTree = "<group>"; };
                521322441ECBCE8200F65615 /* WebAssemblyFunctionBase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = WebAssemblyFunctionBase.h; path = js/WebAssemblyFunctionBase.h; sourceTree = "<group>"; };
                521131F61F82BF11007CCEEE /* PolyProtoAccessChain.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PolyProtoAccessChain.h; sourceTree = "<group>"; };
                521322431ECBCE8200F65615 /* WebAssemblyFunctionBase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = WebAssemblyFunctionBase.cpp; path = js/WebAssemblyFunctionBase.cpp; sourceTree = "<group>"; };
                521322441ECBCE8200F65615 /* WebAssemblyFunctionBase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = WebAssemblyFunctionBase.h; path = js/WebAssemblyFunctionBase.h; sourceTree = "<group>"; };
+               523FD88C225566C3003B3DCC /* WebAssemblyFunctionHeapCellType.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = WebAssemblyFunctionHeapCellType.h; path = js/WebAssemblyFunctionHeapCellType.h; sourceTree = "<group>"; };
+               523FD88D225566C4003B3DCC /* WebAssemblyFunctionHeapCellType.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = WebAssemblyFunctionHeapCellType.cpp; path = js/WebAssemblyFunctionHeapCellType.cpp; sourceTree = "<group>"; };
                524E9D7122092B4500A6BEEE /* AirAllocateRegistersAndStackAndGenerateCode.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = AirAllocateRegistersAndStackAndGenerateCode.cpp; path = b3/air/AirAllocateRegistersAndStackAndGenerateCode.cpp; sourceTree = "<group>"; };
                524E9D7222092B4600A6BEEE /* AirAllocateRegistersAndStackAndGenerateCode.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = AirAllocateRegistersAndStackAndGenerateCode.h; path = b3/air/AirAllocateRegistersAndStackAndGenerateCode.h; sourceTree = "<group>"; };
                5250D2CF1E8DA05A0029A932 /* WasmThunks.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WasmThunks.cpp; sourceTree = "<group>"; };
                524E9D7122092B4500A6BEEE /* AirAllocateRegistersAndStackAndGenerateCode.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = AirAllocateRegistersAndStackAndGenerateCode.cpp; path = b3/air/AirAllocateRegistersAndStackAndGenerateCode.cpp; sourceTree = "<group>"; };
                524E9D7222092B4600A6BEEE /* AirAllocateRegistersAndStackAndGenerateCode.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = AirAllocateRegistersAndStackAndGenerateCode.h; path = b3/air/AirAllocateRegistersAndStackAndGenerateCode.h; sourceTree = "<group>"; };
                5250D2CF1E8DA05A0029A932 /* WasmThunks.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WasmThunks.cpp; sourceTree = "<group>"; };
                526AC4B41E977C5D003500E1 /* WasmCodeBlock.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WasmCodeBlock.cpp; sourceTree = "<group>"; };
                526AC4B51E977C5D003500E1 /* WasmCodeBlock.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WasmCodeBlock.h; sourceTree = "<group>"; };
                527773DD1AAF83AC00BDE7E8 /* RuntimeType.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RuntimeType.cpp; sourceTree = "<group>"; };
                526AC4B41E977C5D003500E1 /* WasmCodeBlock.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WasmCodeBlock.cpp; sourceTree = "<group>"; };
                526AC4B51E977C5D003500E1 /* WasmCodeBlock.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WasmCodeBlock.h; sourceTree = "<group>"; };
                527773DD1AAF83AC00BDE7E8 /* RuntimeType.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RuntimeType.cpp; sourceTree = "<group>"; };
+               527CE35222555FDD00C6F382 /* JSToWasmICCallee.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = JSToWasmICCallee.cpp; path = js/JSToWasmICCallee.cpp; sourceTree = "<group>"; };
+               527CE35322555FDD00C6F382 /* JSToWasmICCallee.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = JSToWasmICCallee.h; path = js/JSToWasmICCallee.h; sourceTree = "<group>"; };
                52847AD921FFB8630061A9DB /* WasmAirIRGenerator.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = WasmAirIRGenerator.cpp; sourceTree = "<group>"; };
                52847ADA21FFB8630061A9DB /* WasmAirIRGenerator.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WasmAirIRGenerator.h; sourceTree = "<group>"; };
                52B310FA1974AE610080857C /* FunctionHasExecutedCache.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FunctionHasExecutedCache.h; sourceTree = "<group>"; };
                52847AD921FFB8630061A9DB /* WasmAirIRGenerator.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = WasmAirIRGenerator.cpp; sourceTree = "<group>"; };
                52847ADA21FFB8630061A9DB /* WasmAirIRGenerator.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WasmAirIRGenerator.h; sourceTree = "<group>"; };
                52B310FA1974AE610080857C /* FunctionHasExecutedCache.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FunctionHasExecutedCache.h; sourceTree = "<group>"; };
                        children = (
                                AD8DD6D01F6708A30004EB52 /* JSToWasm.cpp */,
                                AD8DD6CF1F67089F0004EB52 /* JSToWasm.h */,
                        children = (
                                AD8DD6D01F6708A30004EB52 /* JSToWasm.cpp */,
                                AD8DD6CF1F67089F0004EB52 /* JSToWasm.h */,
+                               527CE35222555FDD00C6F382 /* JSToWasmICCallee.cpp */,
+                               527CE35322555FDD00C6F382 /* JSToWasmICCallee.h */,
                                ADD09AF21F624829001313C2 /* JSWebAssembly.cpp */,
                                ADD09AF31F62482E001313C2 /* JSWebAssembly.h */,
                                5383AA2F1E65E8A100A532FC /* JSWebAssemblyCodeBlock.cpp */,
                                ADD09AF21F624829001313C2 /* JSWebAssembly.cpp */,
                                ADD09AF31F62482E001313C2 /* JSWebAssembly.h */,
                                5383AA2F1E65E8A100A532FC /* JSWebAssemblyCodeBlock.cpp */,
                                AD2FCBB31DB58DA400B3E736 /* WebAssemblyCompileErrorPrototype.h */,
                                AD4937C91DDD27340077C807 /* WebAssemblyFunction.cpp */,
                                AD4937CA1DDD27340077C807 /* WebAssemblyFunction.h */,
                                AD2FCBB31DB58DA400B3E736 /* WebAssemblyCompileErrorPrototype.h */,
                                AD4937C91DDD27340077C807 /* WebAssemblyFunction.cpp */,
                                AD4937CA1DDD27340077C807 /* WebAssemblyFunction.h */,
+                               523FD88D225566C4003B3DCC /* WebAssemblyFunctionHeapCellType.cpp */,
+                               523FD88C225566C3003B3DCC /* WebAssemblyFunctionHeapCellType.h */,
                                521322431ECBCE8200F65615 /* WebAssemblyFunctionBase.cpp */,
                                521322441ECBCE8200F65615 /* WebAssemblyFunctionBase.h */,
                                AD2FCBB41DB58DA400B3E736 /* WebAssemblyInstanceConstructor.cpp */,
                                521322431ECBCE8200F65615 /* WebAssemblyFunctionBase.cpp */,
                                521322441ECBCE8200F65615 /* WebAssemblyFunctionBase.h */,
                                AD2FCBB41DB58DA400B3E736 /* WebAssemblyInstanceConstructor.cpp */,
                                0F5BF1641F2317120029D91D /* B3HoistLoopInvariantValues.h in Headers */,
                                DC69B99D1D15F914002E3C00 /* B3InferSwitches.h in Headers */,
                                0FEC85BA1BE1462F0080FF74 /* B3InsertionSet.h in Headers */,
                                0F5BF1641F2317120029D91D /* B3HoistLoopInvariantValues.h in Headers */,
                                DC69B99D1D15F914002E3C00 /* B3InferSwitches.h in Headers */,
                                0FEC85BA1BE1462F0080FF74 /* B3InsertionSet.h in Headers */,
+                               523FD88E225566C9003B3DCC /* WebAssemblyFunctionHeapCellType.h in Headers */,
                                0FEC85BB1BE1462F0080FF74 /* B3InsertionSetInlines.h in Headers */,
                                0FDF67D21D9C6D27001B9825 /* B3Kind.h in Headers */,
                                436E54531C468E7400B5AF73 /* B3LegalizeMemoryOffsets.h in Headers */,
                                0FEC85BB1BE1462F0080FF74 /* B3InsertionSetInlines.h in Headers */,
                                0FDF67D21D9C6D27001B9825 /* B3Kind.h in Headers */,
                                436E54531C468E7400B5AF73 /* B3LegalizeMemoryOffsets.h in Headers */,
                                473DA4A4764C45FE871B0485 /* DefinePropertyAttributes.h in Headers */,
                                0FBB73BB1DEF8645002C009E /* DeleteAllCodeEffort.h in Headers */,
                                0F96303C1D4192CD005609D9 /* DestructionMode.h in Headers */,
                                473DA4A4764C45FE871B0485 /* DefinePropertyAttributes.h in Headers */,
                                0FBB73BB1DEF8645002C009E /* DeleteAllCodeEffort.h in Headers */,
                                0F96303C1D4192CD005609D9 /* DestructionMode.h in Headers */,
+                               527CE35422555FE500C6F382 /* JSToWasmICCallee.h in Headers */,
                                A77A423E17A0BBFD00A8DB81 /* DFGAbstractHeap.h in Headers */,
                                A704D90317A0BAA8006BA554 /* DFGAbstractInterpreter.h in Headers */,
                                0F5E0FD8207C72730097F0DE /* DFGAbstractInterpreterClobberState.h in Headers */,
                                A77A423E17A0BBFD00A8DB81 /* DFGAbstractHeap.h in Headers */,
                                A704D90317A0BAA8006BA554 /* DFGAbstractInterpreter.h in Headers */,
                                0F5E0FD8207C72730097F0DE /* DFGAbstractInterpreterClobberState.h in Headers */,
index d9cd467..24c2d68 100644 (file)
@@ -1014,6 +1014,7 @@ wasm/WasmWorklist.cpp
 
 wasm/js/JSToWasm.cpp
 wasm/js/JSToWasm.h
 
 wasm/js/JSToWasm.cpp
 wasm/js/JSToWasm.h
+wasm/js/JSToWasmICCallee.cpp
 wasm/js/JSWebAssembly.cpp
 wasm/js/JSWebAssemblyCodeBlock.cpp
 wasm/js/JSWebAssemblyCodeBlockHeapCellType.cpp
 wasm/js/JSWebAssembly.cpp
 wasm/js/JSWebAssemblyCodeBlock.cpp
 wasm/js/JSWebAssemblyCodeBlockHeapCellType.cpp
@@ -1030,6 +1031,7 @@ wasm/js/WebAssemblyCompileErrorConstructor.cpp
 wasm/js/WebAssemblyCompileErrorPrototype.cpp
 wasm/js/WebAssemblyFunction.cpp
 wasm/js/WebAssemblyFunctionBase.cpp
 wasm/js/WebAssemblyCompileErrorPrototype.cpp
 wasm/js/WebAssemblyFunction.cpp
 wasm/js/WebAssemblyFunctionBase.cpp
+wasm/js/WebAssemblyFunctionHeapCellType.cpp
 wasm/js/WebAssemblyInstanceConstructor.cpp
 wasm/js/WebAssemblyInstancePrototype.cpp
 wasm/js/WebAssemblyLinkErrorConstructor.cpp
 wasm/js/WebAssemblyInstanceConstructor.cpp
 wasm/js/WebAssemblyInstancePrototype.cpp
 wasm/js/WebAssemblyLinkErrorConstructor.cpp
index 14a9b74..54658dd 100644 (file)
@@ -380,6 +380,14 @@ public:
         ASSERT(m_executableMemory->start());
         ASSERT(m_codePtr);
     }
         ASSERT(m_executableMemory->start());
         ASSERT(m_codePtr);
     }
+
+    template<PtrTag otherTag>
+    MacroAssemblerCodeRef& operator=(const MacroAssemblerCodeRef<otherTag>& otherCodeRef)
+    {
+        m_codePtr = MacroAssemblerCodePtr<tag>::createFromExecutableAddress(otherCodeRef.code().template retaggedExecutableAddress<tag>());
+        m_executableMemory = otherCodeRef.m_executableMemory;
+        return *this;
+    }
     
     // Use this only when you know that the codePtr refers to code that is
     // already being kept alive through some other means. Typically this means
     
     // Use this only when you know that the codePtr refers to code that is
     // already being kept alive through some other means. Typically this means
@@ -443,9 +451,9 @@ public:
 private:
     template<PtrTag otherTag>
     MacroAssemblerCodeRef(const MacroAssemblerCodeRef<otherTag>& otherCodeRef)
 private:
     template<PtrTag otherTag>
     MacroAssemblerCodeRef(const MacroAssemblerCodeRef<otherTag>& otherCodeRef)
-        : m_codePtr(MacroAssemblerCodePtr<tag>::createFromExecutableAddress(otherCodeRef.code().template retaggedExecutableAddress<tag>()))
-        , m_executableMemory(otherCodeRef.m_executableMemory)
-    }
+    {
+        *this = otherCodeRef;
+    }
 
     MacroAssemblerCodePtr<tag> m_codePtr;
     RefPtr<ExecutableMemoryHandle> m_executableMemory;
 
     MacroAssemblerCodePtr<tag> m_codePtr;
     RefPtr<ExecutableMemoryHandle> m_executableMemory;
index 7f15d19..ac963bc 100644 (file)
@@ -549,6 +549,13 @@ public:
             }
         }
 
             }
         }
 
+#if ENABLE(WEBASSEMBLY)
+        if (visitor->callee().isCell()) {
+            if (auto* jsToWasmICCallee = jsDynamicCast<JSToWasmICCallee*>(m_vm, visitor->callee().asCell()))
+                m_vm.wasmContext.store(jsToWasmICCallee->function()->previousInstance(m_callFrame), m_vm.softStackLimit());
+        }
+#endif
+
         notifyDebuggerOfUnwinding(m_vm, m_callFrame);
 
         copyCalleeSavesToEntryFrameCalleeSavesBuffer(visitor);
         notifyDebuggerOfUnwinding(m_vm, m_callFrame);
 
         copyCalleeSavesToEntryFrameCalleeSavesBuffer(visitor);
@@ -564,7 +571,7 @@ private:
     void copyCalleeSavesToEntryFrameCalleeSavesBuffer(StackVisitor& visitor) const
     {
 #if !ENABLE(C_LOOP) && NUMBER_OF_CALLEE_SAVES_REGISTERS > 0
     void copyCalleeSavesToEntryFrameCalleeSavesBuffer(StackVisitor& visitor) const
     {
 #if !ENABLE(C_LOOP) && NUMBER_OF_CALLEE_SAVES_REGISTERS > 0
-        const RegisterAtOffsetList* currentCalleeSaves = visitor->calleeSaveRegisters();
+        Optional<RegisterAtOffsetList> currentCalleeSaves = visitor->calleeSaveRegistersForUnwinding();
 
         if (!currentCalleeSaves)
             return;
 
         if (!currentCalleeSaves)
             return;
index 833df06..8954d00 100644 (file)
@@ -33,6 +33,7 @@
 #include "JSCInlines.h"
 #include "WasmCallee.h"
 #include "WasmIndexOrName.h"
 #include "JSCInlines.h"
 #include "WasmCallee.h"
 #include "WasmIndexOrName.h"
+#include "WebAssemblyFunction.h"
 #include <wtf/text/StringBuilder.h>
 
 namespace JSC {
 #include <wtf/text/StringBuilder.h>
 
 namespace JSC {
@@ -252,10 +253,10 @@ StackVisitor::Frame::CodeType StackVisitor::Frame::codeType() const
     return CodeType::Global;
 }
 
     return CodeType::Global;
 }
 
-const RegisterAtOffsetList* StackVisitor::Frame::calleeSaveRegisters()
+Optional<RegisterAtOffsetList> StackVisitor::Frame::calleeSaveRegistersForUnwinding()
 {
     if (isInlinedFrame())
 {
     if (isInlinedFrame())
-        return nullptr;
+        return WTF::nullopt;
 
 #if !ENABLE(C_LOOP) && NUMBER_OF_CALLEE_SAVES_REGISTERS > 0
 
 
 #if !ENABLE(C_LOOP) && NUMBER_OF_CALLEE_SAVES_REGISTERS > 0
 
@@ -263,19 +264,24 @@ const RegisterAtOffsetList* StackVisitor::Frame::calleeSaveRegisters()
     if (isWasmFrame()) {
         if (callee().isCell()) {
             RELEASE_ASSERT(isWebAssemblyToJSCallee(callee().asCell()));
     if (isWasmFrame()) {
         if (callee().isCell()) {
             RELEASE_ASSERT(isWebAssemblyToJSCallee(callee().asCell()));
-            return nullptr;
+            return WTF::nullopt;
         }
         Wasm::Callee* wasmCallee = callee().asWasmCallee();
         }
         Wasm::Callee* wasmCallee = callee().asWasmCallee();
-        return wasmCallee->calleeSaveRegisters();
+        return *wasmCallee->calleeSaveRegisters();
+    }
+
+    if (callee().isCell()) {
+        if (auto* jsToWasmICCallee = jsDynamicCast<JSToWasmICCallee*>(*callee().asCell()->vm(), callee().asCell()))
+            return jsToWasmICCallee->function()->usedCalleeSaveRegisters();
     }
 #endif // ENABLE(WEBASSEMBLY)
 
     if (CodeBlock* codeBlock = this->codeBlock())
     }
 #endif // ENABLE(WEBASSEMBLY)
 
     if (CodeBlock* codeBlock = this->codeBlock())
-        return codeBlock->calleeSaveRegisters();
+        return *codeBlock->calleeSaveRegisters();
 
 #endif // !ENABLE(C_LOOP) && NUMBER_OF_CALLEE_SAVES_REGISTERS > 0
 
 
 #endif // !ENABLE(C_LOOP) && NUMBER_OF_CALLEE_SAVES_REGISTERS > 0
 
-    return nullptr;
+    return WTF::nullopt;
 }
 
 String StackVisitor::Frame::functionName() const
 }
 
 String StackVisitor::Frame::functionName() const
index b2f02f8..8ab9fef 100644 (file)
@@ -94,7 +94,7 @@ public:
         bool hasLineAndColumnInfo() const;
         JS_EXPORT_PRIVATE void computeLineAndColumn(unsigned& line, unsigned& column) const;
 
         bool hasLineAndColumnInfo() const;
         JS_EXPORT_PRIVATE void computeLineAndColumn(unsigned& line, unsigned& column) const;
 
-        const RegisterAtOffsetList* calleeSaveRegisters();
+        Optional<RegisterAtOffsetList> calleeSaveRegistersForUnwinding();
 
         ClonedArguments* createArguments();
         CallFrame* callFrame() const { return m_callFrame; }
 
         ClonedArguments* createArguments();
         CallFrame* callFrame() const { return m_callFrame; }
index 8261a69..b8ec4cd 100644 (file)
@@ -76,6 +76,7 @@
 #include "ThunkGenerators.h"
 #include "TypeProfilerLog.h"
 #include "VMInlines.h"
 #include "ThunkGenerators.h"
 #include "TypeProfilerLog.h"
 #include "VMInlines.h"
+#include "WebAssemblyFunction.h"
 #include <wtf/InlineASM.h>
 
 namespace JSC {
 #include <wtf/InlineASM.h>
 
 namespace JSC {
@@ -1036,9 +1037,11 @@ SlowPathReturnType JIT_OPERATION operationLinkCall(ExecState* execCallee, CallLi
 
     MacroAssemblerCodePtr<JSEntryPtrTag> codePtr;
     CodeBlock* codeBlock = nullptr;
 
     MacroAssemblerCodePtr<JSEntryPtrTag> codePtr;
     CodeBlock* codeBlock = nullptr;
-    if (executable->isHostFunction())
-        codePtr = executable->entrypointFor(kind, MustCheckArity);
-    else {
+    if (executable->isHostFunction()) {
+        codePtr = jsToWasmICCodePtr(*vm, kind, callee);
+        if (!codePtr)
+            codePtr = executable->entrypointFor(kind, MustCheckArity);
+    } else {
         FunctionExecutable* functionExecutable = static_cast<FunctionExecutable*>(executable);
 
         auto handleThrowException = [&] () {
         FunctionExecutable* functionExecutable = static_cast<FunctionExecutable*>(executable);
 
         auto handleThrowException = [&] () {
@@ -1064,6 +1067,7 @@ SlowPathReturnType JIT_OPERATION operationLinkCall(ExecState* execCallee, CallLi
             arity = ArityCheckNotRequired;
         codePtr = functionExecutable->entrypointFor(kind, arity);
     }
             arity = ArityCheckNotRequired;
         codePtr = functionExecutable->entrypointFor(kind, arity);
     }
+
     if (!callLinkInfo->seenOnce())
         callLinkInfo->setSeen();
     else
     if (!callLinkInfo->seenOnce())
         callLinkInfo->setSeen();
     else
index 3d02317..79de8c4 100644 (file)
@@ -58,7 +58,7 @@ RegisterSet RegisterSet::reservedHardwareRegisters()
 #endif
 }
 
 #endif
 }
 
-RegisterSet RegisterSet::runtimeRegisters()
+RegisterSet RegisterSet::runtimeTagRegisters()
 {
 #if USE(JSVALUE64)
     return RegisterSet(GPRInfo::tagTypeNumberRegister, GPRInfo::tagMaskRegister);
 {
 #if USE(JSVALUE64)
     return RegisterSet(GPRInfo::tagTypeNumberRegister, GPRInfo::tagMaskRegister);
@@ -70,7 +70,7 @@ RegisterSet RegisterSet::runtimeRegisters()
 RegisterSet RegisterSet::specialRegisters()
 {
     return RegisterSet(
 RegisterSet RegisterSet::specialRegisters()
 {
     return RegisterSet(
-        stackRegisters(), reservedHardwareRegisters(), runtimeRegisters());
+        stackRegisters(), reservedHardwareRegisters(), runtimeTagRegisters());
 }
 
 RegisterSet RegisterSet::volatileRegistersForJSCall()
 }
 
 RegisterSet RegisterSet::volatileRegistersForJSCall()
index a618852..ae42323 100644 (file)
@@ -50,7 +50,7 @@ public:
     
     JS_EXPORT_PRIVATE static RegisterSet stackRegisters();
     JS_EXPORT_PRIVATE static RegisterSet reservedHardwareRegisters();
     
     JS_EXPORT_PRIVATE static RegisterSet stackRegisters();
     JS_EXPORT_PRIVATE static RegisterSet reservedHardwareRegisters();
-    static RegisterSet runtimeRegisters();
+    static RegisterSet runtimeTagRegisters();
     static RegisterSet specialRegisters(); // The union of stack, reserved hardware, and runtime registers.
     JS_EXPORT_PRIVATE static RegisterSet calleeSaveRegisters();
     static RegisterSet vmCalleeSaveRegisters(); // Callee save registers that might be saved and used by any tier.
     static RegisterSet specialRegisters(); // The union of stack, reserved hardware, and runtime registers.
     JS_EXPORT_PRIVATE static RegisterSet calleeSaveRegisters();
     static RegisterSet vmCalleeSaveRegisters(); // Callee save registers that might be saved and used by any tier.
index 48af689..17f5dea 100644 (file)
@@ -975,7 +975,7 @@ void linkPolymorphicCall(
     if (PolymorphicCallStubRoutine* stub = callLinkInfo.stub())
         list = stub->variants();
     else if (JSObject* oldCallee = callLinkInfo.callee())
     if (PolymorphicCallStubRoutine* stub = callLinkInfo.stub())
         list = stub->variants();
     else if (JSObject* oldCallee = callLinkInfo.callee())
-        list = CallVariantList{ CallVariant(oldCallee) };
+        list = CallVariantList { CallVariant(oldCallee) };
     
     list = variantListWithVariant(list, newVariant);
 
     
     list = variantListWithVariant(list, newVariant);
 
@@ -1137,7 +1137,10 @@ void linkPolymorphicCall(
         MacroAssemblerCodePtr<JSEntryPtrTag> codePtr;
         if (variant.executable()) {
             ASSERT(variant.executable()->hasJITCodeForCall());
         MacroAssemblerCodePtr<JSEntryPtrTag> codePtr;
         if (variant.executable()) {
             ASSERT(variant.executable()->hasJITCodeForCall());
-            codePtr = variant.executable()->generatedJITCodeForCall()->addressForCall(ArityCheckNotRequired);
+            
+            codePtr = jsToWasmICCodePtr(vm, callLinkInfo.specializationKind(), variant.function());
+            if (!codePtr)
+                codePtr = variant.executable()->generatedJITCodeForCall()->addressForCall(ArityCheckNotRequired);
         } else {
             ASSERT(variant.internalFunction());
             codePtr = vm.getCTIInternalFunctionTrampolineFor(CodeForCall);
         } else {
             ASSERT(variant.internalFunction());
             codePtr = vm.getCTIInternalFunctionTrampolineFor(CodeForCall);
@@ -1277,6 +1280,23 @@ void resetInstanceOf(StructureStubInfo& stubInfo)
     resetPatchableJump(stubInfo);
 }
 
     resetPatchableJump(stubInfo);
 }
 
+MacroAssemblerCodePtr<JSEntryPtrTag> jsToWasmICCodePtr(VM& vm, CodeSpecializationKind kind, JSObject* callee)
+{
+#if ENABLE(WEBASSEMBLY)
+    if (!callee)
+        return nullptr;
+    if (kind != CodeForCall)
+        return nullptr;
+    if (auto* wasmFunction = jsDynamicCast<WebAssemblyFunction*>(vm, callee))
+        return wasmFunction->jsCallEntrypoint();
+#else
+    UNUSED_PARAM(vm);
+    UNUSED_PARAM(kind);
+    UNUSED_PARAM(callee);
+#endif
+    return nullptr;
+}
+
 } // namespace JSC
 
 #endif
 } // namespace JSC
 
 #endif
index 0f366dd..86a6c5a 100644 (file)
@@ -57,6 +57,8 @@ void resetPutByID(CodeBlock*, StructureStubInfo&);
 void resetInByID(CodeBlock*, StructureStubInfo&);
 void resetInstanceOf(StructureStubInfo&);
 void ftlThunkAwareRepatchCall(CodeBlock*, CodeLocationCall<JSInternalPtrTag>, FunctionPtr<CFunctionPtrTag> newCalleeFunction);
 void resetInByID(CodeBlock*, StructureStubInfo&);
 void resetInstanceOf(StructureStubInfo&);
 void ftlThunkAwareRepatchCall(CodeBlock*, CodeLocationCall<JSInternalPtrTag>, FunctionPtr<CFunctionPtrTag> newCalleeFunction);
+MacroAssemblerCodePtr<JSEntryPtrTag> jsToWasmICCodePtr(VM&, CodeSpecializationKind, JSObject* callee);
+
 
 } // namespace JSC
 
 
 } // namespace JSC
 
index f592a1a..37ff4c8 100644 (file)
@@ -48,6 +48,7 @@
 #include "Parser.h"
 #include "PropertyNameArray.h"
 #include "StackVisitor.h"
 #include "Parser.h"
 #include "PropertyNameArray.h"
 #include "StackVisitor.h"
+#include "WebAssemblyFunction.h"
 
 namespace JSC {
 
 
 namespace JSC {
 
@@ -627,10 +628,14 @@ ConstructType JSFunction::getConstructData(JSCell* cell, ConstructData& construc
 
 String getCalculatedDisplayName(VM& vm, JSObject* object)
 {
 
 String getCalculatedDisplayName(VM& vm, JSObject* object)
 {
+#if ENABLE(WEBASSEMBLY)
+    if (jsDynamicCast<JSToWasmICCallee*>(vm, object))
+        return "wasm-stub"_s;
+#endif
+
     if (!jsDynamicCast<JSFunction*>(vm, object) && !jsDynamicCast<InternalFunction*>(vm, object))
         return emptyString();
 
     if (!jsDynamicCast<JSFunction*>(vm, object) && !jsDynamicCast<InternalFunction*>(vm, object))
         return emptyString();
 
-
     Structure* structure = object->structure(vm);
     unsigned attributes;
     // This function may be called when the mutator isn't running and we are lazily generating a stack trace.
     Structure* structure = object->structure(vm);
     unsigned attributes;
     // This function may be called when the mutator isn't running and we are lazily generating a stack trace.
index adef69b..cd93d38 100644 (file)
@@ -1053,6 +1053,10 @@ putDirectWithoutTransition(vm, vm.propertyNames-> jsName, lowerName ## Construct
             [] (const Initializer<Structure>& init) {
                 init.set(WebAssemblyFunction::createStructure(init.vm, init.owner, init.owner->m_functionPrototype.get()));
             });
             [] (const Initializer<Structure>& init) {
                 init.set(WebAssemblyFunction::createStructure(init.vm, init.owner, init.owner->m_functionPrototype.get()));
             });
+        m_jsToWasmICCalleeStructure.initLater(
+            [] (const Initializer<Structure>& init) {
+                init.set(JSToWasmICCallee::createStructure(init.vm, init.owner, JSValue()));
+            });
         m_webAssemblyWrapperFunctionStructure.initLater(
             [] (const Initializer<Structure>& init) {
                 init.set(WebAssemblyWrapperFunction::createStructure(init.vm, init.owner, init.owner->m_functionPrototype.get()));
         m_webAssemblyWrapperFunctionStructure.initLater(
             [] (const Initializer<Structure>& init) {
                 init.set(WebAssemblyWrapperFunction::createStructure(init.vm, init.owner, init.owner->m_functionPrototype.get()));
@@ -1751,6 +1755,7 @@ void JSGlobalObject::visitChildren(JSCell* cell, SlotVisitor& visitor)
 #if ENABLE(WEBASSEMBLY)
     thisObject->m_webAssemblyModuleRecordStructure.visit(visitor);
     thisObject->m_webAssemblyFunctionStructure.visit(visitor);
 #if ENABLE(WEBASSEMBLY)
     thisObject->m_webAssemblyModuleRecordStructure.visit(visitor);
     thisObject->m_webAssemblyFunctionStructure.visit(visitor);
+    thisObject->m_jsToWasmICCalleeStructure.visit(visitor);
     thisObject->m_webAssemblyWrapperFunctionStructure.visit(visitor);
     thisObject->m_webAssemblyToJSCalleeStructure.visit(visitor);
     FOR_EACH_WEBASSEMBLY_CONSTRUCTOR_TYPE(VISIT_LAZY_TYPE)
     thisObject->m_webAssemblyWrapperFunctionStructure.visit(visitor);
     thisObject->m_webAssemblyToJSCalleeStructure.visit(visitor);
     FOR_EACH_WEBASSEMBLY_CONSTRUCTOR_TYPE(VISIT_LAZY_TYPE)
index 46f56c5..8f60764 100644 (file)
@@ -400,6 +400,7 @@ public:
 #if ENABLE(WEBASSEMBLY)
     LazyProperty<JSGlobalObject, Structure> m_webAssemblyModuleRecordStructure;
     LazyProperty<JSGlobalObject, Structure> m_webAssemblyFunctionStructure;
 #if ENABLE(WEBASSEMBLY)
     LazyProperty<JSGlobalObject, Structure> m_webAssemblyModuleRecordStructure;
     LazyProperty<JSGlobalObject, Structure> m_webAssemblyFunctionStructure;
+    LazyProperty<JSGlobalObject, Structure> m_jsToWasmICCalleeStructure;
     LazyProperty<JSGlobalObject, Structure> m_webAssemblyWrapperFunctionStructure;
     LazyProperty<JSGlobalObject, Structure> m_webAssemblyToJSCalleeStructure;
     FOR_EACH_WEBASSEMBLY_CONSTRUCTOR_TYPE(DEFINE_STORAGE_FOR_LAZY_TYPE)
     LazyProperty<JSGlobalObject, Structure> m_webAssemblyWrapperFunctionStructure;
     LazyProperty<JSGlobalObject, Structure> m_webAssemblyToJSCalleeStructure;
     FOR_EACH_WEBASSEMBLY_CONSTRUCTOR_TYPE(DEFINE_STORAGE_FOR_LAZY_TYPE)
@@ -764,6 +765,7 @@ public:
 #if ENABLE(WEBASSEMBLY)
     Structure* webAssemblyModuleRecordStructure() const { return m_webAssemblyModuleRecordStructure.get(this); }
     Structure* webAssemblyFunctionStructure() const { return m_webAssemblyFunctionStructure.get(this); }
 #if ENABLE(WEBASSEMBLY)
     Structure* webAssemblyModuleRecordStructure() const { return m_webAssemblyModuleRecordStructure.get(this); }
     Structure* webAssemblyFunctionStructure() const { return m_webAssemblyFunctionStructure.get(this); }
+    Structure* jsToWasmICCalleeStructure() const { return m_jsToWasmICCalleeStructure.get(this); }
     Structure* webAssemblyWrapperFunctionStructure() const { return m_webAssemblyWrapperFunctionStructure.get(this); }
     Structure* webAssemblyToJSCalleeStructure() const { return m_webAssemblyToJSCalleeStructure.get(this); }
 #endif // ENABLE(WEBASSEMBLY)
     Structure* webAssemblyWrapperFunctionStructure() const { return m_webAssemblyWrapperFunctionStructure.get(this); }
     Structure* webAssemblyToJSCalleeStructure() const { return m_webAssemblyToJSCalleeStructure.get(this); }
 #endif // ENABLE(WEBASSEMBLY)
index 65af3a0..87423fe 100644 (file)
 #include "Watchdog.h"
 #include "WeakGCMapInlines.h"
 #include "WebAssemblyFunction.h"
 #include "Watchdog.h"
 #include "WeakGCMapInlines.h"
 #include "WebAssemblyFunction.h"
+#include "WebAssemblyFunctionHeapCellType.h"
 #include "WebAssemblyWrapperFunction.h"
 #include <wtf/ProcessID.h>
 #include <wtf/ReadWriteLock.h>
 #include "WebAssemblyWrapperFunction.h"
 #include <wtf/ProcessID.h>
 #include <wtf/ReadWriteLock.h>
@@ -280,6 +281,7 @@ VM::VM(VMType vmType, HeapType heapType)
     , destructibleObjectHeapCellType(std::make_unique<JSDestructibleObjectHeapCellType>())
 #if ENABLE(WEBASSEMBLY)
     , webAssemblyCodeBlockHeapCellType(std::make_unique<JSWebAssemblyCodeBlockHeapCellType>())
     , destructibleObjectHeapCellType(std::make_unique<JSDestructibleObjectHeapCellType>())
 #if ENABLE(WEBASSEMBLY)
     , webAssemblyCodeBlockHeapCellType(std::make_unique<JSWebAssemblyCodeBlockHeapCellType>())
+    , webAssemblyFunctionHeapCellType(std::make_unique<WebAssemblyFunctionHeapCellType>())
 #endif
     , primitiveGigacageAuxiliarySpace("Primitive Gigacage Auxiliary", heap, auxiliaryHeapCellType.get(), primitiveGigacageAllocator.get())
     , jsValueGigacageAuxiliarySpace("JSValue Gigacage Auxiliary", heap, auxiliaryHeapCellType.get(), jsValueGigacageAllocator.get())
 #endif
     , primitiveGigacageAuxiliarySpace("Primitive Gigacage Auxiliary", heap, auxiliaryHeapCellType.get(), primitiveGigacageAllocator.get())
     , jsValueGigacageAuxiliarySpace("JSValue Gigacage Auxiliary", heap, auxiliaryHeapCellType.get(), jsValueGigacageAllocator.get())
@@ -1264,7 +1266,7 @@ DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER_SLOW(objCCallbackFunctionSpace, destructibleO
 #endif
 #if ENABLE(WEBASSEMBLY)
 DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER_SLOW(webAssemblyCodeBlockSpace, webAssemblyCodeBlockHeapCellType.get(), JSWebAssemblyCodeBlock)
 #endif
 #if ENABLE(WEBASSEMBLY)
 DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER_SLOW(webAssemblyCodeBlockSpace, webAssemblyCodeBlockHeapCellType.get(), JSWebAssemblyCodeBlock)
-DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER_SLOW(webAssemblyFunctionSpace, cellHeapCellType.get(), WebAssemblyFunction)
+DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER_SLOW(webAssemblyFunctionSpace, webAssemblyFunctionHeapCellType.get(), WebAssemblyFunction)
 DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER_SLOW(webAssemblyWrapperFunctionSpace, cellHeapCellType.get(), WebAssemblyWrapperFunction)
 #endif
 
 DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER_SLOW(webAssemblyWrapperFunctionSpace, cellHeapCellType.get(), WebAssemblyWrapperFunction)
 #endif
 
index c5fbe5e..e0fe5fa 100644 (file)
@@ -158,6 +158,7 @@ class VMEntryScope;
 class Watchdog;
 class Watchpoint;
 class WatchpointSet;
 class Watchdog;
 class Watchpoint;
 class WatchpointSet;
+class WebAssemblyFunctionHeapCellType;
 
 #if ENABLE(FTL_JIT)
 namespace FTL {
 
 #if ENABLE(FTL_JIT)
 namespace FTL {
@@ -337,6 +338,7 @@ public:
     std::unique_ptr<JSDestructibleObjectHeapCellType> destructibleObjectHeapCellType;
 #if ENABLE(WEBASSEMBLY)
     std::unique_ptr<JSWebAssemblyCodeBlockHeapCellType> webAssemblyCodeBlockHeapCellType;
     std::unique_ptr<JSDestructibleObjectHeapCellType> destructibleObjectHeapCellType;
 #if ENABLE(WEBASSEMBLY)
     std::unique_ptr<JSWebAssemblyCodeBlockHeapCellType> webAssemblyCodeBlockHeapCellType;
+    std::unique_ptr<WebAssemblyFunctionHeapCellType> webAssemblyFunctionHeapCellType;
 #endif
     
     CompleteSubspace primitiveGigacageAuxiliarySpace; // Typed arrays, strings, bitvectors, etc go here.
 #endif
     
     CompleteSubspace primitiveGigacageAuxiliarySpace; // Typed arrays, strings, bitvectors, etc go here.
index d95571e..07e219c 100644 (file)
@@ -680,10 +680,8 @@ AirIRGenerator::AirIRGenerator(const ModuleInformation& info, B3::Procedure& pro
         m_code.pinRegister(m_wasmContextInstanceGPR);
 
     if (mode != MemoryMode::Signaling) {
         m_code.pinRegister(m_wasmContextInstanceGPR);
 
     if (mode != MemoryMode::Signaling) {
-        ASSERT(!pinnedRegs.sizeRegisters[0].sizeOffset);
-        m_memorySizeGPR = pinnedRegs.sizeRegisters[0].sizeRegister;
-        for (const PinnedSizeRegisterInfo& regInfo : pinnedRegs.sizeRegisters)
-            m_code.pinRegister(regInfo.sizeRegister);
+        m_memorySizeGPR = pinnedRegs.sizeRegister;
+        m_code.pinRegister(m_memorySizeGPR);
     }
 
     if (throwWasmException)
     }
 
     if (throwWasmException)
@@ -823,8 +821,7 @@ void AirIRGenerator::restoreWebAssemblyGlobalState(RestoreCachedStackLimit resto
         const PinnedRegisterInfo* pinnedRegs = &PinnedRegisterInfo::get();
         RegisterSet clobbers;
         clobbers.set(pinnedRegs->baseMemoryPointer);
         const PinnedRegisterInfo* pinnedRegs = &PinnedRegisterInfo::get();
         RegisterSet clobbers;
         clobbers.set(pinnedRegs->baseMemoryPointer);
-        for (auto info : pinnedRegs->sizeRegisters)
-            clobbers.set(info.sizeRegister);
+        clobbers.set(pinnedRegs->sizeRegister);
 
         auto* patchpoint = addPatchpoint(B3::Void);
         B3::Effects effects = B3::Effects::none();
 
         auto* patchpoint = addPatchpoint(B3::Void);
         B3::Effects effects = B3::Effects::none();
@@ -834,14 +831,8 @@ void AirIRGenerator::restoreWebAssemblyGlobalState(RestoreCachedStackLimit resto
         patchpoint->clobber(clobbers);
 
         patchpoint->setGenerator([pinnedRegs] (CCallHelpers& jit, const B3::StackmapGenerationParams& params) {
         patchpoint->clobber(clobbers);
 
         patchpoint->setGenerator([pinnedRegs] (CCallHelpers& jit, const B3::StackmapGenerationParams& params) {
-            GPRReg baseMemory = pinnedRegs->baseMemoryPointer;
-            const auto& sizeRegs = pinnedRegs->sizeRegisters;
-            ASSERT(sizeRegs.size() >= 1);
-            ASSERT(!sizeRegs[0].sizeOffset); // The following code assumes we start at 0, and calculates subsequent size registers relative to 0.
-            jit.loadPtr(CCallHelpers::Address(params[0].gpr(), Instance::offsetOfCachedMemorySize()), sizeRegs[0].sizeRegister);
-            jit.loadPtr(CCallHelpers::Address(params[0].gpr(), Instance::offsetOfCachedMemory()), baseMemory);
-            for (unsigned i = 1; i < sizeRegs.size(); ++i)
-                jit.add64(CCallHelpers::TrustedImm32(-sizeRegs[i].sizeOffset), sizeRegs[0].sizeRegister, sizeRegs[i].sizeRegister);
+            jit.loadPtr(CCallHelpers::Address(params[0].gpr(), Instance::offsetOfCachedMemorySize()), pinnedRegs->sizeRegister);
+            jit.loadPtr(CCallHelpers::Address(params[0].gpr(), Instance::offsetOfCachedMemory()), pinnedRegs->baseMemoryPointer);
         });
 
         emitPatchpoint(block, patchpoint, Tmp(), instance);
         });
 
         emitPatchpoint(block, patchpoint, Tmp(), instance);
@@ -1855,19 +1846,15 @@ auto AirIRGenerator::addCallIndirect(const Signature& signature, Vector<Expressi
             GPRReg newContextInstance = params[0].gpr();
             GPRReg oldContextInstance = params[1].gpr();
             const PinnedRegisterInfo& pinnedRegs = PinnedRegisterInfo::get();
             GPRReg newContextInstance = params[0].gpr();
             GPRReg oldContextInstance = params[1].gpr();
             const PinnedRegisterInfo& pinnedRegs = PinnedRegisterInfo::get();
-            const auto& sizeRegs = pinnedRegs.sizeRegisters;
             GPRReg baseMemory = pinnedRegs.baseMemoryPointer;
             ASSERT(newContextInstance != baseMemory);
             jit.loadPtr(CCallHelpers::Address(oldContextInstance, Instance::offsetOfCachedStackLimit()), baseMemory);
             jit.storePtr(baseMemory, CCallHelpers::Address(newContextInstance, Instance::offsetOfCachedStackLimit()));
             jit.storeWasmContextInstance(newContextInstance);
             GPRReg baseMemory = pinnedRegs.baseMemoryPointer;
             ASSERT(newContextInstance != baseMemory);
             jit.loadPtr(CCallHelpers::Address(oldContextInstance, Instance::offsetOfCachedStackLimit()), baseMemory);
             jit.storePtr(baseMemory, CCallHelpers::Address(newContextInstance, Instance::offsetOfCachedStackLimit()));
             jit.storeWasmContextInstance(newContextInstance);
-            ASSERT(sizeRegs[0].sizeRegister != baseMemory);
             // FIXME: We should support more than one memory size register
             //   see: https://bugs.webkit.org/show_bug.cgi?id=162952
             // FIXME: We should support more than one memory size register
             //   see: https://bugs.webkit.org/show_bug.cgi?id=162952
-            ASSERT(sizeRegs.size() == 1);
-            ASSERT(sizeRegs[0].sizeRegister != newContextInstance);
-            ASSERT(!sizeRegs[0].sizeOffset);
-            jit.loadPtr(CCallHelpers::Address(newContextInstance, Instance::offsetOfCachedMemorySize()), sizeRegs[0].sizeRegister); // Memory size.
+            ASSERT(pinnedRegs.sizeRegister != newContextInstance);
+            jit.loadPtr(CCallHelpers::Address(newContextInstance, Instance::offsetOfCachedMemorySize()), pinnedRegs.sizeRegister); // Memory size.
             jit.loadPtr(CCallHelpers::Address(newContextInstance, Instance::offsetOfCachedMemory()), baseMemory); // Memory::void*.
         });
 
             jit.loadPtr(CCallHelpers::Address(newContextInstance, Instance::offsetOfCachedMemory()), baseMemory); // Memory::void*.
         });
 
index 5a5f727..7a7bdc3 100644 (file)
@@ -346,10 +346,8 @@ B3IRGenerator::B3IRGenerator(const ModuleInformation& info, Procedure& procedure
         m_proc.pinRegister(m_wasmContextInstanceGPR);
 
     if (mode != MemoryMode::Signaling) {
         m_proc.pinRegister(m_wasmContextInstanceGPR);
 
     if (mode != MemoryMode::Signaling) {
-        ASSERT(!pinnedRegs.sizeRegisters[0].sizeOffset);
-        m_memorySizeGPR = pinnedRegs.sizeRegisters[0].sizeRegister;
-        for (const PinnedSizeRegisterInfo& regInfo : pinnedRegs.sizeRegisters)
-            m_proc.pinRegister(regInfo.sizeRegister);
+        m_memorySizeGPR = pinnedRegs.sizeRegister;
+        m_proc.pinRegister(m_memorySizeGPR);
     }
 
     if (throwWasmException)
     }
 
     if (throwWasmException)
@@ -469,8 +467,7 @@ void B3IRGenerator::restoreWebAssemblyGlobalState(RestoreCachedStackLimit restor
         const PinnedRegisterInfo* pinnedRegs = &PinnedRegisterInfo::get();
         RegisterSet clobbers;
         clobbers.set(pinnedRegs->baseMemoryPointer);
         const PinnedRegisterInfo* pinnedRegs = &PinnedRegisterInfo::get();
         RegisterSet clobbers;
         clobbers.set(pinnedRegs->baseMemoryPointer);
-        for (auto info : pinnedRegs->sizeRegisters)
-            clobbers.set(info.sizeRegister);
+        clobbers.set(pinnedRegs->sizeRegister);
 
         B3::PatchpointValue* patchpoint = block->appendNew<B3::PatchpointValue>(proc, B3::Void, origin());
         Effects effects = Effects::none();
 
         B3::PatchpointValue* patchpoint = block->appendNew<B3::PatchpointValue>(proc, B3::Void, origin());
         Effects effects = Effects::none();
@@ -483,13 +480,8 @@ void B3IRGenerator::restoreWebAssemblyGlobalState(RestoreCachedStackLimit restor
 
         patchpoint->setGenerator([pinnedRegs] (CCallHelpers& jit, const B3::StackmapGenerationParams& params) {
             GPRReg baseMemory = pinnedRegs->baseMemoryPointer;
 
         patchpoint->setGenerator([pinnedRegs] (CCallHelpers& jit, const B3::StackmapGenerationParams& params) {
             GPRReg baseMemory = pinnedRegs->baseMemoryPointer;
-            const auto& sizeRegs = pinnedRegs->sizeRegisters;
-            ASSERT(sizeRegs.size() >= 1);
-            ASSERT(!sizeRegs[0].sizeOffset); // The following code assumes we start at 0, and calculates subsequent size registers relative to 0.
-            jit.loadPtr(CCallHelpers::Address(params[0].gpr(), Instance::offsetOfCachedMemorySize()), sizeRegs[0].sizeRegister);
+            jit.loadPtr(CCallHelpers::Address(params[0].gpr(), Instance::offsetOfCachedMemorySize()), pinnedRegs->sizeRegister);
             jit.loadPtr(CCallHelpers::Address(params[0].gpr(), Instance::offsetOfCachedMemory()), baseMemory);
             jit.loadPtr(CCallHelpers::Address(params[0].gpr(), Instance::offsetOfCachedMemory()), baseMemory);
-            for (unsigned i = 1; i < sizeRegs.size(); ++i)
-                jit.add64(CCallHelpers::TrustedImm32(-sizeRegs[i].sizeOffset), sizeRegs[0].sizeRegister, sizeRegs[i].sizeRegister);
         });
     }
 }
         });
     }
 }
@@ -1282,19 +1274,16 @@ auto B3IRGenerator::addCallIndirect(const Signature& signature, Vector<Expressio
             GPRReg newContextInstance = params[0].gpr();
             GPRReg oldContextInstance = params[1].gpr();
             const PinnedRegisterInfo& pinnedRegs = PinnedRegisterInfo::get();
             GPRReg newContextInstance = params[0].gpr();
             GPRReg oldContextInstance = params[1].gpr();
             const PinnedRegisterInfo& pinnedRegs = PinnedRegisterInfo::get();
-            const auto& sizeRegs = pinnedRegs.sizeRegisters;
             GPRReg baseMemory = pinnedRegs.baseMemoryPointer;
             ASSERT(newContextInstance != baseMemory);
             jit.loadPtr(CCallHelpers::Address(oldContextInstance, Instance::offsetOfCachedStackLimit()), baseMemory);
             jit.storePtr(baseMemory, CCallHelpers::Address(newContextInstance, Instance::offsetOfCachedStackLimit()));
             jit.storeWasmContextInstance(newContextInstance);
             GPRReg baseMemory = pinnedRegs.baseMemoryPointer;
             ASSERT(newContextInstance != baseMemory);
             jit.loadPtr(CCallHelpers::Address(oldContextInstance, Instance::offsetOfCachedStackLimit()), baseMemory);
             jit.storePtr(baseMemory, CCallHelpers::Address(newContextInstance, Instance::offsetOfCachedStackLimit()));
             jit.storeWasmContextInstance(newContextInstance);
-            ASSERT(sizeRegs[0].sizeRegister != baseMemory);
+            ASSERT(pinnedRegs.sizeRegister != baseMemory);
             // FIXME: We should support more than one memory size register
             //   see: https://bugs.webkit.org/show_bug.cgi?id=162952
             // FIXME: We should support more than one memory size register
             //   see: https://bugs.webkit.org/show_bug.cgi?id=162952
-            ASSERT(sizeRegs.size() == 1);
-            ASSERT(sizeRegs[0].sizeRegister != newContextInstance);
-            ASSERT(!sizeRegs[0].sizeOffset);
-            jit.loadPtr(CCallHelpers::Address(newContextInstance, Instance::offsetOfCachedMemorySize()), sizeRegs[0].sizeRegister); // Memory size.
+            ASSERT(pinnedRegs.sizeRegister != newContextInstance);
+            jit.loadPtr(CCallHelpers::Address(newContextInstance, Instance::offsetOfCachedMemorySize()), pinnedRegs.sizeRegister); // Memory size.
             jit.loadPtr(CCallHelpers::Address(newContextInstance, Instance::offsetOfCachedMemory()), baseMemory); // Memory::void*.
         });
         doContextSwitch->appendNewControlValue(m_proc, Jump, origin(), continuation);
             jit.loadPtr(CCallHelpers::Address(newContextInstance, Instance::offsetOfCachedMemory()), baseMemory); // Memory::void*.
         });
         doContextSwitch->appendNewControlValue(m_proc, Jump, origin(), continuation);
index c3faec1..ea13a25 100644 (file)
@@ -48,11 +48,9 @@ Expected<MacroAssemblerCodeRef<WasmEntryPtrTag>, BindingFailure> wasmToWasm(unsi
     GPRReg scratch = GPRInfo::nonPreservedNonArgumentGPR0;
     GPRReg baseMemory = pinnedRegs.baseMemoryPointer;
     ASSERT(baseMemory != scratch);
     GPRReg scratch = GPRInfo::nonPreservedNonArgumentGPR0;
     GPRReg baseMemory = pinnedRegs.baseMemoryPointer;
     ASSERT(baseMemory != scratch);
-    const auto& sizeRegs = pinnedRegs.sizeRegisters;
-    ASSERT(sizeRegs.size() >= 1);
-    ASSERT(sizeRegs[0].sizeRegister != baseMemory);
-    ASSERT(sizeRegs[0].sizeRegister != scratch);
-    GPRReg sizeRegAsScratch = sizeRegs[0].sizeRegister;
+    ASSERT(pinnedRegs.sizeRegister != baseMemory);
+    ASSERT(pinnedRegs.sizeRegister != scratch);
+    GPRReg sizeRegAsScratch = pinnedRegs.sizeRegister;
 
     // B3's call codegen ensures that the JSCell is a WebAssemblyFunction.
     jit.loadWasmContextInstance(sizeRegAsScratch); // Old Instance*
 
     // B3's call codegen ensures that the JSCell is a WebAssemblyFunction.
     jit.loadWasmContextInstance(sizeRegAsScratch); // Old Instance*
@@ -67,14 +65,8 @@ Expected<MacroAssemblerCodeRef<WasmEntryPtrTag>, BindingFailure> wasmToWasm(unsi
 
     // FIXME the following code assumes that all Wasm::Instance have the same pinned registers. https://bugs.webkit.org/show_bug.cgi?id=162952
     // Set up the callee's baseMemory register as well as the memory size registers.
 
     // FIXME the following code assumes that all Wasm::Instance have the same pinned registers. https://bugs.webkit.org/show_bug.cgi?id=162952
     // Set up the callee's baseMemory register as well as the memory size registers.
-    ASSERT(!sizeRegs[0].sizeOffset); // The following code assumes we start at 0, and calculates subsequent size registers relative to 0.
-    jit.loadPtr(JIT::Address(baseMemory, Wasm::Instance::offsetOfCachedMemorySize()), sizeRegs[0].sizeRegister); // Memory size.
+    jit.loadPtr(JIT::Address(baseMemory, Wasm::Instance::offsetOfCachedMemorySize()), pinnedRegs.sizeRegister); // Memory size.
     jit.loadPtr(JIT::Address(baseMemory, Wasm::Instance::offsetOfCachedMemory()), baseMemory); // Wasm::Memory::void*.
     jit.loadPtr(JIT::Address(baseMemory, Wasm::Instance::offsetOfCachedMemory()), baseMemory); // Wasm::Memory::void*.
-    for (unsigned i = 1; i < sizeRegs.size(); ++i) {
-        ASSERT(sizeRegs[i].sizeRegister != baseMemory);
-        ASSERT(sizeRegs[i].sizeRegister != scratch);
-        jit.add64(JIT::TrustedImm32(-sizeRegs[i].sizeOffset), sizeRegs[0].sizeRegister, sizeRegs[i].sizeRegister);
-    }
 
     // Tail call into the callee WebAssembly function.
     jit.loadPtr(scratch, scratch);
 
     // Tail call into the callee WebAssembly function.
     jit.loadPtr(scratch, scratch);
index b6ce195..fe44f5e 100644 (file)
@@ -32,12 +32,19 @@ namespace JSC { namespace Wasm {
 class Instance;
 
 struct Context {
 class Instance;
 
 struct Context {
-    Instance* instance { nullptr };
-
     Instance* load() const;
     void store(Instance*, void* softStackLimit);
 
     static bool useFastTLS();
     Instance* load() const;
     void store(Instance*, void* softStackLimit);
 
     static bool useFastTLS();
+
+    Instance** pointerToInstance()
+    {
+        ASSERT(!useFastTLS());
+        return &instance;
+    }
+
+private:
+    Instance* instance { nullptr };
 };
 
 } } // namespace JSC::Wasm
 };
 
 } } // namespace JSC::Wasm
index 713be67..881f3e3 100644 (file)
@@ -55,13 +55,15 @@ inline Instance* Context::load() const
 
 inline void Context::store(Instance* inst, void* softStackLimit)
 {
 
 inline void Context::store(Instance* inst, void* softStackLimit)
 {
+    if (inst)
+        inst->setCachedStackLimit(softStackLimit);
+
 #if ENABLE(FAST_TLS_JIT)
     if (useFastTLS())
         _pthread_setspecific_direct(WTF_WASM_CONTEXT_KEY, bitwise_cast<void*>(inst));
 #if ENABLE(FAST_TLS_JIT)
     if (useFastTLS())
         _pthread_setspecific_direct(WTF_WASM_CONTEXT_KEY, bitwise_cast<void*>(inst));
+    else
 #endif
 #endif
-    instance = inst;
-    if (instance)
-        instance->setCachedStackLimit(softStackLimit);
+        instance = inst;
 }
 
 } } // namespace JSC::Wasm
 }
 
 } } // namespace JSC::Wasm
index c3a4041..2bb38d9 100644 (file)
@@ -44,6 +44,11 @@ static Vector<GPRReg> getPinnedRegisters(unsigned remainingPinnedRegisters)
         GPRReg gpr = reg.gpr();
         if (!remainingPinnedRegisters || RegisterSet::stackRegisters().get(reg))
             return;
         GPRReg gpr = reg.gpr();
         if (!remainingPinnedRegisters || RegisterSet::stackRegisters().get(reg))
             return;
+        if (RegisterSet::runtimeTagRegisters().get(reg)) {
+            // Since we don't need to, we currently don't pick from the tag registers to allow
+            // JS->Wasm stubs to freely use these registers.
+            return;
+        }
         --remainingPinnedRegisters;
         registers.append(gpr);
     });
         --remainingPinnedRegisters;
         registers.append(gpr);
     });
@@ -55,35 +60,25 @@ const PinnedRegisterInfo& PinnedRegisterInfo::get()
     static LazyNeverDestroyed<PinnedRegisterInfo> staticPinnedRegisterInfo;
     static std::once_flag staticPinnedRegisterInfoFlag;
     std::call_once(staticPinnedRegisterInfoFlag, [] () {
     static LazyNeverDestroyed<PinnedRegisterInfo> staticPinnedRegisterInfo;
     static std::once_flag staticPinnedRegisterInfoFlag;
     std::call_once(staticPinnedRegisterInfoFlag, [] () {
-        Vector<PinnedSizeRegisterInfo> sizeRegisters;
-        GPRReg baseMemoryPointer = InvalidGPRReg;
-        GPRReg wasmContextInstancePointer = InvalidGPRReg;
-
-        // FIXME: We should support more than one memory size register, and we should allow different
-        //        WebAssembly.Instance to have different pins. Right now we take a vector with only one entry.
-        //        If we have more than one size register, we can have one for each load size class.
-        //        see: https://bugs.webkit.org/show_bug.cgi?id=162952
-        Vector<unsigned> pinnedSizes = { 0 };
-        unsigned numberOfPinnedRegisters = pinnedSizes.size() + 1;
+        unsigned numberOfPinnedRegisters = 2;
         if (!Context::useFastTLS())
             ++numberOfPinnedRegisters;
         Vector<GPRReg> pinnedRegs = getPinnedRegisters(numberOfPinnedRegisters);
 
         if (!Context::useFastTLS())
             ++numberOfPinnedRegisters;
         Vector<GPRReg> pinnedRegs = getPinnedRegisters(numberOfPinnedRegisters);
 
-        baseMemoryPointer = pinnedRegs.takeLast();
+        GPRReg baseMemoryPointer = pinnedRegs.takeLast();
+        GPRReg sizeRegister = pinnedRegs.takeLast();
+        GPRReg wasmContextInstancePointer = InvalidGPRReg;
         if (!Context::useFastTLS())
             wasmContextInstancePointer = pinnedRegs.takeLast();
 
         if (!Context::useFastTLS())
             wasmContextInstancePointer = pinnedRegs.takeLast();
 
-        ASSERT(pinnedSizes.size() == pinnedRegs.size());
-        for (unsigned i = 0; i < pinnedSizes.size(); ++i)
-            sizeRegisters.append({ pinnedRegs[i], pinnedSizes[i] });
-        staticPinnedRegisterInfo.construct(WTFMove(sizeRegisters), baseMemoryPointer, wasmContextInstancePointer);
+        staticPinnedRegisterInfo.construct(sizeRegister, baseMemoryPointer, wasmContextInstancePointer);
     });
 
     return staticPinnedRegisterInfo.get();
 }
 
     });
 
     return staticPinnedRegisterInfo.get();
 }
 
-PinnedRegisterInfo::PinnedRegisterInfo(Vector<PinnedSizeRegisterInfo>&& sizeRegisters, GPRReg baseMemoryPointer, GPRReg wasmContextInstancePointer)
-    : sizeRegisters(WTFMove(sizeRegisters))
+PinnedRegisterInfo::PinnedRegisterInfo(GPRReg sizeRegister, GPRReg baseMemoryPointer, GPRReg wasmContextInstancePointer)
+    : sizeRegister(sizeRegister)
     , baseMemoryPointer(baseMemoryPointer)
     , wasmContextInstancePointer(wasmContextInstancePointer)
 {
     , baseMemoryPointer(baseMemoryPointer)
     , wasmContextInstancePointer(wasmContextInstancePointer)
 {
index 8cebc5f..4b8ef8e 100644 (file)
@@ -45,7 +45,7 @@ struct PinnedSizeRegisterInfo {
 
 class PinnedRegisterInfo {
 public:
 
 class PinnedRegisterInfo {
 public:
-    PinnedRegisterInfo(Vector<PinnedSizeRegisterInfo>&&, GPRReg, GPRReg);
+    PinnedRegisterInfo(GPRReg, GPRReg, GPRReg);
 
     static const PinnedRegisterInfo& get();
 
 
     static const PinnedRegisterInfo& get();
 
@@ -55,14 +55,12 @@ public:
         result.set(baseMemoryPointer);
         if (wasmContextInstancePointer != InvalidGPRReg)
             result.set(wasmContextInstancePointer);
         result.set(baseMemoryPointer);
         if (wasmContextInstancePointer != InvalidGPRReg)
             result.set(wasmContextInstancePointer);
-        if (mode != MemoryMode::Signaling) {
-            for (const auto& info : sizeRegisters)
-                result.set(info.sizeRegister);
-        }
+        if (mode != MemoryMode::Signaling)
+            result.set(sizeRegister);
         return result;
     }
 
         return result;
     }
 
-    Vector<PinnedSizeRegisterInfo> sizeRegisters;
+    GPRReg sizeRegister;
     GPRReg baseMemoryPointer;
     GPRReg wasmContextInstancePointer;
 };
     GPRReg baseMemoryPointer;
     GPRReg wasmContextInstancePointer;
 };
index e31b471..79bf026 100644 (file)
@@ -138,7 +138,7 @@ void OMGPlan::work(CompilationEffort)
     {
         LockHolder holder(m_codeBlock->m_lock);
 
     {
         LockHolder holder(m_codeBlock->m_lock);
 
-        auto repatchCalls = [&] (const Vector<UnlinkedWasmToWasmCall>&  callsites) {
+        auto repatchCalls = [&] (const Vector<UnlinkedWasmToWasmCall>& callsites) {
             for (auto& call : callsites) {
                 dataLogLnIf(WasmOMGPlanInternal::verbose, "Considering repatching call at: ", RawPointer(call.callLocation.dataLocation()), " that targets ", call.functionIndexSpace);
                 if (call.functionIndexSpace == functionIndexSpace) {
             for (auto& call : callsites) {
                 dataLogLnIf(WasmOMGPlanInternal::verbose, "Considering repatching call at: ", RawPointer(call.callLocation.dataLocation()), " that targets ", call.functionIndexSpace);
                 if (call.functionIndexSpace == functionIndexSpace) {
index ae30b22..e0b821b 100644 (file)
@@ -213,14 +213,8 @@ std::unique_ptr<InternalFunction> createJSToWasmWrapper(CompilationContext& comp
             jit.loadWasmContextInstance(baseMemory);
 
         GPRReg currentInstanceGPR = Context::useFastTLS() ? baseMemory : wasmContextInstanceGPR;
             jit.loadWasmContextInstance(baseMemory);
 
         GPRReg currentInstanceGPR = Context::useFastTLS() ? baseMemory : wasmContextInstanceGPR;
-        if (mode != MemoryMode::Signaling) {
-            const auto& sizeRegs = pinnedRegs.sizeRegisters;
-            ASSERT(sizeRegs.size() >= 1);
-            ASSERT(!sizeRegs[0].sizeOffset); // The following code assumes we start at 0, and calculates subsequent size registers relative to 0.
-            jit.loadPtr(CCallHelpers::Address(currentInstanceGPR, Wasm::Instance::offsetOfCachedMemorySize()), sizeRegs[0].sizeRegister);
-            for (unsigned i = 1; i < sizeRegs.size(); ++i)
-                jit.add64(CCallHelpers::TrustedImm32(-sizeRegs[i].sizeOffset), sizeRegs[0].sizeRegister, sizeRegs[i].sizeRegister);
-        }
+        if (mode != MemoryMode::Signaling)
+            jit.loadPtr(CCallHelpers::Address(currentInstanceGPR, Wasm::Instance::offsetOfCachedMemorySize()), pinnedRegs.sizeRegister);
 
         jit.loadPtr(CCallHelpers::Address(currentInstanceGPR, Wasm::Instance::offsetOfCachedMemory()), baseMemory);
     }
 
         jit.loadPtr(CCallHelpers::Address(currentInstanceGPR, Wasm::Instance::offsetOfCachedMemory()), baseMemory);
     }
diff --git a/Source/JavaScriptCore/wasm/js/JSToWasmICCallee.cpp b/Source/JavaScriptCore/wasm/js/JSToWasmICCallee.cpp
new file mode 100644 (file)
index 0000000..de5da9b
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2019 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "JSToWasmICCallee.h"
+
+#if ENABLE(WEBASSEMBLY)
+
+#include "WebAssemblyFunction.h"
+
+namespace JSC {
+
+const ClassInfo JSToWasmICCallee::s_info = { "JSToWasmICCallee", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSToWasmICCallee) };
+
+JSToWasmICCallee* JSToWasmICCallee::create(VM& vm, JSGlobalObject* globalObject, WebAssemblyFunction* function)
+{
+    auto* structure = globalObject->jsToWasmICCalleeStructure();
+    JSToWasmICCallee* result = new (NotNull, allocateCell<JSToWasmICCallee>(vm.heap)) JSToWasmICCallee(vm, globalObject, structure);
+    result->finishCreation(vm);
+    result->m_function.set(vm, result, function);
+    return result;
+}
+
+Structure* JSToWasmICCallee::createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
+{
+    return Structure::create(vm, globalObject, prototype, TypeInfo(JSCalleeType, StructureFlags), info());
+}
+
+void JSToWasmICCallee::visitChildren(JSCell* cell, SlotVisitor& visitor)
+{
+    JSToWasmICCallee* thisObject = jsCast<JSToWasmICCallee*>(cell);
+    ASSERT_GC_OBJECT_INHERITS(thisObject, info());
+
+    Base::visitChildren(thisObject, visitor);
+    visitor.append(thisObject->m_function);
+}
+
+} // namespace JSC
+
+#endif // ENABLE(WEBASSEMBLY)
diff --git a/Source/JavaScriptCore/wasm/js/JSToWasmICCallee.h b/Source/JavaScriptCore/wasm/js/JSToWasmICCallee.h
new file mode 100644 (file)
index 0000000..4618ebb
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2019 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include "JSCallee.h"
+
+namespace JSC {
+
+#if ENABLE(WEBASSEMBLY)
+
+class WebAssemblyFunction;
+
+class JSToWasmICCallee : public JSCallee {
+    using Base = JSCallee;
+public:
+    DECLARE_INFO;
+
+    static JSToWasmICCallee* create(VM&, JSGlobalObject*, WebAssemblyFunction*);
+    static Structure* createStructure(VM&, JSGlobalObject*, JSValue);
+
+    WebAssemblyFunction* function() { return m_function.get(); }
+
+private:
+    JSToWasmICCallee(VM& vm, JSGlobalObject* globalObject, Structure* structure)
+        : Base(vm, globalObject, structure)
+    { }
+    static void visitChildren(JSCell*, SlotVisitor&);
+
+    WriteBarrier<WebAssemblyFunction> m_function;
+};
+
+#endif // ENABLE(WEBASSEMBLY)
+
+} // namespace JSC
index 42468ef..02ef41e 100644 (file)
 #include "JSWebAssemblyMemory.h"
 #include "JSWebAssemblyRuntimeError.h"
 #include "LLIntThunks.h"
 #include "JSWebAssemblyMemory.h"
 #include "JSWebAssemblyRuntimeError.h"
 #include "LLIntThunks.h"
+#include "LinkBuffer.h"
 #include "ProtoCallFrame.h"
 #include "VM.h"
 #include "WasmCallee.h"
 #include "ProtoCallFrame.h"
 #include "VM.h"
 #include "WasmCallee.h"
+#include "WasmCallingConvention.h"
 #include "WasmContextInlines.h"
 #include "WasmFormat.h"
 #include "WasmMemory.h"
 #include "WasmContextInlines.h"
 #include "WasmFormat.h"
 #include "WasmMemory.h"
+#include "WasmMemoryInformation.h"
+#include "WasmModuleInformation.h"
 #include "WasmSignatureInlines.h"
 #include <wtf/FastTLS.h>
 #include <wtf/StackPointer.h>
 #include "WasmSignatureInlines.h"
 #include <wtf/FastTLS.h>
 #include <wtf/StackPointer.h>
@@ -148,6 +152,335 @@ static EncodedJSValue JSC_HOST_CALL callWebAssemblyFunction(ExecState* exec)
     return rawResult;
 }
 
     return rawResult;
 }
 
+bool WebAssemblyFunction::useTagRegisters() const
+{
+    const auto& signature = Wasm::SignatureInformation::get(signatureIndex());
+    return signature.argumentCount() || signature.returnType() != Wasm::Void;
+}
+
+RegisterSet WebAssemblyFunction::calleeSaves() const
+{
+    RegisterSet toSave = Wasm::PinnedRegisterInfo::get().toSave(instance()->memoryMode());
+    if (useTagRegisters()) {
+        RegisterSet tagRegisters = RegisterSet::runtimeTagRegisters();
+        // We rely on these being disjoint sets.
+#if !ASSERT_DISABLED
+        for (Reg reg : tagRegisters)
+            ASSERT(!toSave.contains(reg));
+#endif
+        toSave.merge(tagRegisters);
+    }
+    return toSave;
+}
+
+RegisterAtOffsetList WebAssemblyFunction::usedCalleeSaveRegisters() const
+{
+    return RegisterAtOffsetList { calleeSaves(), RegisterAtOffsetList::OffsetBaseType::FramePointerBased };
+}
+
+ptrdiff_t WebAssemblyFunction::previousInstanceOffset() const
+{
+    ptrdiff_t result = calleeSaves().numberOfSetRegisters() * sizeof(CPURegister);
+    result = -result - sizeof(CPURegister);
+#if !ASSERT_DISABLED
+    ptrdiff_t minOffset = 1;
+    for (const RegisterAtOffset& regAtOffset : usedCalleeSaveRegisters()) {
+        ptrdiff_t offset = regAtOffset.offset();
+        ASSERT(offset < 0);
+        minOffset = std::min(offset, minOffset);
+    }
+    ASSERT(minOffset - static_cast<ptrdiff_t>(sizeof(CPURegister)) == result);
+#endif
+    return result;
+}
+
+Wasm::Instance* WebAssemblyFunction::previousInstance(CallFrame* callFrame)
+{
+    ASSERT(callFrame->callee().rawPtr() == m_jsToWasmICCallee.get());
+    auto* result = *bitwise_cast<Wasm::Instance**>(bitwise_cast<char*>(callFrame) + previousInstanceOffset());
+    return result;
+}
+
+MacroAssemblerCodePtr<JSEntryPtrTag> WebAssemblyFunction::jsCallEntrypointSlow()
+{
+    VM& vm = *this->vm();
+    CCallHelpers jit;
+
+    const auto& signature = Wasm::SignatureInformation::get(signatureIndex());
+    const auto& pinnedRegs = Wasm::PinnedRegisterInfo::get();
+    RegisterAtOffsetList registersToSpill = usedCalleeSaveRegisters();
+
+    auto& moduleInformation = instance()->instance().module().moduleInformation();
+
+    unsigned totalFrameSize = registersToSpill.size() * sizeof(CPURegister);
+    totalFrameSize += sizeof(CPURegister); // Slot for the VM's previous wasm instance.
+    totalFrameSize += Wasm::WasmCallingConvention::headerSizeInBytes();
+    totalFrameSize -= sizeof(CallerFrameAndPC);
+
+    unsigned numGPRs = 0;
+    unsigned numFPRs = 0;
+    bool argumentsIncludeI64 = false;
+    for (unsigned i = 0; i < signature.argumentCount(); i++) {
+        switch (signature.argument(i)) {
+        case Wasm::I64:
+            argumentsIncludeI64 = true;
+            break;
+        case Wasm::I32:
+            if (numGPRs >= Wasm::wasmCallingConvention().m_gprArgs.size())
+                totalFrameSize += sizeof(CPURegister);
+            ++numGPRs;
+            break;
+        case Wasm::F32:
+        case Wasm::F64:
+            if (numFPRs >= Wasm::wasmCallingConvention().m_fprArgs.size())
+                totalFrameSize += sizeof(CPURegister);
+            ++numFPRs;
+            break;
+        default:
+            RELEASE_ASSERT_NOT_REACHED();
+        }
+    }
+
+    if (argumentsIncludeI64)
+        return nullptr;
+
+    totalFrameSize = WTF::roundUpToMultipleOf(stackAlignmentBytes(), totalFrameSize);
+
+    jit.emitFunctionPrologue();
+    jit.subPtr(MacroAssembler::TrustedImm32(totalFrameSize), MacroAssembler::stackPointerRegister);
+    jit.store64(CCallHelpers::TrustedImm64(0), CCallHelpers::addressFor(CallFrameSlot::codeBlock));
+
+    for (const RegisterAtOffset& regAtOffset : registersToSpill) {
+        GPRReg reg = regAtOffset.reg().gpr();
+        ptrdiff_t offset = regAtOffset.offset();
+        jit.storePtr(reg, CCallHelpers::Address(GPRInfo::callFrameRegister, offset));
+    }
+
+    GPRReg scratchGPR = Wasm::wasmCallingConventionAir().prologueScratch(1);
+    GPRReg scratch2GPR = Wasm::wasmCallingConventionAir().prologueScratch(0);
+    jit.loadPtr(vm.addressOfSoftStackLimit(), scratch2GPR);
+
+    CCallHelpers::JumpList slowPath;
+    slowPath.append(jit.branchPtr(CCallHelpers::Above, MacroAssembler::stackPointerRegister, GPRInfo::callFrameRegister));
+    slowPath.append(jit.branchPtr(CCallHelpers::Below, MacroAssembler::stackPointerRegister, scratch2GPR));
+
+    // Ensure:
+    // argCountPlusThis - 1 >= signature.argumentCount()
+    // argCountPlusThis >= signature.argumentCount() + 1
+    // FIXME: We should handle mismatched arity
+    // https://bugs.webkit.org/show_bug.cgi?id=196564
+    slowPath.append(jit.branch32(CCallHelpers::Below,
+        CCallHelpers::payloadFor(CallFrameSlot::argumentCount), CCallHelpers::TrustedImm32(signature.argumentCount() + 1)));
+
+    if (useTagRegisters())
+        jit.emitMaterializeTagCheckRegisters();
+
+    // First we do stack slots for FPRs so we can use FPR argument registers as scratch.
+    // After that, we handle FPR argument registers.
+    // We also handle all GPR types here as we have GPR scratch registers.
+    {
+        CCallHelpers::Address calleeFrame = CCallHelpers::Address(MacroAssembler::stackPointerRegister, -static_cast<ptrdiff_t>(sizeof(CallerFrameAndPC)));
+        numGPRs = 0;
+        numFPRs = 0;
+        FPRReg scratchFPR = Wasm::wasmCallingConvention().m_fprArgs[0].fpr();
+
+        ptrdiff_t jsOffset = CallFrameSlot::firstArgument * sizeof(EncodedJSValue);
+
+        ptrdiff_t wasmOffset = CallFrame::headerSizeInRegisters * sizeof(CPURegister);
+        for (unsigned i = 0; i < signature.argumentCount(); i++) {
+            switch (signature.argument(i)) {
+            case Wasm::I32:
+                jit.load64(CCallHelpers::Address(GPRInfo::callFrameRegister, jsOffset), scratchGPR);
+                slowPath.append(jit.branchIfNotInt32(scratchGPR));
+                if (numGPRs >= Wasm::wasmCallingConvention().m_gprArgs.size()) {
+                    jit.store32(scratchGPR, calleeFrame.withOffset(wasmOffset));
+                    wasmOffset += sizeof(CPURegister);
+                } else {
+                    jit.zeroExtend32ToPtr(scratchGPR, Wasm::wasmCallingConvention().m_gprArgs[numGPRs].gpr());
+                    ++numGPRs;
+                }
+                break;
+            case Wasm::F32:
+            case Wasm::F64:
+                if (numFPRs >= Wasm::wasmCallingConvention().m_fprArgs.size()) {
+                    jit.load64(CCallHelpers::Address(GPRInfo::callFrameRegister, jsOffset), scratchGPR);
+                    slowPath.append(jit.branchIfNotNumber(scratchGPR));
+                    auto isInt32 = jit.branchIfInt32(scratchGPR);
+                    if (signature.argument(i) == Wasm::F32) {
+                        jit.unboxDouble(scratchGPR, scratchGPR, scratchFPR);
+                        jit.convertDoubleToFloat(scratchFPR, scratchFPR);
+                        jit.storeFloat(scratchFPR, calleeFrame.withOffset(wasmOffset));
+                    } else {
+                        jit.add64(GPRInfo::tagTypeNumberRegister, scratchGPR, scratchGPR);
+                        jit.store64(scratchGPR, calleeFrame.withOffset(wasmOffset));
+                    }
+                    auto done = jit.jump();
+
+                    isInt32.link(&jit);
+                    if (signature.argument(i) == Wasm::F32) {
+                        jit.convertInt32ToFloat(scratchGPR, scratchFPR);
+                        jit.storeFloat(scratchFPR, calleeFrame.withOffset(wasmOffset));
+                    } else {
+                        jit.convertInt32ToDouble(scratchGPR, scratchFPR);
+                        jit.storeDouble(scratchFPR, calleeFrame.withOffset(wasmOffset));
+                    }
+                    done.link(&jit);
+
+                    wasmOffset += sizeof(CPURegister);
+                } else
+                    ++numFPRs;
+                break;
+            default:
+                RELEASE_ASSERT_NOT_REACHED();
+            }
+
+            jsOffset += sizeof(EncodedJSValue);
+        }
+    }
+
+    // Now handle FPR arguments in registers.
+    {
+        numFPRs = 0;
+        ptrdiff_t jsOffset = CallFrameSlot::firstArgument * sizeof(EncodedJSValue);
+        for (unsigned i = 0; i < signature.argumentCount(); i++) {
+            switch (signature.argument(i)) {
+            case Wasm::F32:
+            case Wasm::F64:
+                if (numFPRs < Wasm::wasmCallingConvention().m_fprArgs.size()) {
+                    FPRReg argFPR = Wasm::wasmCallingConvention().m_fprArgs[numFPRs].fpr();
+                    jit.load64(CCallHelpers::Address(GPRInfo::callFrameRegister, jsOffset), scratchGPR);
+                    slowPath.append(jit.branchIfNotNumber(scratchGPR));
+                    auto isInt32 = jit.branchIfInt32(scratchGPR);
+                    jit.unboxDouble(scratchGPR, scratchGPR, argFPR);
+                    if (signature.argument(i) == Wasm::F32)
+                        jit.convertDoubleToFloat(argFPR, argFPR);
+                    auto done = jit.jump();
+
+                    isInt32.link(&jit);
+                    if (signature.argument(i) == Wasm::F32)
+                        jit.convertInt32ToFloat(scratchGPR, argFPR);
+                    else
+                        jit.convertInt32ToDouble(scratchGPR, argFPR);
+
+                    done.link(&jit);
+                    ++numFPRs;
+                }
+                break;
+            default:
+                break;
+            }
+
+            jsOffset += sizeof(EncodedJSValue);
+        }
+    }
+
+    // At this point, we're committed to doing a fast call.
+
+    if (Wasm::Context::useFastTLS()) 
+        jit.loadWasmContextInstance(scratchGPR);
+    else
+        jit.loadPtr(vm.wasmContext.pointerToInstance(), scratchGPR);
+    ptrdiff_t previousInstanceOffset = this->previousInstanceOffset();
+    jit.storePtr(scratchGPR, CCallHelpers::Address(GPRInfo::callFrameRegister, previousInstanceOffset));
+
+    jit.move(CCallHelpers::TrustedImmPtr(&instance()->instance()), scratchGPR);
+    if (Wasm::Context::useFastTLS()) 
+        jit.storeWasmContextInstance(scratchGPR);
+    else {
+        jit.move(scratchGPR, pinnedRegs.wasmContextInstancePointer);
+        jit.storePtr(scratchGPR, vm.wasmContext.pointerToInstance());
+    }
+    // This contains the cached stack limit still.
+    jit.storePtr(scratch2GPR, CCallHelpers::Address(scratchGPR, Wasm::Instance::offsetOfCachedStackLimit()));
+
+    if (!!moduleInformation.memory) {
+        GPRReg baseMemory = pinnedRegs.baseMemoryPointer;
+
+        if (instance()->memoryMode() != Wasm::MemoryMode::Signaling) {
+            ASSERT(pinnedRegs.sizeRegister != scratchGPR);
+            jit.loadPtr(CCallHelpers::Address(scratchGPR, Wasm::Instance::offsetOfCachedMemorySize()), pinnedRegs.sizeRegister);
+        }
+
+        jit.loadPtr(CCallHelpers::Address(scratchGPR, Wasm::Instance::offsetOfCachedMemory()), baseMemory);
+    }
+
+    // We use this callee to indicate how to unwind past these types of frames:
+    // 1. We need to know where to get callee saves.
+    // 2. We need to know to restore the previous wasm context.
+    if (!m_jsToWasmICCallee)
+        m_jsToWasmICCallee.set(vm, this, JSToWasmICCallee::create(vm, globalObject(), this));
+    jit.storePtr(CCallHelpers::TrustedImmPtr(m_jsToWasmICCallee.get()), CCallHelpers::addressFor(CallFrameSlot::callee));
+
+    {
+        // FIXME: Currently we just do an indirect jump. But we should teach the Module
+        // how to repatch us:
+        // https://bugs.webkit.org/show_bug.cgi?id=196570
+        jit.loadPtr(entrypointLoadLocation(), scratchGPR);
+        jit.call(scratchGPR, WasmEntryPtrTag);
+    }
+
+    ASSERT(!RegisterSet::runtimeTagRegisters().contains(GPRInfo::nonPreservedNonReturnGPR));
+    jit.loadPtr(CCallHelpers::Address(GPRInfo::callFrameRegister, previousInstanceOffset), GPRInfo::nonPreservedNonReturnGPR);
+    if (Wasm::Context::useFastTLS())
+        jit.storeWasmContextInstance(GPRInfo::nonPreservedNonReturnGPR);
+    else
+        jit.storePtr(GPRInfo::nonPreservedNonReturnGPR, vm.wasmContext.pointerToInstance());
+
+    switch (signature.returnType()) {
+    case Wasm::Void:
+        jit.moveTrustedValue(jsUndefined(), JSValueRegs { GPRInfo::returnValueGPR });
+        break;
+    case Wasm::I32:
+        jit.zeroExtend32ToPtr(GPRInfo::returnValueGPR, GPRInfo::returnValueGPR);
+        jit.boxInt32(GPRInfo::returnValueGPR, JSValueRegs { GPRInfo::returnValueGPR });
+        break;
+    case Wasm::F32:
+        jit.convertFloatToDouble(FPRInfo::returnValueFPR, FPRInfo::returnValueFPR);
+        FALLTHROUGH;
+    case Wasm::F64: {
+        jit.moveTrustedValue(jsNumber(pureNaN()), JSValueRegs { GPRInfo::returnValueGPR });
+        auto isNaN = jit.branchIfNaN(FPRInfo::returnValueFPR);
+        jit.boxDouble(FPRInfo::returnValueFPR, JSValueRegs { GPRInfo::returnValueGPR });
+        isNaN.link(&jit);
+        break;
+    }
+    case Wasm::I64:
+    case Wasm::Func:
+    case Wasm::Anyfunc:
+        return nullptr;
+    default:
+        break;
+    }
+
+    auto emitRestoreCalleeSaves = [&] {
+        for (const RegisterAtOffset& regAtOffset : registersToSpill) {
+            GPRReg reg = regAtOffset.reg().gpr();
+            ASSERT(reg != GPRInfo::returnValueGPR);
+            ptrdiff_t offset = regAtOffset.offset();
+            jit.loadPtr(CCallHelpers::Address(GPRInfo::callFrameRegister, offset), reg);
+        }
+    };
+
+    emitRestoreCalleeSaves();
+
+    jit.emitFunctionEpilogue();
+    jit.ret();
+
+    slowPath.link(&jit);
+    emitRestoreCalleeSaves();
+    jit.move(CCallHelpers::TrustedImmPtr(this), GPRInfo::regT0);
+    jit.emitFunctionEpilogue();
+    auto jumpToHostCallThunk = jit.jump();
+
+    LinkBuffer linkBuffer(jit, nullptr, JITCompilationCanFail);
+    if (UNLIKELY(linkBuffer.didFailToAllocate()))
+        return nullptr;
+
+    linkBuffer.link(jumpToHostCallThunk, CodeLocationLabel<JSEntryPtrTag>(executable()->entrypointFor(CodeForCall, MustCheckArity).executableAddress()));
+    m_jsCallEntrypoint = FINALIZE_CODE(linkBuffer, WasmEntryPtrTag, "JS->Wasm IC");
+    return m_jsCallEntrypoint.code();
+}
+
 WebAssemblyFunction* 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)
 {
     NativeExecutable* executable = vm.getHostFunction(callWebAssemblyFunction, NoIntrinsic, callHostFunctionAsConstructor, nullptr, name);
 WebAssemblyFunction* 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)
 {
     NativeExecutable* executable = vm.getHostFunction(callWebAssemblyFunction, NoIntrinsic, callHostFunctionAsConstructor, nullptr, name);
@@ -169,6 +502,20 @@ WebAssemblyFunction::WebAssemblyFunction(VM& vm, JSGlobalObject* globalObject, S
     , m_importableFunction { signatureIndex, wasmToWasmEntrypointLoadLocation }
 { }
 
     , m_importableFunction { signatureIndex, wasmToWasmEntrypointLoadLocation }
 { }
 
+void WebAssemblyFunction::visitChildren(JSCell* cell, SlotVisitor& visitor)
+{
+    WebAssemblyFunction* thisObject = jsCast<WebAssemblyFunction*>(cell);
+    ASSERT_GC_OBJECT_INHERITS(thisObject, info());
+
+    Base::visitChildren(thisObject, visitor);
+    visitor.append(thisObject->m_jsToWasmICCallee);
+}
+
+void WebAssemblyFunction::destroy(JSCell* cell)
+{
+    static_cast<WebAssemblyFunction*>(cell)->WebAssemblyFunction::~WebAssemblyFunction();
+}
+
 } // namespace JSC
 
 #endif // ENABLE(WEBASSEMBLY)
 } // namespace JSC
 
 #endif // ENABLE(WEBASSEMBLY)
index 3f971f2..470d058 100644 (file)
@@ -27,6 +27,7 @@
 
 #if ENABLE(WEBASSEMBLY)
 
 
 #if ENABLE(WEBASSEMBLY)
 
+#include "JSToWasmICCallee.h"
 #include "MacroAssemblerCodeRef.h"
 #include "WasmCallee.h"
 #include "WebAssemblyFunctionBase.h"
 #include "MacroAssemblerCodeRef.h"
 #include "WasmCallee.h"
 #include "WebAssemblyFunctionBase.h"
@@ -49,6 +50,9 @@ public:
 
     const static unsigned StructureFlags = Base::StructureFlags;
 
 
     const static unsigned StructureFlags = Base::StructureFlags;
 
+    static const bool needsDestruction = true;
+    static void destroy(JSCell*);
+
     template<typename CellType, SubspaceAccess mode>
     static IsoSubspace* subspaceFor(VM& vm)
     {
     template<typename CellType, SubspaceAccess mode>
     static IsoSubspace* subspaceFor(VM& vm)
     {
@@ -74,14 +78,34 @@ public:
 
     static ptrdiff_t offsetOfEntrypointLoadLocation() { return OBJECT_OFFSETOF(WebAssemblyFunction, m_importableFunction) + WasmToWasmImportableFunction::offsetOfEntrypointLoadLocation(); }
 
 
     static ptrdiff_t offsetOfEntrypointLoadLocation() { return OBJECT_OFFSETOF(WebAssemblyFunction, m_importableFunction) + WasmToWasmImportableFunction::offsetOfEntrypointLoadLocation(); }
 
+    MacroAssemblerCodePtr<JSEntryPtrTag> jsCallEntrypoint()
+    {
+        if (m_jsCallEntrypoint)
+            return m_jsCallEntrypoint.code();
+        return jsCallEntrypointSlow();
+    }
+
+    RegisterAtOffsetList usedCalleeSaveRegisters() const;
+    Wasm::Instance* previousInstance(CallFrame*);
+
 private:
 private:
+    static void visitChildren(JSCell*, SlotVisitor&);
     WebAssemblyFunction(VM&, JSGlobalObject*, Structure*, Wasm::Callee& jsEntrypoint, WasmToWasmImportableFunction::LoadLocation entrypointLoadLocation, Wasm::SignatureIndex);
 
     WebAssemblyFunction(VM&, JSGlobalObject*, Structure*, Wasm::Callee& jsEntrypoint, WasmToWasmImportableFunction::LoadLocation entrypointLoadLocation, Wasm::SignatureIndex);
 
+    MacroAssemblerCodePtr<JSEntryPtrTag> jsCallEntrypointSlow();
+    ptrdiff_t previousInstanceOffset() const;
+    bool useTagRegisters() const;
+
+    RegisterSet calleeSaves() const;
+
     // It's safe to just hold the raw WasmToWasmImportableFunction/jsEntrypoint because we have a reference
     // to our Instance, which points to the Module that exported us, which
     // ensures that the actual Signature/code doesn't get deallocated.
     MacroAssemblerCodePtr<WasmEntryPtrTag> m_jsEntrypoint;
     WasmToWasmImportableFunction m_importableFunction;
     // It's safe to just hold the raw WasmToWasmImportableFunction/jsEntrypoint because we have a reference
     // to our Instance, which points to the Module that exported us, which
     // ensures that the actual Signature/code doesn't get deallocated.
     MacroAssemblerCodePtr<WasmEntryPtrTag> m_jsEntrypoint;
     WasmToWasmImportableFunction m_importableFunction;
+    WriteBarrier<JSToWasmICCallee> m_jsToWasmICCallee;
+    // Used for JS calling into Wasm.
+    MacroAssemblerCodeRef<JSEntryPtrTag> m_jsCallEntrypoint;
 };
 
 } // namespace JSC
 };
 
 } // namespace JSC
diff --git a/Source/JavaScriptCore/wasm/js/WebAssemblyFunctionHeapCellType.cpp b/Source/JavaScriptCore/wasm/js/WebAssemblyFunctionHeapCellType.cpp
new file mode 100644 (file)
index 0000000..37f914d
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2019 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#include "config.h"
+#include "WebAssemblyFunctionHeapCellType.h"
+
+#if ENABLE(WEBASSEMBLY)
+
+#include "JSCInlines.h"
+#include "MarkedBlockInlines.h"
+#include "WebAssemblyFunction.h"
+
+namespace JSC {
+
+struct WebAssemblyFunctionDestroyFunc {
+    ALWAYS_INLINE void operator()(VM&, JSCell* cell) const
+    {
+        static_assert(std::is_final<WebAssemblyFunction>::value, "Otherwise, this code would not be correct.");
+        WebAssemblyFunction::info()->methodTable.destroy(cell);
+    }
+};
+
+WebAssemblyFunctionHeapCellType::WebAssemblyFunctionHeapCellType()
+    : HeapCellType(CellAttributes(NeedsDestruction, HeapCell::JSCell))
+{
+}
+
+WebAssemblyFunctionHeapCellType::~WebAssemblyFunctionHeapCellType()
+{
+}
+
+void WebAssemblyFunctionHeapCellType::finishSweep(MarkedBlock::Handle& handle, FreeList* freeList)
+{
+    handle.finishSweepKnowingHeapCellType(freeList, WebAssemblyFunctionDestroyFunc());
+}
+
+void WebAssemblyFunctionHeapCellType::destroy(VM& vm, JSCell* cell)
+{
+    WebAssemblyFunctionDestroyFunc()(vm, cell);
+}
+
+} // namespace JSC
+
+#endif // ENABLE(WEBASSEMBLY)
diff --git a/Source/JavaScriptCore/wasm/js/WebAssemblyFunctionHeapCellType.h b/Source/JavaScriptCore/wasm/js/WebAssemblyFunctionHeapCellType.h
new file mode 100644 (file)
index 0000000..f7ebd9d
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2019 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#pragma once
+
+#if ENABLE(WEBASSEMBLY)
+
+#include "HeapCellType.h"
+
+namespace JSC {
+
+class WebAssemblyFunctionHeapCellType : public HeapCellType {
+public:
+    WebAssemblyFunctionHeapCellType();
+    virtual ~WebAssemblyFunctionHeapCellType();
+    
+    void finishSweep(MarkedBlock::Handle&, FreeList*) override;
+    void destroy(VM&, JSCell*) override;
+};
+
+} // namespace JSC
+
+#endif // ENABLE(WEBASSEMBLY)
index 5f7c56a..dc43898 100644 (file)
@@ -33,6 +33,8 @@
 
 namespace JSC {
 
 
 namespace JSC {
 
+class JSPromiseDeferred;
+
 class WebAssemblyPrototype final : public JSNonFinalObject {
 public:
     typedef JSNonFinalObject Base;
 class WebAssemblyPrototype final : public JSNonFinalObject {
 public:
     typedef JSNonFinalObject Base;