Title: [243886] trunk
Revision
243886
Author
[email protected]
Date
2019-04-04 11:54:16 -0700 (Thu, 04 Apr 2019)

Log Message

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

Reviewed by Filip Pizlo.

JSTests:

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

Source/_javascript_Core:

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.

* _javascript_Core.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:

Modified Paths

Added Paths

Diff

Modified: trunk/JSTests/ChangeLog (243885 => 243886)


--- trunk/JSTests/ChangeLog	2019-04-04 18:53:08 UTC (rev 243885)
+++ trunk/JSTests/ChangeLog	2019-04-04 18:54:16 UTC (rev 243886)
@@ -1,3 +1,12 @@
+2019-04-04  Saam barati  <[email protected]>
+
+        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  <[email protected]>
 
         [JSC] We should consider moving UnlinkedFunctionExecutable::m_parentScopeTDZVariables to RareData

Modified: trunk/JSTests/wasm/function-tests/stack-trace.js (243885 => 243886)


--- trunk/JSTests/wasm/function-tests/stack-trace.js	2019-04-04 18:53:08 UTC (rev 243885)
+++ trunk/JSTests/wasm/function-tests/stack-trace.js	2019-04-04 18:54:16 UTC (rev 243886)
@@ -43,11 +43,16 @@
     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;
 }

Modified: trunk/Source/_javascript_Core/CMakeLists.txt (243885 => 243886)


--- trunk/Source/_javascript_Core/CMakeLists.txt	2019-04-04 18:53:08 UTC (rev 243885)
+++ trunk/Source/_javascript_Core/CMakeLists.txt	2019-04-04 18:54:16 UTC (rev 243886)
@@ -100,8 +100,10 @@
     runtime/SymbolPrototype.cpp
 
     wasm/js/JSWebAssembly.cpp
+    wasm/js/JSToWasmICCallee.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

Modified: trunk/Source/_javascript_Core/ChangeLog (243885 => 243886)


--- trunk/Source/_javascript_Core/ChangeLog	2019-04-04 18:53:08 UTC (rev 243885)
+++ trunk/Source/_javascript_Core/ChangeLog	2019-04-04 18:54:16 UTC (rev 243886)
@@ -1,3 +1,114 @@
+2019-04-04  Saam barati  <[email protected]>
+
+        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.
+
+        * _javascript_Core.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  <[email protected]>
 
         [JSC] Pass CodeOrigin to FuzzerAgent

Modified: trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj (243885 => 243886)


--- trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj	2019-04-04 18:53:08 UTC (rev 243885)
+++ trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj	2019-04-04 18:54:16 UTC (rev 243886)
@@ -873,6 +873,7 @@
 		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, ); }; };
@@ -880,6 +881,7 @@
 		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, ); }; };
@@ -3377,6 +3379,8 @@
 		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>"; };
@@ -3389,6 +3393,8 @@
 		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>"; };
@@ -8268,6 +8274,8 @@
 			children = (
 				AD8DD6D01F6708A30004EB52 /* JSToWasm.cpp */,
 				AD8DD6CF1F67089F0004EB52 /* JSToWasm.h */,
+				527CE35222555FDD00C6F382 /* JSToWasmICCallee.cpp */,
+				527CE35322555FDD00C6F382 /* JSToWasmICCallee.h */,
 				ADD09AF21F624829001313C2 /* JSWebAssembly.cpp */,
 				ADD09AF31F62482E001313C2 /* JSWebAssembly.h */,
 				5383AA2F1E65E8A100A532FC /* JSWebAssemblyCodeBlock.cpp */,
@@ -8297,6 +8305,8 @@
 				AD2FCBB31DB58DA400B3E736 /* WebAssemblyCompileErrorPrototype.h */,
 				AD4937C91DDD27340077C807 /* WebAssemblyFunction.cpp */,
 				AD4937CA1DDD27340077C807 /* WebAssemblyFunction.h */,
+				523FD88D225566C4003B3DCC /* WebAssemblyFunctionHeapCellType.cpp */,
+				523FD88C225566C3003B3DCC /* WebAssemblyFunctionHeapCellType.h */,
 				521322431ECBCE8200F65615 /* WebAssemblyFunctionBase.cpp */,
 				521322441ECBCE8200F65615 /* WebAssemblyFunctionBase.h */,
 				AD2FCBB41DB58DA400B3E736 /* WebAssemblyInstanceConstructor.cpp */,
@@ -8614,6 +8624,7 @@
 				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 */,
@@ -8806,6 +8817,7 @@
 				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 */,

Modified: trunk/Source/_javascript_Core/Sources.txt (243885 => 243886)


--- trunk/Source/_javascript_Core/Sources.txt	2019-04-04 18:53:08 UTC (rev 243885)
+++ trunk/Source/_javascript_Core/Sources.txt	2019-04-04 18:54:16 UTC (rev 243886)
@@ -1014,6 +1014,7 @@
 
 wasm/js/JSToWasm.cpp
 wasm/js/JSToWasm.h
+wasm/js/JSToWasmICCallee.cpp
 wasm/js/JSWebAssembly.cpp
 wasm/js/JSWebAssemblyCodeBlock.cpp
 wasm/js/JSWebAssemblyCodeBlockHeapCellType.cpp
@@ -1030,6 +1031,7 @@
 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

Modified: trunk/Source/_javascript_Core/assembler/MacroAssemblerCodeRef.h (243885 => 243886)


--- trunk/Source/_javascript_Core/assembler/MacroAssemblerCodeRef.h	2019-04-04 18:53:08 UTC (rev 243885)
+++ trunk/Source/_javascript_Core/assembler/MacroAssemblerCodeRef.h	2019-04-04 18:54:16 UTC (rev 243886)
@@ -380,6 +380,14 @@
         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
@@ -443,9 +451,9 @@
 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;

Modified: trunk/Source/_javascript_Core/interpreter/Interpreter.cpp (243885 => 243886)


--- trunk/Source/_javascript_Core/interpreter/Interpreter.cpp	2019-04-04 18:53:08 UTC (rev 243885)
+++ trunk/Source/_javascript_Core/interpreter/Interpreter.cpp	2019-04-04 18:54:16 UTC (rev 243886)
@@ -549,6 +549,13 @@
             }
         }
 
+#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);
@@ -564,7 +571,7 @@
     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;

Modified: trunk/Source/_javascript_Core/interpreter/StackVisitor.cpp (243885 => 243886)


--- trunk/Source/_javascript_Core/interpreter/StackVisitor.cpp	2019-04-04 18:53:08 UTC (rev 243885)
+++ trunk/Source/_javascript_Core/interpreter/StackVisitor.cpp	2019-04-04 18:54:16 UTC (rev 243886)
@@ -33,6 +33,7 @@
 #include "JSCInlines.h"
 #include "WasmCallee.h"
 #include "WasmIndexOrName.h"
+#include "WebAssemblyFunction.h"
 #include <wtf/text/StringBuilder.h>
 
 namespace JSC {
@@ -252,10 +253,10 @@
     return CodeType::Global;
 }
 
-const RegisterAtOffsetList* StackVisitor::Frame::calleeSaveRegisters()
+Optional<RegisterAtOffsetList> StackVisitor::Frame::calleeSaveRegistersForUnwinding()
 {
     if (isInlinedFrame())
-        return nullptr;
+        return WTF::nullopt;
 
 #if !ENABLE(C_LOOP) && NUMBER_OF_CALLEE_SAVES_REGISTERS > 0
 
@@ -263,19 +264,24 @@
     if (isWasmFrame()) {
         if (callee().isCell()) {
             RELEASE_ASSERT(isWebAssemblyToJSCallee(callee().asCell()));
-            return nullptr;
+            return WTF::nullopt;
         }
         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())
-        return codeBlock->calleeSaveRegisters();
+        return *codeBlock->calleeSaveRegisters();
 
 #endif // !ENABLE(C_LOOP) && NUMBER_OF_CALLEE_SAVES_REGISTERS > 0
 
-    return nullptr;
+    return WTF::nullopt;
 }
 
 String StackVisitor::Frame::functionName() const

Modified: trunk/Source/_javascript_Core/interpreter/StackVisitor.h (243885 => 243886)


--- trunk/Source/_javascript_Core/interpreter/StackVisitor.h	2019-04-04 18:53:08 UTC (rev 243885)
+++ trunk/Source/_javascript_Core/interpreter/StackVisitor.h	2019-04-04 18:54:16 UTC (rev 243886)
@@ -94,7 +94,7 @@
         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; }

Modified: trunk/Source/_javascript_Core/jit/JITOperations.cpp (243885 => 243886)


--- trunk/Source/_javascript_Core/jit/JITOperations.cpp	2019-04-04 18:53:08 UTC (rev 243885)
+++ trunk/Source/_javascript_Core/jit/JITOperations.cpp	2019-04-04 18:54:16 UTC (rev 243886)
@@ -76,6 +76,7 @@
 #include "ThunkGenerators.h"
 #include "TypeProfilerLog.h"
 #include "VMInlines.h"
+#include "WebAssemblyFunction.h"
 #include <wtf/InlineASM.h>
 
 namespace JSC {
@@ -1036,9 +1037,11 @@
 
     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 = [&] () {
@@ -1064,6 +1067,7 @@
             arity = ArityCheckNotRequired;
         codePtr = functionExecutable->entrypointFor(kind, arity);
     }
+
     if (!callLinkInfo->seenOnce())
         callLinkInfo->setSeen();
     else

Modified: trunk/Source/_javascript_Core/jit/RegisterSet.cpp (243885 => 243886)


--- trunk/Source/_javascript_Core/jit/RegisterSet.cpp	2019-04-04 18:53:08 UTC (rev 243885)
+++ trunk/Source/_javascript_Core/jit/RegisterSet.cpp	2019-04-04 18:54:16 UTC (rev 243886)
@@ -58,7 +58,7 @@
 #endif
 }
 
-RegisterSet RegisterSet::runtimeRegisters()
+RegisterSet RegisterSet::runtimeTagRegisters()
 {
 #if USE(JSVALUE64)
     return RegisterSet(GPRInfo::tagTypeNumberRegister, GPRInfo::tagMaskRegister);
@@ -70,7 +70,7 @@
 RegisterSet RegisterSet::specialRegisters()
 {
     return RegisterSet(
-        stackRegisters(), reservedHardwareRegisters(), runtimeRegisters());
+        stackRegisters(), reservedHardwareRegisters(), runtimeTagRegisters());
 }
 
 RegisterSet RegisterSet::volatileRegistersForJSCall()

Modified: trunk/Source/_javascript_Core/jit/RegisterSet.h (243885 => 243886)


--- trunk/Source/_javascript_Core/jit/RegisterSet.h	2019-04-04 18:53:08 UTC (rev 243885)
+++ trunk/Source/_javascript_Core/jit/RegisterSet.h	2019-04-04 18:54:16 UTC (rev 243886)
@@ -50,7 +50,7 @@
     
     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.

Modified: trunk/Source/_javascript_Core/jit/Repatch.cpp (243885 => 243886)


--- trunk/Source/_javascript_Core/jit/Repatch.cpp	2019-04-04 18:53:08 UTC (rev 243885)
+++ trunk/Source/_javascript_Core/jit/Repatch.cpp	2019-04-04 18:54:16 UTC (rev 243886)
@@ -975,7 +975,7 @@
     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);
 
@@ -1137,7 +1137,10 @@
         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);
@@ -1277,6 +1280,23 @@
     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

Modified: trunk/Source/_javascript_Core/jit/Repatch.h (243885 => 243886)


--- trunk/Source/_javascript_Core/jit/Repatch.h	2019-04-04 18:53:08 UTC (rev 243885)
+++ trunk/Source/_javascript_Core/jit/Repatch.h	2019-04-04 18:54:16 UTC (rev 243886)
@@ -57,7 +57,9 @@
 void resetInByID(CodeBlock*, StructureStubInfo&);
 void resetInstanceOf(StructureStubInfo&);
 void ftlThunkAwareRepatchCall(CodeBlock*, CodeLocationCall<JSInternalPtrTag>, FunctionPtr<CFunctionPtrTag> newCalleeFunction);
+MacroAssemblerCodePtr<JSEntryPtrTag> jsToWasmICCodePtr(VM&, CodeSpecializationKind, JSObject* callee);
 
+
 } // namespace JSC
 
 #endif // ENABLE(JIT)

Modified: trunk/Source/_javascript_Core/runtime/JSFunction.cpp (243885 => 243886)


--- trunk/Source/_javascript_Core/runtime/JSFunction.cpp	2019-04-04 18:53:08 UTC (rev 243885)
+++ trunk/Source/_javascript_Core/runtime/JSFunction.cpp	2019-04-04 18:54:16 UTC (rev 243886)
@@ -48,6 +48,7 @@
 #include "Parser.h"
 #include "PropertyNameArray.h"
 #include "StackVisitor.h"
+#include "WebAssemblyFunction.h"
 
 namespace JSC {
 
@@ -627,10 +628,14 @@
 
 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();
 
-
     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.

Modified: trunk/Source/_javascript_Core/runtime/JSGlobalObject.cpp (243885 => 243886)


--- trunk/Source/_javascript_Core/runtime/JSGlobalObject.cpp	2019-04-04 18:53:08 UTC (rev 243885)
+++ trunk/Source/_javascript_Core/runtime/JSGlobalObject.cpp	2019-04-04 18:54:16 UTC (rev 243886)
@@ -1053,6 +1053,10 @@
             [] (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()));
@@ -1751,6 +1755,7 @@
 #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)

Modified: trunk/Source/_javascript_Core/runtime/JSGlobalObject.h (243885 => 243886)


--- trunk/Source/_javascript_Core/runtime/JSGlobalObject.h	2019-04-04 18:53:08 UTC (rev 243885)
+++ trunk/Source/_javascript_Core/runtime/JSGlobalObject.h	2019-04-04 18:54:16 UTC (rev 243886)
@@ -400,6 +400,7 @@
 #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)
@@ -764,6 +765,7 @@
 #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)

Modified: trunk/Source/_javascript_Core/runtime/VM.cpp (243885 => 243886)


--- trunk/Source/_javascript_Core/runtime/VM.cpp	2019-04-04 18:53:08 UTC (rev 243885)
+++ trunk/Source/_javascript_Core/runtime/VM.cpp	2019-04-04 18:54:16 UTC (rev 243886)
@@ -148,6 +148,7 @@
 #include "Watchdog.h"
 #include "WeakGCMapInlines.h"
 #include "WebAssemblyFunction.h"
+#include "WebAssemblyFunctionHeapCellType.h"
 #include "WebAssemblyWrapperFunction.h"
 #include <wtf/ProcessID.h>
 #include <wtf/ReadWriteLock.h>
@@ -280,6 +281,7 @@
     , 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())
@@ -1264,7 +1266,7 @@
 #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
 

Modified: trunk/Source/_javascript_Core/runtime/VM.h (243885 => 243886)


--- trunk/Source/_javascript_Core/runtime/VM.h	2019-04-04 18:53:08 UTC (rev 243885)
+++ trunk/Source/_javascript_Core/runtime/VM.h	2019-04-04 18:54:16 UTC (rev 243886)
@@ -158,6 +158,7 @@
 class Watchdog;
 class Watchpoint;
 class WatchpointSet;
+class WebAssemblyFunctionHeapCellType;
 
 #if ENABLE(FTL_JIT)
 namespace FTL {
@@ -337,6 +338,7 @@
     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.

Modified: trunk/Source/_javascript_Core/wasm/WasmAirIRGenerator.cpp (243885 => 243886)


--- trunk/Source/_javascript_Core/wasm/WasmAirIRGenerator.cpp	2019-04-04 18:53:08 UTC (rev 243885)
+++ trunk/Source/_javascript_Core/wasm/WasmAirIRGenerator.cpp	2019-04-04 18:54:16 UTC (rev 243886)
@@ -680,10 +680,8 @@
         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)
@@ -823,8 +821,7 @@
         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();
@@ -834,14 +831,8 @@
         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);
@@ -1855,19 +1846,15 @@
             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);
-            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
-            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*.
         });
 

Modified: trunk/Source/_javascript_Core/wasm/WasmB3IRGenerator.cpp (243885 => 243886)


--- trunk/Source/_javascript_Core/wasm/WasmB3IRGenerator.cpp	2019-04-04 18:53:08 UTC (rev 243885)
+++ trunk/Source/_javascript_Core/wasm/WasmB3IRGenerator.cpp	2019-04-04 18:54:16 UTC (rev 243886)
@@ -346,10 +346,8 @@
         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)
@@ -469,8 +467,7 @@
         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();
@@ -483,13 +480,8 @@
 
         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);
-            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 @@
             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);
-            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
-            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);

Modified: trunk/Source/_javascript_Core/wasm/WasmBinding.cpp (243885 => 243886)


--- trunk/Source/_javascript_Core/wasm/WasmBinding.cpp	2019-04-04 18:53:08 UTC (rev 243885)
+++ trunk/Source/_javascript_Core/wasm/WasmBinding.cpp	2019-04-04 18:54:16 UTC (rev 243886)
@@ -48,11 +48,9 @@
     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*
@@ -67,14 +65,8 @@
 
     // 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*.
-    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);

Modified: trunk/Source/_javascript_Core/wasm/WasmContext.h (243885 => 243886)


--- trunk/Source/_javascript_Core/wasm/WasmContext.h	2019-04-04 18:53:08 UTC (rev 243885)
+++ trunk/Source/_javascript_Core/wasm/WasmContext.h	2019-04-04 18:54:16 UTC (rev 243886)
@@ -32,12 +32,19 @@
 class Instance;
 
 struct Context {
-    Instance* instance { nullptr };
-
     Instance* load() const;
     void store(Instance*, void* softStackLimit);
 
     static bool useFastTLS();
+
+    Instance** pointerToInstance()
+    {
+        ASSERT(!useFastTLS());
+        return &instance;
+    }
+
+private:
+    Instance* instance { nullptr };
 };
 
 } } // namespace JSC::Wasm

Modified: trunk/Source/_javascript_Core/wasm/WasmContextInlines.h (243885 => 243886)


--- trunk/Source/_javascript_Core/wasm/WasmContextInlines.h	2019-04-04 18:53:08 UTC (rev 243885)
+++ trunk/Source/_javascript_Core/wasm/WasmContextInlines.h	2019-04-04 18:54:16 UTC (rev 243886)
@@ -55,13 +55,15 @@
 
 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));
+    else
 #endif
-    instance = inst;
-    if (instance)
-        instance->setCachedStackLimit(softStackLimit);
+        instance = inst;
 }
 
 } } // namespace JSC::Wasm

Modified: trunk/Source/_javascript_Core/wasm/WasmMemoryInformation.cpp (243885 => 243886)


--- trunk/Source/_javascript_Core/wasm/WasmMemoryInformation.cpp	2019-04-04 18:53:08 UTC (rev 243885)
+++ trunk/Source/_javascript_Core/wasm/WasmMemoryInformation.cpp	2019-04-04 18:54:16 UTC (rev 243886)
@@ -44,6 +44,11 @@
         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);
     });
@@ -55,35 +60,25 @@
     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);
 
-        baseMemoryPointer = pinnedRegs.takeLast();
+        GPRReg baseMemoryPointer = pinnedRegs.takeLast();
+        GPRReg sizeRegister = pinnedRegs.takeLast();
+        GPRReg wasmContextInstancePointer = InvalidGPRReg;
         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();
 }
 
-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)
 {

Modified: trunk/Source/_javascript_Core/wasm/WasmMemoryInformation.h (243885 => 243886)


--- trunk/Source/_javascript_Core/wasm/WasmMemoryInformation.h	2019-04-04 18:53:08 UTC (rev 243885)
+++ trunk/Source/_javascript_Core/wasm/WasmMemoryInformation.h	2019-04-04 18:54:16 UTC (rev 243886)
@@ -45,7 +45,7 @@
 
 class PinnedRegisterInfo {
 public:
-    PinnedRegisterInfo(Vector<PinnedSizeRegisterInfo>&&, GPRReg, GPRReg);
+    PinnedRegisterInfo(GPRReg, GPRReg, GPRReg);
 
     static const PinnedRegisterInfo& get();
 
@@ -55,14 +55,12 @@
         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;
     }
 
-    Vector<PinnedSizeRegisterInfo> sizeRegisters;
+    GPRReg sizeRegister;
     GPRReg baseMemoryPointer;
     GPRReg wasmContextInstancePointer;
 };

Modified: trunk/Source/_javascript_Core/wasm/WasmOMGPlan.cpp (243885 => 243886)


--- trunk/Source/_javascript_Core/wasm/WasmOMGPlan.cpp	2019-04-04 18:53:08 UTC (rev 243885)
+++ trunk/Source/_javascript_Core/wasm/WasmOMGPlan.cpp	2019-04-04 18:54:16 UTC (rev 243886)
@@ -138,7 +138,7 @@
     {
         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) {

Modified: trunk/Source/_javascript_Core/wasm/js/JSToWasm.cpp (243885 => 243886)


--- trunk/Source/_javascript_Core/wasm/js/JSToWasm.cpp	2019-04-04 18:53:08 UTC (rev 243885)
+++ trunk/Source/_javascript_Core/wasm/js/JSToWasm.cpp	2019-04-04 18:54:16 UTC (rev 243886)
@@ -213,14 +213,8 @@
             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);
     }

Copied: trunk/Source/_javascript_Core/wasm/js/JSToWasmICCallee.cpp (from rev 243885, trunk/Source/_javascript_Core/wasm/js/WebAssemblyPrototype.h) (0 => 243886)


--- trunk/Source/_javascript_Core/wasm/js/JSToWasmICCallee.cpp	                        (rev 0)
+++ trunk/Source/_javascript_Core/wasm/js/JSToWasmICCallee.cpp	2019-04-04 18:54:16 UTC (rev 243886)
@@ -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)

Copied: trunk/Source/_javascript_Core/wasm/js/JSToWasmICCallee.h (from rev 243885, trunk/Source/_javascript_Core/wasm/WasmContext.h) (0 => 243886)


--- trunk/Source/_javascript_Core/wasm/js/JSToWasmICCallee.h	                        (rev 0)
+++ trunk/Source/_javascript_Core/wasm/js/JSToWasmICCallee.h	2019-04-04 18:54:16 UTC (rev 243886)
@@ -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

Modified: trunk/Source/_javascript_Core/wasm/js/WebAssemblyFunction.cpp (243885 => 243886)


--- trunk/Source/_javascript_Core/wasm/js/WebAssemblyFunction.cpp	2019-04-04 18:53:08 UTC (rev 243885)
+++ trunk/Source/_javascript_Core/wasm/js/WebAssemblyFunction.cpp	2019-04-04 18:54:16 UTC (rev 243886)
@@ -36,12 +36,16 @@
 #include "JSWebAssemblyMemory.h"
 #include "JSWebAssemblyRuntimeError.h"
 #include "LLIntThunks.h"
+#include "LinkBuffer.h"
 #include "ProtoCallFrame.h"
 #include "VM.h"
 #include "WasmCallee.h"
+#include "WasmCallingConvention.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>
@@ -148,6 +152,335 @@
     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);
@@ -169,6 +502,20 @@
     , 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)

Modified: trunk/Source/_javascript_Core/wasm/js/WebAssemblyFunction.h (243885 => 243886)


--- trunk/Source/_javascript_Core/wasm/js/WebAssemblyFunction.h	2019-04-04 18:53:08 UTC (rev 243885)
+++ trunk/Source/_javascript_Core/wasm/js/WebAssemblyFunction.h	2019-04-04 18:54:16 UTC (rev 243886)
@@ -27,6 +27,7 @@
 
 #if ENABLE(WEBASSEMBLY)
 
+#include "JSToWasmICCallee.h"
 #include "MacroAssemblerCodeRef.h"
 #include "WasmCallee.h"
 #include "WebAssemblyFunctionBase.h"
@@ -49,6 +50,9 @@
 
     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)
     {
@@ -74,14 +78,34 @@
 
     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:
+    static void visitChildren(JSCell*, SlotVisitor&);
     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;
+    WriteBarrier<JSToWasmICCallee> m_jsToWasmICCallee;
+    // Used for JS calling into Wasm.
+    MacroAssemblerCodeRef<JSEntryPtrTag> m_jsCallEntrypoint;
 };
 
 } // namespace JSC

Copied: trunk/Source/_javascript_Core/wasm/js/WebAssemblyFunctionHeapCellType.cpp (from rev 243885, trunk/Source/_javascript_Core/wasm/WasmContextInlines.h) (0 => 243886)


--- trunk/Source/_javascript_Core/wasm/js/WebAssemblyFunctionHeapCellType.cpp	                        (rev 0)
+++ trunk/Source/_javascript_Core/wasm/js/WebAssemblyFunctionHeapCellType.cpp	2019-04-04 18:54:16 UTC (rev 243886)
@@ -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)

Copied: trunk/Source/_javascript_Core/wasm/js/WebAssemblyFunctionHeapCellType.h (from rev 243885, trunk/Source/_javascript_Core/wasm/WasmContext.h) (0 => 243886)


--- trunk/Source/_javascript_Core/wasm/js/WebAssemblyFunctionHeapCellType.h	                        (rev 0)
+++ trunk/Source/_javascript_Core/wasm/js/WebAssemblyFunctionHeapCellType.h	2019-04-04 18:54:16 UTC (rev 243886)
@@ -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)

Modified: trunk/Source/_javascript_Core/wasm/js/WebAssemblyPrototype.h (243885 => 243886)


--- trunk/Source/_javascript_Core/wasm/js/WebAssemblyPrototype.h	2019-04-04 18:53:08 UTC (rev 243885)
+++ trunk/Source/_javascript_Core/wasm/js/WebAssemblyPrototype.h	2019-04-04 18:54:16 UTC (rev 243886)
@@ -33,6 +33,8 @@
 
 namespace JSC {
 
+class JSPromiseDeferred;
+
 class WebAssemblyPrototype final : public JSNonFinalObject {
 public:
     typedef JSNonFinalObject Base;
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to