WebAssembly JS API: wire up Instance imports
authorjfbastien@apple.com <jfbastien@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 8 Dec 2016 21:09:06 +0000 (21:09 +0000)
committerjfbastien@apple.com <jfbastien@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 8 Dec 2016 21:09:06 +0000 (21:09 +0000)
https://bugs.webkit.org/show_bug.cgi?id=165118

Reviewed by Saam Barati.

JSTests:

* wasm/js-api/test_Instance.js: add the test, disabled for now

Source/JavaScriptCore:

Change a bunch of the WebAssembly object model, and pipe the
necessary changes to be able to call JS imports from
WebAssembly. This will make it easier to call_indirect, and
unblock many other missing features.

As a follow-up I need to teach JSC::linkFor to live without a
CodeBlock: wasm doesn't have one and the IC patching is sad. We'll
switch on the callee (or its type?) and then use that as the owner
(because the callee is alive if the instance is alive, ditto
module, and module owns the CallLinkInfo).

* CMakeLists.txt:
* JavaScriptCore.xcodeproj/project.pbxproj:
* interpreter/CallFrame.h:
(JSC::ExecState::callee): give access to the callee as a JSCell
* jit/RegisterSet.cpp: dead code from previous WebAssembly implementation
* jsc.cpp:
(callWasmFunction):
(functionTestWasmModuleFunctions):
* runtime/JSCellInlines.h:
(JSC::ExecState::vm): check callee instead of jsCallee: wasm only has a JSCell and not a JSObject
* runtime/VM.cpp:
(JSC::VM::VM): store the "top" WebAssembly.Instance on entry to WebAssembly (and restore the previous one on exit)
* runtime/VM.h:
* testWasm.cpp:
(runWasmTests):
* wasm/JSWebAssembly.h:
* wasm/WasmB3IRGenerator.cpp:
(JSC::Wasm::B3IRGenerator::B3IRGenerator): pass unlinked calls around to shorten their lifetime: they're ony needed until the Plan is done
(JSC::Wasm::B3IRGenerator::addCall):
(JSC::Wasm::createJSToWasmWrapper):
(JSC::Wasm::parseAndCompile): also pass in the function index space, so that imports can be signature-checked along with internal functions
* wasm/WasmB3IRGenerator.h:
* wasm/WasmBinding.cpp: Added.
(JSC::Wasm::importStubGenerator): stubs from wasm to JS
* wasm/WasmBinding.h: Copied from Source/JavaScriptCore/wasm/WasmValidate.h.
* wasm/WasmCallingConvention.h:
(JSC::Wasm::CallingConvention::setupFrameInPrologue):
* wasm/WasmFormat.h: fix the object model
(JSC::Wasm::CallableFunction::CallableFunction):
* wasm/WasmFunctionParser.h: simplify some of the failure condition checks
(JSC::Wasm::FunctionParser<Context>::FunctionParser): need function index space, not just internal functions
(JSC::Wasm::FunctionParser<Context>::parseExpression):
* wasm/WasmModuleParser.cpp: early-create some of the structures which will be needed later
(JSC::Wasm::ModuleParser::parseImport):
(JSC::Wasm::ModuleParser::parseFunction):
(JSC::Wasm::ModuleParser::parseMemory):
(JSC::Wasm::ModuleParser::parseExport):
(JSC::Wasm::ModuleParser::parseCode):
* wasm/WasmModuleParser.h:
(JSC::Wasm::ModuleParser::functionIndexSpace):
(JSC::Wasm::ModuleParser::functionLocations):
* wasm/WasmParser.h:
(JSC::Wasm::Parser::consumeUTF8String):
* wasm/WasmPlan.cpp: pass around the wasm objects at the right time, reducing their lifetime and making it easier to pass them around when needed
(JSC::Wasm::Plan::run):
(JSC::Wasm::Plan::initializeCallees):
* wasm/WasmPlan.h:
(JSC::Wasm::Plan::exports):
(JSC::Wasm::Plan::internalFunctionCount):
(JSC::Wasm::Plan::jsToWasmEntryPointForFunction):
(JSC::Wasm::Plan::takeModuleInformation):
(JSC::Wasm::Plan::takeCallLinkInfos):
(JSC::Wasm::Plan::takeWasmToJSStubs):
(JSC::Wasm::Plan::takeFunctionIndexSpace):
* wasm/WasmValidate.cpp: check function index space instead of only internal functions
(JSC::Wasm::Validate::addCall):
(JSC::Wasm::validateFunction):
* wasm/WasmValidate.h:
* wasm/js/JSWebAssemblyCallee.cpp:
(JSC::JSWebAssemblyCallee::finishCreation):
* wasm/js/JSWebAssemblyCallee.h:
(JSC::JSWebAssemblyCallee::create):
(JSC::JSWebAssemblyCallee::jsToWasmEntryPoint):
* wasm/js/JSWebAssemblyInstance.cpp:
(JSC::JSWebAssemblyInstance::create):
(JSC::JSWebAssemblyInstance::JSWebAssemblyInstance):
(JSC::JSWebAssemblyInstance::visitChildren):
* wasm/js/JSWebAssemblyInstance.h: hold the import functions off the end of the Instance
(JSC::JSWebAssemblyInstance::importFunction):
(JSC::JSWebAssemblyInstance::importFunctions):
(JSC::JSWebAssemblyInstance::setImportFunction):
(JSC::JSWebAssemblyInstance::offsetOfImportFunctions):
(JSC::JSWebAssemblyInstance::offsetOfImportFunction):
(JSC::JSWebAssemblyInstance::allocationSize):
* wasm/js/JSWebAssemblyModule.cpp:
(JSC::JSWebAssemblyModule::create):
(JSC::JSWebAssemblyModule::JSWebAssemblyModule):
(JSC::JSWebAssemblyModule::visitChildren):
* wasm/js/JSWebAssemblyModule.h: hold the link call info, the import function stubs, and the function index space
(JSC::JSWebAssemblyModule::signatureForFunctionIndexSpace):
(JSC::JSWebAssemblyModule::importCount):
(JSC::JSWebAssemblyModule::calleeFromFunctionIndexSpace):
* wasm/js/WebAssemblyFunction.cpp:
(JSC::callWebAssemblyFunction): set top Instance on VM
* wasm/js/WebAssemblyFunction.h:
(JSC::WebAssemblyFunction::instance):
* wasm/js/WebAssemblyInstanceConstructor.cpp:
(JSC::constructJSWebAssemblyInstance): handle function imports
* wasm/js/WebAssemblyModuleConstructor.cpp:
(JSC::constructJSWebAssemblyModule): generate the stubs for import functions
* wasm/js/WebAssemblyModuleRecord.cpp:
(JSC::WebAssemblyModuleRecord::link):
* wasm/js/WebAssemblyToJSCallee.cpp: Copied from Source/JavaScriptCore/wasm/js/JSWebAssemblyCallee.cpp.
(JSC::WebAssemblyToJSCallee::create): dummy JSCell singleton which lives on the VM, and is put as the callee in the import stub's frame to identified it when unwinding
(JSC::WebAssemblyToJSCallee::createStructure):
(JSC::WebAssemblyToJSCallee::WebAssemblyToJSCallee):
(JSC::WebAssemblyToJSCallee::finishCreation):
(JSC::WebAssemblyToJSCallee::destroy):
* wasm/js/WebAssemblyToJSCallee.h: Copied from Source/JavaScriptCore/wasm/WasmB3IRGenerator.h.

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

40 files changed:
JSTests/ChangeLog
JSTests/wasm/js-api/test_Instance.js
Source/JavaScriptCore/CMakeLists.txt
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
Source/JavaScriptCore/interpreter/CallFrame.h
Source/JavaScriptCore/jit/RegisterSet.cpp
Source/JavaScriptCore/jsc.cpp
Source/JavaScriptCore/runtime/JSCellInlines.h
Source/JavaScriptCore/runtime/VM.cpp
Source/JavaScriptCore/runtime/VM.h
Source/JavaScriptCore/testWasm.cpp
Source/JavaScriptCore/wasm/JSWebAssembly.h
Source/JavaScriptCore/wasm/WasmB3IRGenerator.cpp
Source/JavaScriptCore/wasm/WasmB3IRGenerator.h
Source/JavaScriptCore/wasm/WasmBinding.cpp [new file with mode: 0644]
Source/JavaScriptCore/wasm/WasmBinding.h [new file with mode: 0644]
Source/JavaScriptCore/wasm/WasmCallingConvention.h
Source/JavaScriptCore/wasm/WasmFormat.h
Source/JavaScriptCore/wasm/WasmFunctionParser.h
Source/JavaScriptCore/wasm/WasmModuleParser.cpp
Source/JavaScriptCore/wasm/WasmModuleParser.h
Source/JavaScriptCore/wasm/WasmParser.h
Source/JavaScriptCore/wasm/WasmPlan.cpp
Source/JavaScriptCore/wasm/WasmPlan.h
Source/JavaScriptCore/wasm/WasmValidate.cpp
Source/JavaScriptCore/wasm/WasmValidate.h
Source/JavaScriptCore/wasm/js/JSWebAssemblyCallee.cpp
Source/JavaScriptCore/wasm/js/JSWebAssemblyCallee.h
Source/JavaScriptCore/wasm/js/JSWebAssemblyInstance.cpp
Source/JavaScriptCore/wasm/js/JSWebAssemblyInstance.h
Source/JavaScriptCore/wasm/js/JSWebAssemblyModule.cpp
Source/JavaScriptCore/wasm/js/JSWebAssemblyModule.h
Source/JavaScriptCore/wasm/js/WebAssemblyFunction.cpp
Source/JavaScriptCore/wasm/js/WebAssemblyFunction.h
Source/JavaScriptCore/wasm/js/WebAssemblyInstanceConstructor.cpp
Source/JavaScriptCore/wasm/js/WebAssemblyModuleConstructor.cpp
Source/JavaScriptCore/wasm/js/WebAssemblyModuleRecord.cpp
Source/JavaScriptCore/wasm/js/WebAssemblyToJSCallee.cpp [new file with mode: 0644]
Source/JavaScriptCore/wasm/js/WebAssemblyToJSCallee.h [new file with mode: 0644]

index 83922ef..e21c2fb 100644 (file)
@@ -1,3 +1,12 @@
+2016-12-08  JF Bastien  <jfbastien@apple.com>
+
+        WebAssembly JS API: wire up Instance imports
+        https://bugs.webkit.org/show_bug.cgi?id=165118
+
+        Reviewed by Saam Barati.
+
+        * wasm/js-api/test_Instance.js: add the test, disabled for now
+
 2016-12-07  Keith Miller  <keith_miller@apple.com>
 
         Add more missing trivial wasm ops.
index 89f2056..005097b 100644 (file)
@@ -29,3 +29,36 @@ import Builder from '../Builder.js';
     assert.isA(result, "number");
     assert.eq(result, 42);
 })();
+
+/* FIXME this currently crashes as detailed in https://bugs.webkit.org/show_bug.cgi?id=165591
+(function Import() {
+    let counter = 0;
+    const counterSetter = v => counter = v;
+    const builder = (new Builder())
+        .Type().End()
+        .Import()
+            .Function("imp", "func", { params: ["i32"] })
+        .End()
+        .Function().End()
+        .Export()
+            .Function("changeCounter")
+        .End()
+        .Code()
+            .Function("changeCounter", { params: ["i32"] })
+                .I32Const(42)
+                .GetLocal(0)
+                .I32Add()
+                .Call(0) // Calls func(param[0] + 42).
+            .End()
+        .End();
+    const bin = builder.WebAssembly().get();
+    const module = new WebAssembly.Module(bin);
+    const instance = new WebAssembly.Instance(module, { imp: { func: counterSetter } });
+    instance.exports.changeCounter(0);
+    assert.eq(counter, 42);
+    instance.exports.changeCounter(1);
+    assert.eq(counter, 43);
+    instance.exports.changeCounter(42);
+    assert.eq(counter, 84);
+})();
+*/
index 66ad563..fc6abd3 100644 (file)
@@ -896,6 +896,7 @@ set(JavaScriptCore_SOURCES
 
     wasm/JSWebAssembly.cpp
     wasm/WasmB3IRGenerator.cpp
+    wasm/WasmBinding.cpp
     wasm/WasmCallingConvention.cpp
     wasm/WasmFormat.cpp
     wasm/WasmMemory.cpp
@@ -925,6 +926,7 @@ set(JavaScriptCore_SOURCES
     wasm/js/WebAssemblyRuntimeErrorPrototype.cpp
     wasm/js/WebAssemblyTableConstructor.cpp
     wasm/js/WebAssemblyTablePrototype.cpp
+    wasm/js/WebAssemblyToJSCallee.cpp
 
     yarr/RegularExpression.cpp
     yarr/YarrCanonicalizeUCS2.cpp
index 805a541..5297986 100644 (file)
@@ -1,3 +1,121 @@
+2016-12-08  JF Bastien  <jfbastien@apple.com>
+
+        WebAssembly JS API: wire up Instance imports
+        https://bugs.webkit.org/show_bug.cgi?id=165118
+
+        Reviewed by Saam Barati.
+
+        Change a bunch of the WebAssembly object model, and pipe the
+        necessary changes to be able to call JS imports from
+        WebAssembly. This will make it easier to call_indirect, and
+        unblock many other missing features.
+
+        As a follow-up I need to teach JSC::linkFor to live without a
+        CodeBlock: wasm doesn't have one and the IC patching is sad. We'll
+        switch on the callee (or its type?) and then use that as the owner
+        (because the callee is alive if the instance is alive, ditto
+        module, and module owns the CallLinkInfo).
+
+        * CMakeLists.txt:
+        * JavaScriptCore.xcodeproj/project.pbxproj:
+        * interpreter/CallFrame.h:
+        (JSC::ExecState::callee): give access to the callee as a JSCell
+        * jit/RegisterSet.cpp: dead code from previous WebAssembly implementation
+        * jsc.cpp:
+        (callWasmFunction):
+        (functionTestWasmModuleFunctions):
+        * runtime/JSCellInlines.h:
+        (JSC::ExecState::vm): check callee instead of jsCallee: wasm only has a JSCell and not a JSObject
+        * runtime/VM.cpp:
+        (JSC::VM::VM): store the "top" WebAssembly.Instance on entry to WebAssembly (and restore the previous one on exit)
+        * runtime/VM.h:
+        * testWasm.cpp:
+        (runWasmTests):
+        * wasm/JSWebAssembly.h:
+        * wasm/WasmB3IRGenerator.cpp:
+        (JSC::Wasm::B3IRGenerator::B3IRGenerator): pass unlinked calls around to shorten their lifetime: they're ony needed until the Plan is done
+        (JSC::Wasm::B3IRGenerator::addCall):
+        (JSC::Wasm::createJSToWasmWrapper):
+        (JSC::Wasm::parseAndCompile): also pass in the function index space, so that imports can be signature-checked along with internal functions
+        * wasm/WasmB3IRGenerator.h:
+        * wasm/WasmBinding.cpp: Added.
+        (JSC::Wasm::importStubGenerator): stubs from wasm to JS
+        * wasm/WasmBinding.h: Copied from Source/JavaScriptCore/wasm/WasmValidate.h.
+        * wasm/WasmCallingConvention.h:
+        (JSC::Wasm::CallingConvention::setupFrameInPrologue):
+        * wasm/WasmFormat.h: fix the object model
+        (JSC::Wasm::CallableFunction::CallableFunction):
+        * wasm/WasmFunctionParser.h: simplify some of the failure condition checks
+        (JSC::Wasm::FunctionParser<Context>::FunctionParser): need function index space, not just internal functions
+        (JSC::Wasm::FunctionParser<Context>::parseExpression):
+        * wasm/WasmModuleParser.cpp: early-create some of the structures which will be needed later
+        (JSC::Wasm::ModuleParser::parseImport):
+        (JSC::Wasm::ModuleParser::parseFunction):
+        (JSC::Wasm::ModuleParser::parseMemory):
+        (JSC::Wasm::ModuleParser::parseExport):
+        (JSC::Wasm::ModuleParser::parseCode):
+        * wasm/WasmModuleParser.h:
+        (JSC::Wasm::ModuleParser::functionIndexSpace):
+        (JSC::Wasm::ModuleParser::functionLocations):
+        * wasm/WasmParser.h:
+        (JSC::Wasm::Parser::consumeUTF8String):
+        * wasm/WasmPlan.cpp: pass around the wasm objects at the right time, reducing their lifetime and making it easier to pass them around when needed
+        (JSC::Wasm::Plan::run):
+        (JSC::Wasm::Plan::initializeCallees):
+        * wasm/WasmPlan.h:
+        (JSC::Wasm::Plan::exports):
+        (JSC::Wasm::Plan::internalFunctionCount):
+        (JSC::Wasm::Plan::jsToWasmEntryPointForFunction):
+        (JSC::Wasm::Plan::takeModuleInformation):
+        (JSC::Wasm::Plan::takeCallLinkInfos):
+        (JSC::Wasm::Plan::takeWasmToJSStubs):
+        (JSC::Wasm::Plan::takeFunctionIndexSpace):
+        * wasm/WasmValidate.cpp: check function index space instead of only internal functions
+        (JSC::Wasm::Validate::addCall):
+        (JSC::Wasm::validateFunction):
+        * wasm/WasmValidate.h:
+        * wasm/js/JSWebAssemblyCallee.cpp:
+        (JSC::JSWebAssemblyCallee::finishCreation):
+        * wasm/js/JSWebAssemblyCallee.h:
+        (JSC::JSWebAssemblyCallee::create):
+        (JSC::JSWebAssemblyCallee::jsToWasmEntryPoint):
+        * wasm/js/JSWebAssemblyInstance.cpp:
+        (JSC::JSWebAssemblyInstance::create):
+        (JSC::JSWebAssemblyInstance::JSWebAssemblyInstance):
+        (JSC::JSWebAssemblyInstance::visitChildren):
+        * wasm/js/JSWebAssemblyInstance.h: hold the import functions off the end of the Instance
+        (JSC::JSWebAssemblyInstance::importFunction):
+        (JSC::JSWebAssemblyInstance::importFunctions):
+        (JSC::JSWebAssemblyInstance::setImportFunction):
+        (JSC::JSWebAssemblyInstance::offsetOfImportFunctions):
+        (JSC::JSWebAssemblyInstance::offsetOfImportFunction):
+        (JSC::JSWebAssemblyInstance::allocationSize):
+        * wasm/js/JSWebAssemblyModule.cpp:
+        (JSC::JSWebAssemblyModule::create):
+        (JSC::JSWebAssemblyModule::JSWebAssemblyModule):
+        (JSC::JSWebAssemblyModule::visitChildren):
+        * wasm/js/JSWebAssemblyModule.h: hold the link call info, the import function stubs, and the function index space
+        (JSC::JSWebAssemblyModule::signatureForFunctionIndexSpace):
+        (JSC::JSWebAssemblyModule::importCount):
+        (JSC::JSWebAssemblyModule::calleeFromFunctionIndexSpace):
+        * wasm/js/WebAssemblyFunction.cpp:
+        (JSC::callWebAssemblyFunction): set top Instance on VM
+        * wasm/js/WebAssemblyFunction.h:
+        (JSC::WebAssemblyFunction::instance):
+        * wasm/js/WebAssemblyInstanceConstructor.cpp:
+        (JSC::constructJSWebAssemblyInstance): handle function imports
+        * wasm/js/WebAssemblyModuleConstructor.cpp:
+        (JSC::constructJSWebAssemblyModule): generate the stubs for import functions
+        * wasm/js/WebAssemblyModuleRecord.cpp:
+        (JSC::WebAssemblyModuleRecord::link):
+        * wasm/js/WebAssemblyToJSCallee.cpp: Copied from Source/JavaScriptCore/wasm/js/JSWebAssemblyCallee.cpp.
+        (JSC::WebAssemblyToJSCallee::create): dummy JSCell singleton which lives on the VM, and is put as the callee in the import stub's frame to identified it when unwinding
+        (JSC::WebAssemblyToJSCallee::createStructure):
+        (JSC::WebAssemblyToJSCallee::WebAssemblyToJSCallee):
+        (JSC::WebAssemblyToJSCallee::finishCreation):
+        (JSC::WebAssemblyToJSCallee::destroy):
+        * wasm/js/WebAssemblyToJSCallee.h: Copied from Source/JavaScriptCore/wasm/WasmB3IRGenerator.h.
+
 2016-12-08  Mark Lam  <mark.lam@apple.com>
 
         Enable JSC restricted options by default in the jsc shell.
index d3bf9a1..34c5de5 100644 (file)
                AD4937C81DDD0AAE0077C807 /* WebAssemblyModuleRecord.h in Headers */ = {isa = PBXBuildFile; fileRef = AD4937C61DDCDCF00077C807 /* WebAssemblyModuleRecord.h */; };
                AD4937D31DDD27DE0077C807 /* WebAssemblyFunction.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AD4937C91DDD27340077C807 /* WebAssemblyFunction.cpp */; };
                AD4937D41DDD27DE0077C807 /* WebAssemblyFunction.h in Headers */ = {isa = PBXBuildFile; fileRef = AD4937CA1DDD27340077C807 /* WebAssemblyFunction.h */; };
+               AD4B1DF91DF244E20071AE32 /* WasmBinding.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AD4B1DF71DF244D70071AE32 /* WasmBinding.cpp */; };
+               AD4B1DFA1DF244E20071AE32 /* WasmBinding.h in Headers */ = {isa = PBXBuildFile; fileRef = AD4B1DF81DF244D70071AE32 /* WasmBinding.h */; };
                AD86A93E1AA4D88D002FE77F /* WeakGCMapInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = AD86A93D1AA4D87C002FE77F /* WeakGCMapInlines.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               ADBC54D41DF8EA2B005BF738 /* WebAssemblyToJSCallee.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ADBC54D21DF8EA00005BF738 /* WebAssemblyToJSCallee.cpp */; };
+               ADBC54D51DF8EA2B005BF738 /* WebAssemblyToJSCallee.h in Headers */ = {isa = PBXBuildFile; fileRef = ADBC54D31DF8EA00005BF738 /* WebAssemblyToJSCallee.h */; };
                ADDB1F6318D77DBE009B58A8 /* OpaqueRootSet.h in Headers */ = {isa = PBXBuildFile; fileRef = ADDB1F6218D77DB7009B58A8 /* OpaqueRootSet.h */; settings = {ATTRIBUTES = (Private, ); }; };
                ADE39FFF16DD144B0003CD4A /* PropertyTable.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AD1CF06816DCAB2D00B97123 /* PropertyTable.cpp */; };
                B59F89391891F29F00D5CCDC /* UnlinkedInstructionStream.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B59F89381891ADB500D5CCDC /* UnlinkedInstructionStream.cpp */; };
                AD4937C61DDCDCF00077C807 /* WebAssemblyModuleRecord.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = WebAssemblyModuleRecord.h; path = js/WebAssemblyModuleRecord.h; sourceTree = "<group>"; };
                AD4937C91DDD27340077C807 /* WebAssemblyFunction.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = WebAssemblyFunction.cpp; path = js/WebAssemblyFunction.cpp; sourceTree = "<group>"; };
                AD4937CA1DDD27340077C807 /* WebAssemblyFunction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = WebAssemblyFunction.h; path = js/WebAssemblyFunction.h; sourceTree = "<group>"; };
+               AD4B1DF71DF244D70071AE32 /* WasmBinding.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WasmBinding.cpp; sourceTree = "<group>"; };
+               AD4B1DF81DF244D70071AE32 /* WasmBinding.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WasmBinding.h; sourceTree = "<group>"; };
                AD86A93D1AA4D87C002FE77F /* WeakGCMapInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WeakGCMapInlines.h; sourceTree = "<group>"; };
+               ADBC54D21DF8EA00005BF738 /* WebAssemblyToJSCallee.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = WebAssemblyToJSCallee.cpp; path = js/WebAssemblyToJSCallee.cpp; sourceTree = "<group>"; };
+               ADBC54D31DF8EA00005BF738 /* WebAssemblyToJSCallee.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = WebAssemblyToJSCallee.h; path = js/WebAssemblyToJSCallee.h; sourceTree = "<group>"; };
                ADDB1F6218D77DB7009B58A8 /* OpaqueRootSet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OpaqueRootSet.h; sourceTree = "<group>"; };
                B59F89371891AD3300D5CCDC /* UnlinkedInstructionStream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UnlinkedInstructionStream.h; sourceTree = "<group>"; };
                B59F89381891ADB500D5CCDC /* UnlinkedInstructionStream.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = UnlinkedInstructionStream.cpp; sourceTree = "<group>"; };
                7B98D1331B60CD1E0023B1A4 /* wasm */ = {
                        isa = PBXGroup;
                        children = (
+                               AD2FCB8A1DB5840000B3E736 /* js */,
                                AD2FCC2E1DB839F700B3E736 /* JSWebAssembly.cpp */,
                                AD2FCC2F1DB839F700B3E736 /* JSWebAssembly.h */,
-                               AD2FCB8A1DB5840000B3E736 /* js */,
                                53F40E8E1D5902820099A1B6 /* WasmB3IRGenerator.cpp */,
                                53F40E921D5A4AB30099A1B6 /* WasmB3IRGenerator.h */,
+                               AD4B1DF71DF244D70071AE32 /* WasmBinding.cpp */,
+                               AD4B1DF81DF244D70071AE32 /* WasmBinding.h */,
                                53FD04D11D7AB187003287D3 /* WasmCallingConvention.cpp */,
                                53FD04D21D7AB187003287D3 /* WasmCallingConvention.h */,
                                AD2FCC321DC4045300B3E736 /* WasmFormat.cpp */,
                                535557131D9D9EA5006D583B /* WasmMemory.h */,
                                53F40E961D5A7BEC0099A1B6 /* WasmModuleParser.cpp */,
                                53F40E941D5A7AEF0099A1B6 /* WasmModuleParser.h */,
+                               53F40E8C1D5901F20099A1B6 /* WasmParser.h */,
                                531374BE1D5CE95000AF7A0B /* WasmPlan.cpp */,
                                531374BC1D5CE67600AF7A0B /* WasmPlan.h */,
-                               53F40E8C1D5901F20099A1B6 /* WasmParser.h */,
                                53F40E841D58F9770099A1B6 /* WasmSections.h */,
                                53FF7F9A1DBFD2B900A26CCC /* WasmValidate.cpp */,
                                53FF7F981DBFCD9000A26CCC /* WasmValidate.h */,
                AD2FCB8A1DB5840000B3E736 /* js */ = {
                        isa = PBXGroup;
                        children = (
-                               AD4937C91DDD27340077C807 /* WebAssemblyFunction.cpp */,
-                               AD4937CA1DDD27340077C807 /* WebAssemblyFunction.h */,
-                               AD4937C51DDCDCF00077C807 /* WebAssemblyModuleRecord.cpp */,
-                               AD4937C61DDCDCF00077C807 /* WebAssemblyModuleRecord.h */,
-                               AD2FCC261DB838C400B3E736 /* WebAssemblyPrototype.cpp */,
-                               AD2FCC271DB838C400B3E736 /* WebAssemblyPrototype.h */,
                                79E423E01DEE65320078D355 /* JSWebAssemblyCallee.cpp */,
                                79E423E11DEE65320078D355 /* JSWebAssemblyCallee.h */,
                                AD2FCBA61DB58DA400B3E736 /* JSWebAssemblyCompileError.cpp */,
                                AD2FCBA91DB58DA400B3E736 /* JSWebAssemblyInstance.h */,
                                AD2FCBAA1DB58DA400B3E736 /* JSWebAssemblyMemory.cpp */,
                                AD2FCBAB1DB58DA400B3E736 /* JSWebAssemblyMemory.h */,
+                               AD2FCB8C1DB5844000B3E736 /* JSWebAssemblyModule.cpp */,
+                               AD2FCB8D1DB5844000B3E736 /* JSWebAssemblyModule.h */,
                                AD2FCBAC1DB58DA400B3E736 /* JSWebAssemblyRuntimeError.cpp */,
                                AD2FCBAD1DB58DA400B3E736 /* JSWebAssemblyRuntimeError.h */,
                                AD2FCBAE1DB58DA400B3E736 /* JSWebAssemblyTable.cpp */,
                                AD2FCBB11DB58DA400B3E736 /* WebAssemblyCompileErrorConstructor.h */,
                                AD2FCBB21DB58DA400B3E736 /* WebAssemblyCompileErrorPrototype.cpp */,
                                AD2FCBB31DB58DA400B3E736 /* WebAssemblyCompileErrorPrototype.h */,
+                               AD4937C91DDD27340077C807 /* WebAssemblyFunction.cpp */,
+                               AD4937CA1DDD27340077C807 /* WebAssemblyFunction.h */,
                                AD2FCBB41DB58DA400B3E736 /* WebAssemblyInstanceConstructor.cpp */,
                                AD2FCBB51DB58DA400B3E736 /* WebAssemblyInstanceConstructor.h */,
                                AD2FCBB61DB58DA400B3E736 /* WebAssemblyInstancePrototype.cpp */,
                                AD2FCBB91DB58DA400B3E736 /* WebAssemblyMemoryConstructor.h */,
                                AD2FCBBA1DB58DA400B3E736 /* WebAssemblyMemoryPrototype.cpp */,
                                AD2FCBBB1DB58DA400B3E736 /* WebAssemblyMemoryPrototype.h */,
+                               AD2FCB981DB585A600B3E736 /* WebAssemblyModuleConstructor.cpp */,
+                               AD2FCB991DB585A600B3E736 /* WebAssemblyModuleConstructor.h */,
+                               AD2FCB9A1DB585A600B3E736 /* WebAssemblyModulePrototype.cpp */,
+                               AD2FCB9B1DB585A600B3E736 /* WebAssemblyModulePrototype.h */,
+                               AD4937C51DDCDCF00077C807 /* WebAssemblyModuleRecord.cpp */,
+                               AD4937C61DDCDCF00077C807 /* WebAssemblyModuleRecord.h */,
+                               AD2FCC261DB838C400B3E736 /* WebAssemblyPrototype.cpp */,
+                               AD2FCC271DB838C400B3E736 /* WebAssemblyPrototype.h */,
                                AD2FCBBC1DB58DA400B3E736 /* WebAssemblyRuntimeErrorConstructor.cpp */,
                                AD2FCBBD1DB58DA400B3E736 /* WebAssemblyRuntimeErrorConstructor.h */,
                                AD2FCBBE1DB58DA400B3E736 /* WebAssemblyRuntimeErrorPrototype.cpp */,
                                AD2FCBC11DB58DA400B3E736 /* WebAssemblyTableConstructor.h */,
                                AD2FCBC21DB58DA400B3E736 /* WebAssemblyTablePrototype.cpp */,
                                AD2FCBC31DB58DA400B3E736 /* WebAssemblyTablePrototype.h */,
-                               AD2FCB981DB585A600B3E736 /* WebAssemblyModuleConstructor.cpp */,
-                               AD2FCB991DB585A600B3E736 /* WebAssemblyModuleConstructor.h */,
-                               AD2FCB9A1DB585A600B3E736 /* WebAssemblyModulePrototype.cpp */,
-                               AD2FCB9B1DB585A600B3E736 /* WebAssemblyModulePrototype.h */,
-                               AD2FCB8C1DB5844000B3E736 /* JSWebAssemblyModule.cpp */,
-                               AD2FCB8D1DB5844000B3E736 /* JSWebAssemblyModule.h */,
+                               ADBC54D21DF8EA00005BF738 /* WebAssemblyToJSCallee.cpp */,
+                               ADBC54D31DF8EA00005BF738 /* WebAssemblyToJSCallee.h */,
                        );
                        name = js;
                        sourceTree = "<group>";
                                0F2B66E017B6B5AB00A7AE3F /* GenericTypedArrayView.h in Headers */,
                                0F2B66E117B6B5AB00A7AE3F /* GenericTypedArrayViewInlines.h in Headers */,
                                0F9332A014CA7DCD0085F3C6 /* GetByIdStatus.h in Headers */,
+                               AD4B1DFA1DF244E20071AE32 /* WasmBinding.h in Headers */,
                                0F0332C418B01763005F979A /* GetByIdVariant.h in Headers */,
                                7964656A1B952FF0003059EE /* GetPutInfo.h in Headers */,
                                AD2FCC1C1DB59CB200B3E736 /* WebAssemblyModuleConstructor.lut.h in Headers */,
                                0F2B66F517B6B5AB00A7AE3F /* JSGenericTypedArrayViewPrototype.h in Headers */,
                                53917E7B1B7906FA000EBD33 /* JSGenericTypedArrayViewPrototypeFunctions.h in Headers */,
                                0F2B66F617B6B5AB00A7AE3F /* JSGenericTypedArrayViewPrototypeInlines.h in Headers */,
+                               ADBC54D51DF8EA2B005BF738 /* WebAssemblyToJSCallee.h in Headers */,
                                797E07AA1B8FCFB9008400BA /* JSGlobalLexicalEnvironment.h in Headers */,
                                BC18C4210E16F5CD00B34460 /* JSGlobalObject.h in Headers */,
                                53F40E8B1D5901BB0099A1B6 /* WasmFunctionParser.h in Headers */,
                                62D2D38F1ADF103F000206C1 /* FunctionRareData.cpp in Sources */,
                                2AACE63C18CA5A0300ED0191 /* GCActivityCallback.cpp in Sources */,
                                0F766D2F15A8DCE0008F363E /* GCAwareJITStubRoutine.cpp in Sources */,
+                               AD4B1DF91DF244E20071AE32 /* WasmBinding.cpp in Sources */,
                                2ADFA26318EF3540004F9FCC /* GCLogging.cpp in Sources */,
                                5341FC701DAC33E500E7E4D7 /* B3WasmBoundsCheckValue.cpp in Sources */,
                                0F93329F14CA7DCA0085F3C6 /* GetByIdStatus.cpp in Sources */,
                                0F4A38F91C8E13DF00190318 /* SuperSampler.cpp in Sources */,
                                797E07A91B8FCFB9008400BA /* JSGlobalLexicalEnvironment.cpp in Sources */,
                                DC454B8C1D00E822004C18AF /* AirDumpAsJS.cpp in Sources */,
+                               ADBC54D41DF8EA2B005BF738 /* WebAssemblyToJSCallee.cpp in Sources */,
                                147F39D2107EC37600427A48 /* JSGlobalObject.cpp in Sources */,
                                A5FD0085189B1B7E00633231 /* JSGlobalObjectConsoleAgent.cpp in Sources */,
                                A5C3A1A518C0490200C9593A /* JSGlobalObjectConsoleClient.cpp in Sources */,
index ba2ee67..9822d9c 100644 (file)
@@ -86,6 +86,7 @@ namespace JSC  {
     public:
         static const int headerSizeInRegisters = CallFrameSlot::argumentCount + 1;
 
+        JSCell* callee() const { return this[CallFrameSlot::callee].unboxedCell(); }
         JSValue calleeAsValue() const { return this[CallFrameSlot::callee].jsValue(); }
         JSObject* jsCallee() const { return this[CallFrameSlot::callee].object(); }
         SUPPRESS_ASAN JSValue unsafeCallee() const { return this[CallFrameSlot::callee].asanUnsafeJSValue(); }
index 59ff082..721a4ea 100644 (file)
@@ -306,39 +306,6 @@ RegisterSet RegisterSet::ftlCalleeSaveRegisters()
     return result;
 }
 
-#if ENABLE(WEBASSEMBLY)
-RegisterSet RegisterSet::webAssemblyCalleeSaveRegisters()
-{
-    RegisterSet result;
-#if CPU(X86)
-#elif CPU(X86_64)
-#if !OS(WINDOWS)
-    ASSERT(GPRInfo::regCS3 == GPRInfo::tagTypeNumberRegister);
-    ASSERT(GPRInfo::regCS4 == GPRInfo::tagMaskRegister);
-    result.set(GPRInfo::regCS3);
-    result.set(GPRInfo::regCS4);
-#else
-    ASSERT(GPRInfo::regCS5 == GPRInfo::tagTypeNumberRegister);
-    ASSERT(GPRInfo::regCS6 == GPRInfo::tagMaskRegister);
-    result.set(GPRInfo::regCS5);
-    result.set(GPRInfo::regCS6);
-#endif
-#elif CPU(ARM_THUMB2)
-#elif CPU(ARM_TRADITIONAL)
-#elif CPU(ARM64)
-    ASSERT(GPRInfo::regCS8 == GPRInfo::tagTypeNumberRegister);
-    ASSERT(GPRInfo::regCS9 == GPRInfo::tagMaskRegister);
-    result.set(GPRInfo::regCS8);
-    result.set(GPRInfo::regCS9);
-#elif CPU(MIPS)
-#elif CPU(SH4)
-#else
-    UNREACHABLE_FOR_PLATFORM();
-#endif
-    return result;
-}
-#endif
-
 RegisterSet RegisterSet::argumentGPRS()
 {
     RegisterSet result;
index c2bcb6d..9c9142d 100644 (file)
@@ -2592,7 +2592,7 @@ static JSValue callWasmFunction(VM* vm, JSGlobalObject* globalObject, JSWebAssem
     ProtoCallFrame protoCallFrame;
     protoCallFrame.init(nullptr, globalObject->globalExec()->jsCallee(), firstArgument, argCount, remainingArgs);
 
-    return JSValue::decode(vmEntryToWasm(wasmCallee->jsEntryPoint(), vm, &protoCallFrame));
+    return JSValue::decode(vmEntryToWasm(wasmCallee->jsToWasmEntryPoint(), vm, &protoCallFrame));
 }
 
 // testWasmModule(JSArrayBufferView source, number functionCount, ...[[WasmValue, [WasmValue]]]) where the ith copy of [[result, [args]]] is a list
@@ -2618,7 +2618,7 @@ static EncodedJSValue JSC_HOST_CALL functionTestWasmModuleFunctions(ExecState* e
         CRASH();
     }
 
-    if (plan.compiledFunctionCount() != functionCount)
+    if (plan.internalFunctionCount() != functionCount)
         CRASH();
 
     MarkedArgumentBuffer callees;
index 358e9f5..0b95ad5 100644 (file)
@@ -123,11 +123,11 @@ inline void JSCell::visitChildren(JSCell* cell, SlotVisitor& visitor)
 
 ALWAYS_INLINE VM& ExecState::vm() const
 {
-    ASSERT(jsCallee());
-    ASSERT(jsCallee()->vm());
-    ASSERT(!jsCallee()->isLargeAllocation());
+    ASSERT(callee());
+    ASSERT(callee()->vm());
+    ASSERT(!callee()->isLargeAllocation());
     // This is an important optimization since we access this so often.
-    return *calleeAsValue().asCell()->markedBlock().vm();
+    return *callee()->markedBlock().vm();
 }
 
 template<typename T>
index 7da1bff..089e969 100644 (file)
@@ -168,6 +168,7 @@ VM::VM(VMType vmType, HeapType heapType)
     , clientData(0)
     , topVMEntryFrame(nullptr)
     , topCallFrame(CallFrame::noCaller())
+    , topJSWebAssemblyInstance(nullptr)
     , m_atomicStringTable(vmType == Default ? wtfThreadData().atomicStringTable() : new AtomicStringTable)
     , propertyNames(nullptr)
     , emptyList(new MarkedArgumentBuffer)
@@ -229,6 +230,8 @@ VM::VM(VMType vmType, HeapType heapType)
     functionExecutableStructure.set(*this, FunctionExecutable::createStructure(*this, 0, jsNull()));
 #if ENABLE(WEBASSEMBLY)
     webAssemblyCalleeStructure.set(*this, JSWebAssemblyCallee::createStructure(*this, 0, jsNull()));
+    webAssemblyToJSCalleeStructure.set(*this, WebAssemblyToJSCallee::createStructure(*this, 0, jsNull()));
+    webAssemblyToJSCallee.set(*this, WebAssemblyToJSCallee::create(*this, webAssemblyToJSCalleeStructure.get()));
 #endif
     moduleProgramExecutableStructure.set(*this, ModuleProgramExecutable::createStructure(*this, 0, jsNull()));
     regExpStructure.set(*this, RegExp::createStructure(*this, 0, jsNull()));
index 73eb40b..a634ff4 100644 (file)
@@ -96,6 +96,7 @@ class Interpreter;
 class JSCustomGetterSetterFunction;
 class JSGlobalObject;
 class JSObject;
+class JSWebAssemblyInstance;
 class LLIntOffsetsExtractor;
 class NativeExecutable;
 class RegExpCache;
@@ -292,7 +293,8 @@ public:
     // topVMEntryFrame.
     // FIXME: This should be a void*, because it might not point to a CallFrame.
     // https://bugs.webkit.org/show_bug.cgi?id=160441
-    ExecState* topCallFrame; 
+    ExecState* topCallFrame;
+    JSWebAssemblyInstance* topJSWebAssemblyInstance;
     Strong<Structure> structureStructure;
     Strong<Structure> structureRareDataStructure;
     Strong<Structure> terminatedExecutionErrorStructure;
@@ -310,6 +312,8 @@ public:
     Strong<Structure> functionExecutableStructure;
 #if ENABLE(WEBASSEMBLY)
     Strong<Structure> webAssemblyCalleeStructure;
+    Strong<Structure> webAssemblyToJSCalleeStructure;
+    Strong<JSCell> webAssemblyToJSCallee;
 #endif
     Strong<Structure> moduleProgramExecutableStructure;
     Strong<Structure> regExpStructure;
index efe0050..8f933c4 100644 (file)
@@ -175,13 +175,13 @@ static void checkPlan(Plan& plan, unsigned expectedNumberOfFunctions)
         CRASH();
     }
 
-    if (plan.compiledFunctionCount() != expectedNumberOfFunctions) {
+    if (plan.internalFunctionCount() != expectedNumberOfFunctions) {
         dataLogLn("Incorrect number of functions");
         CRASH();
     }
 
     for (unsigned i = 0; i < expectedNumberOfFunctions; ++i) {
-        if (!plan.compiledFunction(i)) {
+        if (!plan.jsToWasmEntryPointForFunction(i)) {
             dataLogLn("Function at index, " , i, " failed to compile correctly");
             CRASH();
         }
@@ -222,10 +222,10 @@ static void runWasmTests()
         checkPlan(plan, 1);
 
         // Test this doesn't crash.
-        CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(0) }), 1);
-        CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(1) }), 2);
-        CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(100) }), 101);
-        CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(122) }), 123);
+        CHECK_EQ(invoke<int>(*plan.jsToWasmEntryPointForFunction(0), { box(0) }), 1);
+        CHECK_EQ(invoke<int>(*plan.jsToWasmEntryPointForFunction(0), { box(1) }), 2);
+        CHECK_EQ(invoke<int>(*plan.jsToWasmEntryPointForFunction(0), { box(100) }), 101);
+        CHECK_EQ(invoke<int>(*plan.jsToWasmEntryPointForFunction(0), { box(122) }), 123);
     }
 
     {
@@ -268,15 +268,15 @@ static void runWasmTests()
         checkPlan(plan, 1);
 
         // Test this doesn't crash.
-        CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(0) }), 213);
-        CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(1) }), 212);
-        CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(2) }), 211);
-        CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(3) }), 210);
-        CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(3) }), 210);
-        CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(4) }), 214);
-        CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(5) }), 214);
-        CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(-1) }), 214);
-        CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(-1000) }), 214);
+        CHECK_EQ(invoke<int>(*plan.jsToWasmEntryPointForFunction(0), { box(0) }), 213);
+        CHECK_EQ(invoke<int>(*plan.jsToWasmEntryPointForFunction(0), { box(1) }), 212);
+        CHECK_EQ(invoke<int>(*plan.jsToWasmEntryPointForFunction(0), { box(2) }), 211);
+        CHECK_EQ(invoke<int>(*plan.jsToWasmEntryPointForFunction(0), { box(3) }), 210);
+        CHECK_EQ(invoke<int>(*plan.jsToWasmEntryPointForFunction(0), { box(3) }), 210);
+        CHECK_EQ(invoke<int>(*plan.jsToWasmEntryPointForFunction(0), { box(4) }), 214);
+        CHECK_EQ(invoke<int>(*plan.jsToWasmEntryPointForFunction(0), { box(5) }), 214);
+        CHECK_EQ(invoke<int>(*plan.jsToWasmEntryPointForFunction(0), { box(-1) }), 214);
+        CHECK_EQ(invoke<int>(*plan.jsToWasmEntryPointForFunction(0), { box(-1000) }), 214);
     }
 
     {
@@ -306,10 +306,10 @@ static void runWasmTests()
         checkPlan(plan, 1);
 
         // Test this doesn't crash.
-        CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(0) }), 22);
-        CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(1) }), 20);
-        CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(11) }), 20);
-        CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(-100) }), 20);
+        CHECK_EQ(invoke<int>(*plan.jsToWasmEntryPointForFunction(0), { box(0) }), 22);
+        CHECK_EQ(invoke<int>(*plan.jsToWasmEntryPointForFunction(0), { box(1) }), 20);
+        CHECK_EQ(invoke<int>(*plan.jsToWasmEntryPointForFunction(0), { box(11) }), 20);
+        CHECK_EQ(invoke<int>(*plan.jsToWasmEntryPointForFunction(0), { box(-100) }), 20);
     }
 
     {
@@ -339,8 +339,8 @@ static void runWasmTests()
         checkPlan(plan, 1);
 
         // Test this doesn't crash.
-        CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(0), box(32) }), 1);
-        CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(1), box(32) }), 2);
+        CHECK_EQ(invoke<int>(*plan.jsToWasmEntryPointForFunction(0), { box(0), box(32) }), 1);
+        CHECK_EQ(invoke<int>(*plan.jsToWasmEntryPointForFunction(0), { box(1), box(32) }), 2);
     }
 
     {
@@ -366,8 +366,8 @@ static void runWasmTests()
         checkPlan(plan, 1);
 
         // Test this doesn't crash.
-        CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(0), box(32) }), 1);
-        CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(1), box(32) }), 2);
+        CHECK_EQ(invoke<int>(*plan.jsToWasmEntryPointForFunction(0), { box(0), box(32) }), 1);
+        CHECK_EQ(invoke<int>(*plan.jsToWasmEntryPointForFunction(0), { box(1), box(32) }), 2);
     }
 
     {
@@ -404,14 +404,14 @@ static void runWasmTests()
         checkPlan(plan, 1);
 
         // Test this doesn't crash.
-        CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(0), box(1) }), 1);
-        CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(1), box(0) }), 0);
-        CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(2), box(1) }), 0);
-        CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(1), box(2) }), 1);
-        CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(2), box(2) }), 0);
-        CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(1), box(1) }), 0);
-        CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(2), box(6) }), 1);
-        CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(100), box(6) }), 0);
+        CHECK_EQ(invoke<int>(*plan.jsToWasmEntryPointForFunction(0), { box(0), box(1) }), 1);
+        CHECK_EQ(invoke<int>(*plan.jsToWasmEntryPointForFunction(0), { box(1), box(0) }), 0);
+        CHECK_EQ(invoke<int>(*plan.jsToWasmEntryPointForFunction(0), { box(2), box(1) }), 0);
+        CHECK_EQ(invoke<int>(*plan.jsToWasmEntryPointForFunction(0), { box(1), box(2) }), 1);
+        CHECK_EQ(invoke<int>(*plan.jsToWasmEntryPointForFunction(0), { box(2), box(2) }), 0);
+        CHECK_EQ(invoke<int>(*plan.jsToWasmEntryPointForFunction(0), { box(1), box(1) }), 0);
+        CHECK_EQ(invoke<int>(*plan.jsToWasmEntryPointForFunction(0), { box(2), box(6) }), 1);
+        CHECK_EQ(invoke<int>(*plan.jsToWasmEntryPointForFunction(0), { box(100), box(6) }), 0);
     }
 
     {
@@ -434,10 +434,10 @@ static void runWasmTests()
         checkPlan(plan, 2);
 
         // Test this doesn't crash.
-        CHECK(isIdentical(invoke<float>(*plan.compiledFunction(1)->jsEntryPoint, { boxf(0.0), boxf(1.5) }), -1.5f));
-        CHECK(isIdentical(invoke<float>(*plan.compiledFunction(1)->jsEntryPoint, { boxf(100.1234), boxf(12.5) }), 87.6234f));
-        CHECK(isIdentical(invoke<float>(*plan.compiledFunction(0)->jsEntryPoint, { boxf(0.0), boxf(1.5) }), -1.5f));
-        CHECK(isIdentical(invoke<float>(*plan.compiledFunction(0)->jsEntryPoint, { boxf(100.1234), boxf(12.5) }), 87.6234f));
+        CHECK(isIdentical(invoke<float>(*plan.jsToWasmEntryPointForFunction(1), { boxf(0.0), boxf(1.5) }), -1.5f));
+        CHECK(isIdentical(invoke<float>(*plan.jsToWasmEntryPointForFunction(1), { boxf(100.1234), boxf(12.5) }), 87.6234f));
+        CHECK(isIdentical(invoke<float>(*plan.jsToWasmEntryPointForFunction(0), { boxf(0.0), boxf(1.5) }), -1.5f));
+        CHECK(isIdentical(invoke<float>(*plan.jsToWasmEntryPointForFunction(0), { boxf(100.1234), boxf(12.5) }), 87.6234f));
     }
 
     {
@@ -460,10 +460,10 @@ static void runWasmTests()
         checkPlan(plan, 2);
 
         // Test this doesn't crash.
-        CHECK(isIdentical(invoke<float>(*plan.compiledFunction(1)->jsEntryPoint, { boxf(0.0), boxf(1.5) }), 1.5f));
-        CHECK(isIdentical(invoke<float>(*plan.compiledFunction(1)->jsEntryPoint, { boxf(100.1234), boxf(12.5) }), 112.6234f));
-        CHECK(isIdentical(invoke<float>(*plan.compiledFunction(0)->jsEntryPoint, { boxf(0.0), boxf(1.5) }), 1.5f));
-        CHECK(isIdentical(invoke<float>(*plan.compiledFunction(0)->jsEntryPoint, { boxf(100.1234), boxf(12.5) }), 112.6234f));
+        CHECK(isIdentical(invoke<float>(*plan.jsToWasmEntryPointForFunction(1), { boxf(0.0), boxf(1.5) }), 1.5f));
+        CHECK(isIdentical(invoke<float>(*plan.jsToWasmEntryPointForFunction(1), { boxf(100.1234), boxf(12.5) }), 112.6234f));
+        CHECK(isIdentical(invoke<float>(*plan.jsToWasmEntryPointForFunction(0), { boxf(0.0), boxf(1.5) }), 1.5f));
+        CHECK(isIdentical(invoke<float>(*plan.jsToWasmEntryPointForFunction(0), { boxf(100.1234), boxf(12.5) }), 112.6234f));
     }
 
     {
@@ -491,11 +491,11 @@ static void runWasmTests()
         checkPlan(plan, 2);
 
         // Test this doesn't crash.
-        CHECK_EQ(invoke<int>(*plan.compiledFunction(1)->jsEntryPoint, { box(0) }), 0);
-        CHECK_EQ(invoke<int>(*plan.compiledFunction(1)->jsEntryPoint, { box(100) }), 1200);
-        CHECK_EQ(invoke<int>(*plan.compiledFunction(1)->jsEntryPoint, { box(1) }), 12);
-        CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(1), box(2), box(3), box(4), box(5), box(6), box(7), box(8), box(9), box(10), box(11), box(12) }), 78);
-        CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(1), box(2), box(3), box(4), box(5), box(6), box(7), box(8), box(9), box(10), box(11), box(100) }), 166);
+        CHECK_EQ(invoke<int>(*plan.jsToWasmEntryPointForFunction(1), { box(0) }), 0);
+        CHECK_EQ(invoke<int>(*plan.jsToWasmEntryPointForFunction(1), { box(100) }), 1200);
+        CHECK_EQ(invoke<int>(*plan.jsToWasmEntryPointForFunction(1), { box(1) }), 12);
+        CHECK_EQ(invoke<int>(*plan.jsToWasmEntryPointForFunction(0), { box(1), box(2), box(3), box(4), box(5), box(6), box(7), box(8), box(9), box(10), box(11), box(12) }), 78);
+        CHECK_EQ(invoke<int>(*plan.jsToWasmEntryPointForFunction(0), { box(1), box(2), box(3), box(4), box(5), box(6), box(7), box(8), box(9), box(10), box(11), box(100) }), 166);
     }
 
     {
@@ -522,10 +522,10 @@ static void runWasmTests()
         checkPlan(plan, 1);
 
         // Test this doesn't crash.
-        CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(0) }), 1);
-        CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(1) }), 1);
-        CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(2) }), 2);
-        CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(4) }), 24);
+        CHECK_EQ(invoke<int>(*plan.jsToWasmEntryPointForFunction(0), { box(0) }), 1);
+        CHECK_EQ(invoke<int>(*plan.jsToWasmEntryPointForFunction(0), { box(1) }), 1);
+        CHECK_EQ(invoke<int>(*plan.jsToWasmEntryPointForFunction(0), { box(2) }), 2);
+        CHECK_EQ(invoke<int>(*plan.jsToWasmEntryPointForFunction(0), { box(4) }), 24);
     }
 
     {
@@ -548,12 +548,12 @@ static void runWasmTests()
         checkPlan(plan, 2);
 
         // Test this doesn't crash.
-        CHECK_EQ(invoke<int>(*plan.compiledFunction(1)->jsEntryPoint, { box(0), box(0) }), 0);
-        CHECK_EQ(invoke<int>(*plan.compiledFunction(1)->jsEntryPoint, { box(100), box(0) }), 100);
-        CHECK_EQ(invoke<int>(*plan.compiledFunction(1)->jsEntryPoint, { box(1), box(15) }), 16);
-        CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(0) }), 0);
-        CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(100) }), 200);
-        CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(1) }), 2);
+        CHECK_EQ(invoke<int>(*plan.jsToWasmEntryPointForFunction(1), { box(0), box(0) }), 0);
+        CHECK_EQ(invoke<int>(*plan.jsToWasmEntryPointForFunction(1), { box(100), box(0) }), 100);
+        CHECK_EQ(invoke<int>(*plan.jsToWasmEntryPointForFunction(1), { box(1), box(15) }), 16);
+        CHECK_EQ(invoke<int>(*plan.jsToWasmEntryPointForFunction(0), { box(0) }), 0);
+        CHECK_EQ(invoke<int>(*plan.jsToWasmEntryPointForFunction(0), { box(100) }), 200);
+        CHECK_EQ(invoke<int>(*plan.jsToWasmEntryPointForFunction(0), { box(1) }), 2);
     }
 
     {
@@ -576,12 +576,12 @@ static void runWasmTests()
         checkPlan(plan, 2);
 
         // Test this doesn't crash.
-        CHECK_EQ(invoke<int>(*plan.compiledFunction(1)->jsEntryPoint, { box(0) }), 0);
-        CHECK_EQ(invoke<int>(*plan.compiledFunction(1)->jsEntryPoint, { box(100) }), 100);
-        CHECK_EQ(invoke<int>(*plan.compiledFunction(1)->jsEntryPoint, { box(1) }), 1);
-        CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(0) }), 0);
-        CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(100) }), 100);
-        CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(1) }), 1);
+        CHECK_EQ(invoke<int>(*plan.jsToWasmEntryPointForFunction(1), { box(0) }), 0);
+        CHECK_EQ(invoke<int>(*plan.jsToWasmEntryPointForFunction(1), { box(100) }), 100);
+        CHECK_EQ(invoke<int>(*plan.jsToWasmEntryPointForFunction(1), { box(1) }), 1);
+        CHECK_EQ(invoke<int>(*plan.jsToWasmEntryPointForFunction(0), { box(0) }), 0);
+        CHECK_EQ(invoke<int>(*plan.jsToWasmEntryPointForFunction(0), { box(100) }), 100);
+        CHECK_EQ(invoke<int>(*plan.jsToWasmEntryPointForFunction(0), { box(1) }), 1);
     }
 
     {
@@ -605,9 +605,9 @@ static void runWasmTests()
         checkPlan(plan, 1);
 
         // Test this doesn't crash.
-        CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(0), box(10) }), 0);
-        CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(100), box(2) }), 100);
-        CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(1), box(100) }), 1);
+        CHECK_EQ(invoke<int>(*plan.jsToWasmEntryPointForFunction(0), { box(0), box(10) }), 0);
+        CHECK_EQ(invoke<int>(*plan.jsToWasmEntryPointForFunction(0), { box(100), box(2) }), 100);
+        CHECK_EQ(invoke<int>(*plan.jsToWasmEntryPointForFunction(0), { box(1), box(100) }), 1);
     }
 
     {
@@ -632,9 +632,9 @@ static void runWasmTests()
         checkPlan(plan, 1);
 
         // Test this doesn't crash.
-        CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(0), box(10) }), 0);
-        CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(100), box(2) }), 100);
-        CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(1), box(100) }), 1);
+        CHECK_EQ(invoke<int>(*plan.jsToWasmEntryPointForFunction(0), { box(0), box(10) }), 0);
+        CHECK_EQ(invoke<int>(*plan.jsToWasmEntryPointForFunction(0), { box(100), box(2) }), 100);
+        CHECK_EQ(invoke<int>(*plan.jsToWasmEntryPointForFunction(0), { box(1), box(100) }), 1);
     }
 
     {
@@ -673,7 +673,7 @@ static void runWasmTests()
         unsigned length = 5;
         unsigned offset = sizeof(uint32_t);
         uint32_t* memory = static_cast<uint32_t*>(plan.memory()->memory());
-        invoke<void>(*plan.compiledFunction(0)->jsEntryPoint, { box(100), box(offset), box(length) });
+        invoke<void>(*plan.jsToWasmEntryPointForFunction(0), { box(100), box(offset), box(length) });
         offset /= sizeof(uint32_t);
         CHECK_EQ(memory[offset - 1], 0u);
         CHECK_EQ(memory[offset + length], 0u);
@@ -682,7 +682,7 @@ static void runWasmTests()
 
         length = 10;
         offset = 5 * sizeof(uint32_t);
-        invoke<void>(*plan.compiledFunction(0)->jsEntryPoint, { box(5), box(offset), box(length) });
+        invoke<void>(*plan.jsToWasmEntryPointForFunction(0), { box(5), box(offset), box(length) });
         offset /= sizeof(uint32_t);
         CHECK_EQ(memory[offset - 1], 100u);
         CHECK_EQ(memory[offset + length], 0u);
@@ -725,7 +725,7 @@ static void runWasmTests()
         unsigned length = 5;
         unsigned offset = 1;
         uint8_t* memory = static_cast<uint8_t*>(plan.memory()->memory());
-        invoke<void>(*plan.compiledFunction(0)->jsEntryPoint, { box(100), box(offset), box(length) });
+        invoke<void>(*plan.jsToWasmEntryPointForFunction(0), { box(100), box(offset), box(length) });
         CHECK_EQ(memory[offset - 1], 0u);
         CHECK_EQ(memory[offset + length], 0u);
         for (unsigned i = 0; i < length; ++i)
@@ -733,7 +733,7 @@ static void runWasmTests()
 
         length = 10;
         offset = 5;
-        invoke<void>(*plan.compiledFunction(0)->jsEntryPoint, { box(5), box(offset), box(length) });
+        invoke<void>(*plan.jsToWasmEntryPointForFunction(0), { box(5), box(offset), box(length) });
         CHECK_EQ(memory[offset - 1], 100u);
         CHECK_EQ(memory[offset + length], 0u);
         for (unsigned i = 0; i < length; ++i)
@@ -763,9 +763,9 @@ static void runWasmTests()
         ASSERT(plan.memory()->size());
 
         // Test this doesn't crash.
-        CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(0), box(10) }), 0);
-        CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(100), box(2) }), 100);
-        CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(1), box(100) }), 1);
+        CHECK_EQ(invoke<int>(*plan.jsToWasmEntryPointForFunction(0), { box(0), box(10) }), 0);
+        CHECK_EQ(invoke<int>(*plan.jsToWasmEntryPointForFunction(0), { box(100), box(2) }), 100);
+        CHECK_EQ(invoke<int>(*plan.jsToWasmEntryPointForFunction(0), { box(1), box(100) }), 1);
     }
 
     {
@@ -790,9 +790,9 @@ static void runWasmTests()
         checkPlan(plan, 1);
 
         // Test this doesn't crash.
-        CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(0) }), 0);
-        CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(100) }), 100);
-        CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(1) }), 1);
+        CHECK_EQ(invoke<int>(*plan.jsToWasmEntryPointForFunction(0), { box(0) }), 0);
+        CHECK_EQ(invoke<int>(*plan.jsToWasmEntryPointForFunction(0), { box(100) }), 100);
+        CHECK_EQ(invoke<int>(*plan.jsToWasmEntryPointForFunction(0), { box(1) }), 1);
     }
 
     {
@@ -817,10 +817,10 @@ static void runWasmTests()
         checkPlan(plan, 1);
 
         // Test this doesn't crash.
-        CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(0), box(10) }), 0);
-        CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(100), box(2) }), 100);
-        CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(1), box(100) }), 1);
-        CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(-12), box(plan.memory()->size() - sizeof(uint64_t)) }), -12);
+        CHECK_EQ(invoke<int>(*plan.jsToWasmEntryPointForFunction(0), { box(0), box(10) }), 0);
+        CHECK_EQ(invoke<int>(*plan.jsToWasmEntryPointForFunction(0), { box(100), box(2) }), 100);
+        CHECK_EQ(invoke<int>(*plan.jsToWasmEntryPointForFunction(0), { box(1), box(100) }), 1);
+        CHECK_EQ(invoke<int>(*plan.jsToWasmEntryPointForFunction(0), { box(-12), box(plan.memory()->size() - sizeof(uint64_t)) }), -12);
     }
 
     {
@@ -845,9 +845,9 @@ static void runWasmTests()
         checkPlan(plan, 1);
 
         // Test this doesn't crash.
-        CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(0), box(10) }), 0);
-        CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(100), box(2) }), 100);
-        CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(1), box(100) }), 1);
+        CHECK_EQ(invoke<int>(*plan.jsToWasmEntryPointForFunction(0), { box(0), box(10) }), 0);
+        CHECK_EQ(invoke<int>(*plan.jsToWasmEntryPointForFunction(0), { box(100), box(2) }), 100);
+        CHECK_EQ(invoke<int>(*plan.jsToWasmEntryPointForFunction(0), { box(1), box(100) }), 1);
     }
 
     {
@@ -886,7 +886,7 @@ static void runWasmTests()
         unsigned length = 5;
         unsigned offset = sizeof(uint32_t);
         uint32_t* memory = static_cast<uint32_t*>(plan.memory()->memory());
-        invoke<void>(*plan.compiledFunction(0)->jsEntryPoint, { box(100), box(offset), box(length) });
+        invoke<void>(*plan.jsToWasmEntryPointForFunction(0), { box(100), box(offset), box(length) });
         offset /= sizeof(uint32_t);
         CHECK_EQ(memory[offset - 1], 0u);
         CHECK_EQ(memory[offset + length], 0u);
@@ -895,7 +895,7 @@ static void runWasmTests()
 
         length = 10;
         offset = 5 * sizeof(uint32_t);
-        invoke<void>(*plan.compiledFunction(0)->jsEntryPoint, { box(5), box(offset), box(length) });
+        invoke<void>(*plan.jsToWasmEntryPointForFunction(0), { box(5), box(offset), box(length) });
         offset /= sizeof(uint32_t);
         CHECK_EQ(memory[offset - 1], 100u);
         CHECK_EQ(memory[offset + length], 0u);
@@ -938,7 +938,7 @@ static void runWasmTests()
         unsigned length = 5;
         unsigned offset = 1;
         uint8_t* memory = static_cast<uint8_t*>(plan.memory()->memory());
-        invoke<void>(*plan.compiledFunction(0)->jsEntryPoint, { box(100), box(offset), box(length) });
+        invoke<void>(*plan.jsToWasmEntryPointForFunction(0), { box(100), box(offset), box(length) });
         CHECK_EQ(memory[offset - 1], 0u);
         CHECK_EQ(memory[offset + length], 0u);
         for (unsigned i = 0; i < length; ++i)
@@ -946,7 +946,7 @@ static void runWasmTests()
 
         length = 10;
         offset = 5;
-        invoke<void>(*plan.compiledFunction(0)->jsEntryPoint, { box(5), box(offset), box(length) });
+        invoke<void>(*plan.jsToWasmEntryPointForFunction(0), { box(5), box(offset), box(length) });
         CHECK_EQ(memory[offset - 1], 100u);
         CHECK_EQ(memory[offset + length], 0u);
         for (unsigned i = 0; i < length; ++i)
@@ -976,9 +976,9 @@ static void runWasmTests()
         ASSERT(plan.memory()->size());
 
         // Test this doesn't crash.
-        CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(0), box(10) }), 0);
-        CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(100), box(2) }), 100);
-        CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(1), box(100) }), 1);
+        CHECK_EQ(invoke<int>(*plan.jsToWasmEntryPointForFunction(0), { box(0), box(10) }), 0);
+        CHECK_EQ(invoke<int>(*plan.jsToWasmEntryPointForFunction(0), { box(100), box(2) }), 100);
+        CHECK_EQ(invoke<int>(*plan.jsToWasmEntryPointForFunction(0), { box(1), box(100) }), 1);
     }
 
     {
@@ -1003,9 +1003,9 @@ static void runWasmTests()
         checkPlan(plan, 1);
 
         // Test this doesn't crash.
-        CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(0) }), 0);
-        CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(100) }), 100);
-        CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(1) }), 1);
+        CHECK_EQ(invoke<int>(*plan.jsToWasmEntryPointForFunction(0), { box(0) }), 0);
+        CHECK_EQ(invoke<int>(*plan.jsToWasmEntryPointForFunction(0), { box(100) }), 100);
+        CHECK_EQ(invoke<int>(*plan.jsToWasmEntryPointForFunction(0), { box(1) }), 1);
     }
 
     {
@@ -1030,14 +1030,14 @@ static void runWasmTests()
         checkPlan(plan, 1);
 
         // Test this doesn't crash.
-        CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(0), box(1) }), 1);
-        CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(1), box(0) }), 1);
-        CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(2), box(1) }), 1);
-        CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(1), box(2) }), 1);
-        CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(2), box(2) }), 0);
-        CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(1), box(1) }), 0);
-        CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(2), box(6) }), 1);
-        CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(100), box(6) }), 1);
+        CHECK_EQ(invoke<int>(*plan.jsToWasmEntryPointForFunction(0), { box(0), box(1) }), 1);
+        CHECK_EQ(invoke<int>(*plan.jsToWasmEntryPointForFunction(0), { box(1), box(0) }), 1);
+        CHECK_EQ(invoke<int>(*plan.jsToWasmEntryPointForFunction(0), { box(2), box(1) }), 1);
+        CHECK_EQ(invoke<int>(*plan.jsToWasmEntryPointForFunction(0), { box(1), box(2) }), 1);
+        CHECK_EQ(invoke<int>(*plan.jsToWasmEntryPointForFunction(0), { box(2), box(2) }), 0);
+        CHECK_EQ(invoke<int>(*plan.jsToWasmEntryPointForFunction(0), { box(1), box(1) }), 0);
+        CHECK_EQ(invoke<int>(*plan.jsToWasmEntryPointForFunction(0), { box(2), box(6) }), 1);
+        CHECK_EQ(invoke<int>(*plan.jsToWasmEntryPointForFunction(0), { box(100), box(6) }), 1);
     }
 
     {
@@ -1068,14 +1068,14 @@ static void runWasmTests()
         checkPlan(plan, 1);
 
         // Test this doesn't crash.
-        CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(0), box(1) }), 1);
-        CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(1), box(0) }), 0);
-        CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(2), box(1) }), 0);
-        CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(1), box(2) }), 1);
-        CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(2), box(2) }), 0);
-        CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(1), box(1) }), 0);
-        CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(2), box(6) }), 1);
-        CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(100), box(6) }), 0);
+        CHECK_EQ(invoke<int>(*plan.jsToWasmEntryPointForFunction(0), { box(0), box(1) }), 1);
+        CHECK_EQ(invoke<int>(*plan.jsToWasmEntryPointForFunction(0), { box(1), box(0) }), 0);
+        CHECK_EQ(invoke<int>(*plan.jsToWasmEntryPointForFunction(0), { box(2), box(1) }), 0);
+        CHECK_EQ(invoke<int>(*plan.jsToWasmEntryPointForFunction(0), { box(1), box(2) }), 1);
+        CHECK_EQ(invoke<int>(*plan.jsToWasmEntryPointForFunction(0), { box(2), box(2) }), 0);
+        CHECK_EQ(invoke<int>(*plan.jsToWasmEntryPointForFunction(0), { box(1), box(1) }), 0);
+        CHECK_EQ(invoke<int>(*plan.jsToWasmEntryPointForFunction(0), { box(2), box(6) }), 1);
+        CHECK_EQ(invoke<int>(*plan.jsToWasmEntryPointForFunction(0), { box(100), box(6) }), 0);
     }
 
 
@@ -1092,7 +1092,7 @@ static void runWasmTests()
         checkPlan(plan, 1);
 
         // Test this doesn't crash.
-        CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { }), 5);
+        CHECK_EQ(invoke<int>(*plan.jsToWasmEntryPointForFunction(0), { }), 5);
     }
 
 
@@ -1110,7 +1110,7 @@ static void runWasmTests()
         checkPlan(plan, 1);
 
         // Test this doesn't crash.
-        CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { }), 11);
+        CHECK_EQ(invoke<int>(*plan.jsToWasmEntryPointForFunction(0), { }), 11);
     }
 
     {
@@ -1127,7 +1127,7 @@ static void runWasmTests()
         checkPlan(plan, 1);
 
         // Test this doesn't crash.
-        CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { }), 11);
+        CHECK_EQ(invoke<int>(*plan.jsToWasmEntryPointForFunction(0), { }), 11);
     }
 
     {
@@ -1144,7 +1144,7 @@ static void runWasmTests()
         checkPlan(plan, 1);
 
         // Test this doesn't crash.
-        CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { }), 11);
+        CHECK_EQ(invoke<int>(*plan.jsToWasmEntryPointForFunction(0), { }), 11);
     }
 
     {
@@ -1160,10 +1160,10 @@ static void runWasmTests()
         checkPlan(plan, 1);
 
         // Test this doesn't crash.
-        CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(0), box(1) }), 1);
-        CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(100), box(1) }), 101);
-        CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(-1), box(1)}), 0);
-        CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(std::numeric_limits<int>::max()), box(1) }), std::numeric_limits<int>::min());
+        CHECK_EQ(invoke<int>(*plan.jsToWasmEntryPointForFunction(0), { box(0), box(1) }), 1);
+        CHECK_EQ(invoke<int>(*plan.jsToWasmEntryPointForFunction(0), { box(100), box(1) }), 101);
+        CHECK_EQ(invoke<int>(*plan.jsToWasmEntryPointForFunction(0), { box(-1), box(1)}), 0);
+        CHECK_EQ(invoke<int>(*plan.jsToWasmEntryPointForFunction(0), { box(std::numeric_limits<int>::max()), box(1) }), std::numeric_limits<int>::min());
     }
 
     {
@@ -1186,8 +1186,8 @@ static void runWasmTests()
         checkPlan(plan, 1);
 
         // Test this doesn't crash.
-        CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(0) }), 0);
-        CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(10) }), 10);
+        CHECK_EQ(invoke<int>(*plan.jsToWasmEntryPointForFunction(0), { box(0) }), 0);
+        CHECK_EQ(invoke<int>(*plan.jsToWasmEntryPointForFunction(0), { box(10) }), 10);
     }
 
     {
@@ -1219,10 +1219,10 @@ static void runWasmTests()
         checkPlan(plan, 1);
 
         // Test this doesn't crash.
-        CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(0) }), 0);
-        CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(1) }), 1);
-        CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(2)}), 3);
-        CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(100) }), 5050);
+        CHECK_EQ(invoke<int>(*plan.jsToWasmEntryPointForFunction(0), { box(0) }), 0);
+        CHECK_EQ(invoke<int>(*plan.jsToWasmEntryPointForFunction(0), { box(1) }), 1);
+        CHECK_EQ(invoke<int>(*plan.jsToWasmEntryPointForFunction(0), { box(2)}), 3);
+        CHECK_EQ(invoke<int>(*plan.jsToWasmEntryPointForFunction(0), { box(100) }), 5050);
     }
 
     {
@@ -1260,14 +1260,14 @@ static void runWasmTests()
         checkPlan(plan, 1);
 
         // Test this doesn't crash.
-        CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(0), box(1) }), 0);
-        CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(1), box(0) }), 0);
-        CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(2), box(1) }), 2);
-        CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(1), box(2) }), 2);
-        CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(2), box(2) }), 4);
-        CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(2), box(6) }), 12);
-        CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(100), box(6) }), 600);
-        CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(100), box(100) }), 10000);
+        CHECK_EQ(invoke<int>(*plan.jsToWasmEntryPointForFunction(0), { box(0), box(1) }), 0);
+        CHECK_EQ(invoke<int>(*plan.jsToWasmEntryPointForFunction(0), { box(1), box(0) }), 0);
+        CHECK_EQ(invoke<int>(*plan.jsToWasmEntryPointForFunction(0), { box(2), box(1) }), 2);
+        CHECK_EQ(invoke<int>(*plan.jsToWasmEntryPointForFunction(0), { box(1), box(2) }), 2);
+        CHECK_EQ(invoke<int>(*plan.jsToWasmEntryPointForFunction(0), { box(2), box(2) }), 4);
+        CHECK_EQ(invoke<int>(*plan.jsToWasmEntryPointForFunction(0), { box(2), box(6) }), 12);
+        CHECK_EQ(invoke<int>(*plan.jsToWasmEntryPointForFunction(0), { box(100), box(6) }), 600);
+        CHECK_EQ(invoke<int>(*plan.jsToWasmEntryPointForFunction(0), { box(100), box(100) }), 10000);
     }
 
     {
@@ -1310,14 +1310,14 @@ static void runWasmTests()
         checkPlan(plan, 1);
 
         // Test this doesn't crash.
-        CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(0), box(1) }), 1);
-        CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(1), box(0) }), 0);
-        CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(2), box(1) }), 0);
-        CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(1), box(2) }), 1);
-        CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(2), box(2) }), 0);
-        CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(1), box(1) }), 0);
-        CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(2), box(6) }), 1);
-        CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(100), box(6) }), 0);
+        CHECK_EQ(invoke<int>(*plan.jsToWasmEntryPointForFunction(0), { box(0), box(1) }), 1);
+        CHECK_EQ(invoke<int>(*plan.jsToWasmEntryPointForFunction(0), { box(1), box(0) }), 0);
+        CHECK_EQ(invoke<int>(*plan.jsToWasmEntryPointForFunction(0), { box(2), box(1) }), 0);
+        CHECK_EQ(invoke<int>(*plan.jsToWasmEntryPointForFunction(0), { box(1), box(2) }), 1);
+        CHECK_EQ(invoke<int>(*plan.jsToWasmEntryPointForFunction(0), { box(2), box(2) }), 0);
+        CHECK_EQ(invoke<int>(*plan.jsToWasmEntryPointForFunction(0), { box(1), box(1) }), 0);
+        CHECK_EQ(invoke<int>(*plan.jsToWasmEntryPointForFunction(0), { box(2), box(6) }), 1);
+        CHECK_EQ(invoke<int>(*plan.jsToWasmEntryPointForFunction(0), { box(100), box(6) }), 0);
     }
 
 }
index 4bca1f3..996afda 100644 (file)
@@ -50,6 +50,7 @@
 #include "js/WebAssemblyRuntimeErrorPrototype.h"
 #include "js/WebAssemblyTableConstructor.h"
 #include "js/WebAssemblyTablePrototype.h"
+#include "js/WebAssemblyToJSCallee.h"
 
 namespace JSC {
 
index 6dcee37..9f39cd7 100644 (file)
@@ -130,7 +130,7 @@ public:
 
     static constexpr ExpressionType emptyExpression = nullptr;
 
-    B3IRGenerator(Memory*, Procedure&, FunctionCompilation*);
+    B3IRGenerator(Memory*, Procedure&, WasmInternalFunction*, Vector<UnlinkedWasmToWasmCall>&);
 
     bool WARN_UNUSED_RETURN addArguments(const Vector<Type>&);
     bool WARN_UNUSED_RETURN addLocal(Type, uint32_t);
@@ -164,7 +164,7 @@ public:
     bool WARN_UNUSED_RETURN endBlock(ControlEntry&, ExpressionList& expressionStack);
     bool WARN_UNUSED_RETURN addEndToUnreachable(ControlEntry&);
 
-    bool WARN_UNUSED_RETURN addCall(unsigned calleeIndex, const FunctionInformation&, Vector<ExpressionType>& args, ExpressionType& result);
+    bool WARN_UNUSED_RETURN addCall(unsigned calleeIndex, const Signature*, Vector<ExpressionType>& args, ExpressionType& result);
 
     void dump(const Vector<ControlEntry>& controlStack, const ExpressionList& expressionStack);
 
@@ -183,17 +183,16 @@ private:
     Procedure& m_proc;
     BasicBlock* m_currentBlock;
     Vector<Variable*> m_locals;
-    // m_unlikedCalls is list of each call site and the function index whose address it should be patched with.
-    Vector<UnlinkedCall>& m_unlinkedCalls;
+    Vector<UnlinkedWasmToWasmCall>& m_unlinkedWasmToWasmCalls; // List each call site and the function index whose address it should be patched with.
     GPRReg m_memoryBaseGPR;
     GPRReg m_memorySizeGPR;
     Value* m_zeroValues[numTypes];
 };
 
-B3IRGenerator::B3IRGenerator(Memory* memory, Procedure& procedure, FunctionCompilation* compilation)
+B3IRGenerator::B3IRGenerator(Memory* memory, Procedure& procedure, WasmInternalFunction* compilation, Vector<UnlinkedWasmToWasmCall>& unlinkedWasmToWasmCalls)
     : m_memory(memory)
     , m_proc(procedure)
-    , m_unlinkedCalls(compilation->unlinkedCalls)
+    , m_unlinkedWasmToWasmCalls(unlinkedWasmToWasmCalls)
 {
     m_currentBlock = m_proc.addBlock();
 
@@ -595,14 +594,14 @@ bool B3IRGenerator::addEndToUnreachable(ControlEntry& entry)
     return true;
 }
 
-bool B3IRGenerator::addCall(unsigned functionIndex, const FunctionInformation& info, Vector<ExpressionType>& args, ExpressionType& result)
+bool B3IRGenerator::addCall(unsigned functionIndex, const Signature* signature, Vector<ExpressionType>& args, ExpressionType& result)
 {
-    ASSERT(info.signature->arguments.size() == args.size());
+    ASSERT(signature->arguments.size() == args.size());
 
-    Type returnType = info.signature->returnType;
+    Type returnType = signature->returnType;
 
-    size_t callIndex = m_unlinkedCalls.size();
-    m_unlinkedCalls.grow(callIndex + 1);
+    size_t callIndex = m_unlinkedWasmToWasmCalls.size();
+    m_unlinkedWasmToWasmCalls.grow(callIndex + 1);
     result = wasmCallingConvention().setupCall(m_proc, m_currentBlock, Origin(), args, toB3Type(returnType),
         [&] (PatchpointValue* patchpoint) {
             patchpoint->effects.writesPinned = true;
@@ -614,7 +613,7 @@ bool B3IRGenerator::addCall(unsigned functionIndex, const FunctionInformation& i
                 CCallHelpers::Call call = jit.call();
 
                 jit.addLinkTask([=] (LinkBuffer& linkBuffer) {
-                    m_unlinkedCalls[callIndex] = { linkBuffer.locationOf(call), functionIndex };
+                    m_unlinkedWasmToWasmCalls[callIndex] = { linkBuffer.locationOf(call), functionIndex };
                 });
             });
         });
@@ -660,7 +659,7 @@ void B3IRGenerator::dump(const Vector<ControlEntry>& controlStack, const Express
     dataLogLn("\n");
 }
 
-static std::unique_ptr<Compilation> createJSWrapper(VM& vm, const Signature* signature, MacroAssemblerCodePtr mainFunction, Memory* memory)
+static std::unique_ptr<Compilation> createJSToWasmWrapper(VM& vm, const Signature* signature, MacroAssemblerCodePtr mainFunction, Memory* memory)
 {
     Procedure proc;
     BasicBlock* block = proc.addBlock();
@@ -739,13 +738,13 @@ static std::unique_ptr<Compilation> createJSWrapper(VM& vm, const Signature* sig
     return std::make_unique<Compilation>(vm, proc);
 }
 
-std::unique_ptr<FunctionCompilation> parseAndCompile(VM& vm, const uint8_t* functionStart, size_t functionLength, Memory* memory, const Signature* signature, const Vector<FunctionInformation>& functions, unsigned optLevel)
+std::unique_ptr<WasmInternalFunction> parseAndCompile(VM& vm, const uint8_t* functionStart, size_t functionLength, Memory* memory, const Signature* signature, Vector<UnlinkedWasmToWasmCall>& unlinkedWasmToWasmCalls, const FunctionIndexSpace& functionIndexSpace, unsigned optLevel)
 {
-    auto result = std::make_unique<FunctionCompilation>();
+    auto result = std::make_unique<WasmInternalFunction>();
 
     Procedure procedure;
-    B3IRGenerator context(memory, procedure, result.get());
-    FunctionParser<B3IRGenerator> parser(context, functionStart, functionLength, signature, functions);
+    B3IRGenerator context(memory, procedure, result.get(), unlinkedWasmToWasmCalls);
+    FunctionParser<B3IRGenerator> parser(context, functionStart, functionLength, signature, functionIndexSpace);
     if (!parser.parse())
         RELEASE_ASSERT_NOT_REACHED();
 
@@ -759,7 +758,7 @@ std::unique_ptr<FunctionCompilation> parseAndCompile(VM& vm, const uint8_t* func
         dataLog("Post SSA: ", procedure);
 
     result->code = std::make_unique<Compilation>(vm, procedure, optLevel);
-    result->jsEntryPoint = createJSWrapper(vm, signature, result->code->code(), memory);
+    result->jsToWasmEntryPoint = createJSToWasmWrapper(vm, signature, result->code->code(), memory);
     return result;
 }
 
index 43ddb9e..794b5cc 100644 (file)
@@ -37,7 +37,7 @@ namespace JSC { namespace Wasm {
 
 class Memory;
 
-std::unique_ptr<FunctionCompilation> parseAndCompile(VM&, const uint8_t*, size_t, Memory*, const Signature*, const Vector<FunctionInformation>&, unsigned optLevel = 1);
+std::unique_ptr<WasmInternalFunction> parseAndCompile(VM&, const uint8_t*, size_t, Memory*, const Signature*, Vector<UnlinkedWasmToWasmCall>&, const FunctionIndexSpace&, unsigned optLevel = 1);
 
 } } // namespace JSC::Wasm
 
diff --git a/Source/JavaScriptCore/wasm/WasmBinding.cpp b/Source/JavaScriptCore/wasm/WasmBinding.cpp
new file mode 100644 (file)
index 0000000..136c65c
--- /dev/null
@@ -0,0 +1,238 @@
+/*
+ * Copyright (C) 2016 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 "WasmBinding.h"
+
+#if ENABLE(WEBASSEMBLY)
+
+#include "AssemblyHelpers.h"
+#include "JSCJSValueInlines.h"
+#include "JSWebAssemblyInstance.h"
+#include "LinkBuffer.h"
+#include "WasmCallingConvention.h"
+
+namespace JSC { namespace Wasm {
+
+WasmToJSStub importStubGenerator(VM* vm, Bag<CallLinkInfo>& callLinkInfos, Signature* signature, unsigned importIndex)
+{
+    const WasmCallingConvention& wasmCC = wasmCallingConvention();
+    const JSCCallingConvention& jsCC = jscCallingConvention();
+    unsigned argCount = signature->arguments.size();
+    typedef AssemblyHelpers JIT;
+    JIT jit(vm, nullptr);
+
+    // Below, we assume that the JS calling convention is always on the stack.
+    ASSERT(!jsCC.m_gprArgs.size());
+    ASSERT(!jsCC.m_fprArgs.size());
+
+    jit.emitFunctionPrologue();
+    jit.breakpoint(); // FIXME make calling to JavaScript work. https://bugs.webkit.org/show_bug.cgi?id=165591
+    jit.store64(JIT::TrustedImm32(0), JIT::Address(GPRInfo::callFrameRegister, CallFrameSlot::codeBlock * static_cast<int>(sizeof(Register)))); // FIXME Stop using 0 as codeBlocks. https://bugs.webkit.org/show_bug.cgi?id=165321
+    jit.storePtr(JIT::TrustedImmPtr(vm->webAssemblyToJSCallee.get()), JIT::Address(GPRInfo::callFrameRegister, CallFrameSlot::callee * static_cast<int>(sizeof(Register))));
+
+    // Here we assume that the JS calling convention saves at least all the wasm callee saved. We therefore don't need to save and restore more registers since the wasm callee already took care of this.
+    RegisterSet missingCalleeSaves = wasmCC.m_calleeSaveRegisters;
+    missingCalleeSaves.exclude(jsCC.m_calleeSaveRegisters);
+    ASSERT(missingCalleeSaves.isEmpty());
+
+    // FIXME perform a stack check before updating SP. https://bugs.webkit.org/show_bug.cgi?id=165546
+
+    unsigned numberOfParameters = argCount + 1; // There is a "this" argument.
+    unsigned numberOfRegsForCall = CallFrame::headerSizeInRegisters + numberOfParameters;
+    unsigned numberOfBytesForCall = numberOfRegsForCall * sizeof(Register) - sizeof(CallerFrameAndPC);
+    const unsigned stackOffset = WTF::roundUpToMultipleOf(stackAlignmentBytes(), numberOfBytesForCall);
+    jit.subPtr(MacroAssembler::TrustedImm32(stackOffset), MacroAssembler::stackPointerRegister);
+    JIT::Address calleeFrame = CCallHelpers::Address(MacroAssembler::stackPointerRegister, -static_cast<ptrdiff_t>(sizeof(CallerFrameAndPC)));
+
+    // FIXME make this a loop which switches on Signature if there are many arguments on the stack. It'll otherwise be huge for huge signatures. https://bugs.webkit.org/show_bug.cgi?id=165547
+    unsigned marshalledGPRs = 0;
+    unsigned marshalledFPRs = 0;
+    unsigned calleeFrameOffset = CallFrameSlot::firstArgument * static_cast<int>(sizeof(Register));
+    unsigned frOffset = CallFrameSlot::firstArgument * static_cast<int>(sizeof(Register));
+    for (unsigned argNum = 0; argNum < argCount; ++argNum) {
+        Type argType = signature->arguments[argNum];
+        switch (argType) {
+        case Void:
+        case Func:
+        case Anyfunc:
+        case I64:
+            // For the JavaScript embedding, imports with these types in their signature arguments are a WebAssembly.Module validation error.
+            RELEASE_ASSERT_NOT_REACHED();
+            break;
+        case I32: {
+            GPRReg gprReg;
+            if (marshalledGPRs < wasmCC.m_gprArgs.size())
+                gprReg = wasmCC.m_gprArgs[marshalledGPRs].gpr();
+            else {
+                // We've already spilled all arguments, these registers are available as scratch.
+                gprReg = GPRInfo::argumentGPR0;
+                jit.load64(JIT::Address(GPRInfo::callFrameRegister, frOffset), gprReg);
+                frOffset += sizeof(Register);
+            }
+            ++marshalledGPRs;
+            jit.boxInt32(gprReg, JSValueRegs(gprReg), DoNotHaveTagRegisters);
+            jit.store64(gprReg, calleeFrame.withOffset(calleeFrameOffset));
+            calleeFrameOffset += sizeof(Register);
+            break;
+        }
+        case F32: {
+            FPRReg fprReg;
+            if (marshalledFPRs < wasmCC.m_fprArgs.size())
+                fprReg = wasmCC.m_fprArgs[marshalledFPRs].fpr();
+            else {
+                // We've already spilled all arguments, these registers are available as scratch.
+                fprReg = FPRInfo::argumentFPR0;
+                jit.loadFloat(JIT::Address(GPRInfo::callFrameRegister, frOffset), fprReg);
+                frOffset += sizeof(Register);
+            }
+            jit.convertFloatToDouble(fprReg, fprReg);
+            jit.purifyNaN(fprReg);
+            jit.storeDouble(fprReg, calleeFrame.withOffset(calleeFrameOffset));
+            calleeFrameOffset += sizeof(Register);
+            ++marshalledFPRs;
+            break;
+        }
+        case F64: {
+            FPRReg fprReg;
+            if (marshalledFPRs < wasmCC.m_fprArgs.size())
+                fprReg = wasmCC.m_fprArgs[marshalledFPRs].fpr();
+            else {
+                // We've already spilled all arguments, these registers are available as scratch.
+                fprReg = FPRInfo::argumentFPR0;
+                jit.loadDouble(JIT::Address(GPRInfo::callFrameRegister, frOffset), fprReg);
+                frOffset += sizeof(Register);
+            }
+            jit.purifyNaN(fprReg);
+            jit.storeDouble(fprReg, calleeFrame.withOffset(calleeFrameOffset));
+            calleeFrameOffset += sizeof(Register);
+            ++marshalledFPRs;
+            break;
+        }
+        }
+    }
+
+    GPRReg importJSCellGPRReg = GPRInfo::regT0; // Callee needs to be in regT0 for slow path below.
+    ASSERT(!wasmCC.m_calleeSaveRegisters.get(importJSCellGPRReg));
+
+    // Each JS -> wasm entry sets the WebAssembly.Instance whose export is being called. We're calling out of this Instance, and can therefore figure out the import being called.
+    jit.loadPtr(&vm->topJSWebAssemblyInstance, importJSCellGPRReg);
+    jit.loadPtr(JIT::Address(importJSCellGPRReg, JSWebAssemblyInstance::offsetOfImportFunction(importIndex)), importJSCellGPRReg);
+
+    uint64_t thisArgument = ValueUndefined; // FIXME what does the WebAssembly spec say this should be? https://bugs.webkit.org/show_bug.cgi?id=165471
+    jit.store64(importJSCellGPRReg, calleeFrame.withOffset(CallFrameSlot::callee * static_cast<int>(sizeof(Register))));
+    jit.store32(JIT::TrustedImm32(numberOfParameters), calleeFrame.withOffset(CallFrameSlot::argumentCount * static_cast<int>(sizeof(Register)) + PayloadOffset));
+    jit.store64(JIT::TrustedImm64(thisArgument), calleeFrame.withOffset(CallFrameSlot::thisArgument * static_cast<int>(sizeof(Register))));
+
+    // FIXME Tail call if the wasm return type is void and no registers were spilled. https://bugs.webkit.org/show_bug.cgi?id=165488
+
+    CallLinkInfo* callLinkInfo = callLinkInfos.add();
+    callLinkInfo->setUpCall(CallLinkInfo::Call, CodeOrigin(), importJSCellGPRReg);
+    JIT::DataLabelPtr targetToCheck;
+    JIT::TrustedImmPtr initialRightValue(0);
+    JIT::Jump slowPath = jit.branchPtrWithPatch(MacroAssembler::NotEqual, importJSCellGPRReg, targetToCheck, initialRightValue);
+    JIT::Call fastCall = jit.nearCall();
+    JIT::Jump done = jit.jump();
+    slowPath.link(&jit);
+    // Callee needs to be in regT0 here.
+    jit.move(MacroAssembler::TrustedImmPtr(callLinkInfo), GPRInfo::regT2); // Link info needs to be in regT2.
+    JIT::Call slowCall = jit.nearCall();
+    done.link(&jit);
+
+    switch (signature->returnType) {
+    case Void:
+        // Discard.
+        break;
+    case Func:
+    case Anyfunc:
+        // For the JavaScript embedding, imports with these types in their signature return are a WebAssembly.Module validation error.
+        RELEASE_ASSERT_NOT_REACHED();
+        break;
+    case I32: {
+        jit.move(JIT::TrustedImm64(TagTypeNumber), GPRInfo::returnValueGPR2);
+        JIT::Jump checkJSInt32 = jit.branch64(JIT::AboveOrEqual, GPRInfo::returnValueGPR, GPRInfo::returnValueGPR2);
+        jit.move64ToDouble(GPRInfo::returnValueGPR, FPRInfo::returnValueFPR);
+        jit.truncateDoubleToInt32(FPRInfo::returnValueFPR, GPRInfo::returnValueGPR);
+        JIT::Jump checkJSNumber = jit.branchTest64(JIT::NonZero, GPRInfo::returnValueGPR, GPRInfo::returnValueGPR2);
+        jit.abortWithReason(AHIsNotJSNumber); // FIXME Coerce when the values aren't what we expect, instead of aborting. https://bugs.webkit.org/show_bug.cgi?id=165480
+        checkJSInt32.link(&jit);
+        jit.zeroExtend32ToPtr(GPRInfo::returnValueGPR, GPRInfo::returnValueGPR);
+        checkJSNumber.link(&jit);
+        break;
+    }
+    case I64: {
+        jit.move(JIT::TrustedImm64(TagTypeNumber), GPRInfo::returnValueGPR2);
+        JIT::Jump checkJSInt32 = jit.branch64(JIT::AboveOrEqual, GPRInfo::returnValueGPR, GPRInfo::returnValueGPR2);
+        jit.move64ToDouble(GPRInfo::returnValueGPR, FPRInfo::returnValueFPR);
+        jit.truncateDoubleToInt64(FPRInfo::returnValueFPR, GPRInfo::returnValueGPR);
+        JIT::Jump checkJSNumber = jit.branchTest64(JIT::NonZero, GPRInfo::returnValueGPR, GPRInfo::returnValueGPR2);
+        jit.abortWithReason(AHIsNotJSNumber); // FIXME Coerce when the values aren't what we expect, instead of aborting. https://bugs.webkit.org/show_bug.cgi?id=165480
+        checkJSInt32.link(&jit);
+        jit.zeroExtend32ToPtr(GPRInfo::returnValueGPR, GPRInfo::returnValueGPR);
+        checkJSNumber.link(&jit);
+        break;
+    }
+    case F32: {
+        jit.move(JIT::TrustedImm64(TagTypeNumber), GPRInfo::returnValueGPR2);
+        jit.move64ToDouble(GPRInfo::returnValueGPR, FPRInfo::returnValueFPR);
+        jit.convertDoubleToFloat(FPRInfo::returnValueFPR, FPRInfo::returnValueFPR);
+        JIT::Jump checkJSInt32 = jit.branch64(JIT::AboveOrEqual, GPRInfo::returnValueGPR, GPRInfo::returnValueGPR2);
+        JIT::Jump checkJSNumber = jit.branchTest64(JIT::NonZero, GPRInfo::returnValueGPR, GPRInfo::returnValueGPR2);
+        jit.abortWithReason(AHIsNotJSNumber); // FIXME Coerce when the values aren't what we expect, instead of aborting. https://bugs.webkit.org/show_bug.cgi?id=165480
+        checkJSInt32.link(&jit);
+        jit.zeroExtend32ToPtr(GPRInfo::returnValueGPR, GPRInfo::returnValueGPR);
+        jit.convertInt64ToFloat(GPRInfo::returnValueGPR, FPRInfo::returnValueFPR);
+        checkJSNumber.link(&jit);
+        break;
+    }
+    case F64: {
+        jit.move(JIT::TrustedImm64(TagTypeNumber), GPRInfo::returnValueGPR2);
+        jit.move64ToDouble(GPRInfo::returnValueGPR, FPRInfo::returnValueFPR);
+        JIT::Jump checkJSInt32 = jit.branch64(JIT::AboveOrEqual, GPRInfo::returnValueGPR, GPRInfo::returnValueGPR2);
+        JIT::Jump checkJSNumber = jit.branchTest64(JIT::NonZero, GPRInfo::returnValueGPR, GPRInfo::returnValueGPR2);
+        jit.abortWithReason(AHIsNotJSNumber); // FIXME Coerce when the values aren't what we expect, instead of aborting. https://bugs.webkit.org/show_bug.cgi?id=165480
+        checkJSInt32.link(&jit);
+        jit.zeroExtend32ToPtr(GPRInfo::returnValueGPR, GPRInfo::returnValueGPR);
+        jit.convertInt64ToDouble(GPRInfo::returnValueGPR, FPRInfo::returnValueFPR);
+        checkJSNumber.link(&jit);
+        break;
+    }
+    }
+
+    jit.emitFunctionEpilogue();
+    jit.ret();
+
+    LinkBuffer patchBuffer(*vm, jit, GLOBAL_THUNK_ID);
+    patchBuffer.link(slowCall, FunctionPtr(vm->getCTIStub(linkCallThunkGenerator).code().executableAddress()));
+    CodeLocationLabel callReturnLocation(patchBuffer.locationOfNearCall(slowCall));
+    CodeLocationLabel hotPathBegin(patchBuffer.locationOf(targetToCheck));
+    CodeLocationNearCall hotPathOther = patchBuffer.locationOfNearCall(fastCall);
+    callLinkInfo->setCallLocations(callReturnLocation, hotPathBegin, hotPathOther);
+    return FINALIZE_CODE(patchBuffer, ("WebAssembly import[%i] stub for signature %p", importIndex, signature));
+}
+
+} } // namespace JSC::Wasm
+
+#endif // ENABLE(WEBASSEMBLY)
diff --git a/Source/JavaScriptCore/wasm/WasmBinding.h b/Source/JavaScriptCore/wasm/WasmBinding.h
new file mode 100644 (file)
index 0000000..9fe3fdb
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2016 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 "B3Compilation.h"
+#include "VM.h"
+#include "WasmFormat.h"
+#include <wtf/Bag.h>
+
+namespace JSC {
+
+class CallLinkInfo;
+
+namespace Wasm {
+
+WasmToJSStub importStubGenerator(VM*, Bag<CallLinkInfo>&, Signature*, unsigned);
+
+} } // namespace JSC::Wasm
+
+#endif // ENABLE(WEBASSEMBLY)
index 5c2a512..d7ebd80 100644 (file)
@@ -83,7 +83,7 @@ private:
     }
 
 public:
-    void setupFrameInPrologue(FunctionCompilation* compilation, B3::Procedure& proc, B3::Origin origin, B3::BasicBlock* block) const
+    void setupFrameInPrologue(WasmInternalFunction* compilation, B3::Procedure& proc, B3::Origin origin, B3::BasicBlock* block) const
     {
         static_assert(CallFrameSlot::callee * sizeof(Register) < headerSize, "We rely on this here for now.");
         static_assert(CallFrameSlot::codeBlock * sizeof(Register) < headerSize, "We rely on this here for now.");
index c8bd180..43b119a 100644 (file)
@@ -31,6 +31,7 @@
 #include "B3Type.h"
 #include "CodeLocation.h"
 #include "Identifier.h"
+#include "MacroAssemblerCodeRef.h"
 #include "WasmOps.h"
 #include <wtf/Vector.h>
 
@@ -91,18 +92,7 @@ struct Import {
     Identifier module;
     Identifier field;
     External::Kind kind;
-    union {
-        Signature* functionSignature;
-        // FIXME implement Table https://bugs.webkit.org/show_bug.cgi?id=164135
-        // FIXME implement Memory https://bugs.webkit.org/show_bug.cgi?id=164134
-        // FIXME implement Global https://bugs.webkit.org/show_bug.cgi?id=164133
-    };
-};
-
-struct FunctionInformation {
-    Signature* signature;
-    size_t start;
-    size_t end;
+    unsigned kindIndex; // Index in the vector of the corresponding kind.
 };
 
 class Memory;
@@ -118,29 +108,51 @@ struct Export {
     };
 };
 
+struct FunctionLocationInBinary {
+    size_t start;
+    size_t end;
+};
+
+
 struct ModuleInformation {
     Vector<Signature> signatures;
     Vector<Import> imports;
-    Vector<FunctionInformation> functions;
+    Vector<Signature*> importFunctions;
+    // FIXME implement import Table https://bugs.webkit.org/show_bug.cgi?id=164135
+    // FIXME implement import Memory https://bugs.webkit.org/show_bug.cgi?id=164134
+    // FIXME implement import Global https://bugs.webkit.org/show_bug.cgi?id=164133
+    Vector<Signature*> internalFunctionSignatures;
     std::unique_ptr<Memory> memory;
     Vector<Export> exports;
 
     ~ModuleInformation();
 };
 
-struct UnlinkedCall {
+struct UnlinkedWasmToWasmCall {
     CodeLocationCall callLocation;
     size_t functionIndex;
 };
 
-struct FunctionCompilation {
-    Vector<UnlinkedCall> unlinkedCalls;
+struct WasmInternalFunction {
     CodeLocationDataLabelPtr calleeMoveLocation;
     std::unique_ptr<B3::Compilation> code;
-    std::unique_ptr<B3::Compilation> jsEntryPoint;
+    std::unique_ptr<B3::Compilation> jsToWasmEntryPoint;
 };
 
-typedef Vector<std::unique_ptr<FunctionCompilation>> CompiledFunctions;
+typedef MacroAssemblerCodeRef WasmToJSStub;
+
+// WebAssembly direct calls and call_indirect use indices into "function index space". This space starts with all imports, and then all internal functions.
+// CallableFunction and FunctionIndexSpace are only meant as fast lookup tables for these opcodes, and do not own code.
+struct CallableFunction {
+    CallableFunction(Signature* signature)
+        : signature(signature)
+        , code(nullptr)
+    {
+    }
+    Signature* signature; // FIXME pack this inside a (uniqued) integer (for correctness the parser should unique Signatures), and then pack that integer into the code pointer. https://bugs.webkit.org/show_bug.cgi?id=165511
+    void* code;
+};
+typedef Vector<CallableFunction> FunctionIndexSpace;
 
 } } // namespace JSC::Wasm
 
index e621125..ec19325 100644 (file)
@@ -45,7 +45,7 @@ public:
     typedef typename Context::ControlType ControlType;
     typedef typename Context::ExpressionList ExpressionList;
 
-    FunctionParser(Context&, const uint8_t* functionStart, size_t functionLength, const Signature*, const Vector<FunctionInformation>& functions);
+    FunctionParser(Context&, const uint8_t* functionStart, size_t functionLength, const Signature*, const FunctionIndexSpace&);
 
     bool WARN_UNUSED_RETURN parse();
 
@@ -77,16 +77,16 @@ private:
     ExpressionList m_expressionStack;
     Vector<ControlEntry> m_controlStack;
     const Signature* m_signature;
-    const Vector<FunctionInformation>& m_functions;
+    const FunctionIndexSpace& m_functionIndexSpace;
     unsigned m_unreachableBlocks { 0 };
 };
 
 template<typename Context>
-FunctionParser<Context>::FunctionParser(Context& context, const uint8_t* functionStart, size_t functionLength, const Signature* signature, const Vector<FunctionInformation>& functions)
+FunctionParser<Context>::FunctionParser(Context& context, const uint8_t* functionStart, size_t functionLength, const Signature* signature, const FunctionIndexSpace& functionIndexSpace)
     : Parser(functionStart, functionLength)
     , m_context(context)
     , m_signature(signature)
-    , m_functions(functions)
+    , m_functionIndexSpace(functionIndexSpace)
 {
     if (verbose)
         dataLogLn("Parsing function starting at: ", (uintptr_t)functionStart, " of length: ", functionLength);
@@ -350,23 +350,23 @@ bool FunctionParser<Context>::parseExpression(OpType op)
         if (!parseVarUInt32(functionIndex))
             return false;
 
-        if (functionIndex >= m_functions.size())
+        if (functionIndex >= m_functionIndexSpace.size())
             return false;
 
-        const FunctionInformation& info = m_functions[functionIndex];
+        const Signature* calleeSignature = m_functionIndexSpace[functionIndex].signature;
 
-        if (info.signature->arguments.size() > m_expressionStack.size())
+        if (calleeSignature->arguments.size() > m_expressionStack.size())
             return false;
 
-        size_t firstArgumentIndex = m_expressionStack.size() - info.signature->arguments.size();
+        size_t firstArgumentIndex = m_expressionStack.size() - calleeSignature->arguments.size();
         Vector<ExpressionType> args;
-        args.reserveInitialCapacity(info.signature->arguments.size());
+        args.reserveInitialCapacity(calleeSignature->arguments.size());
         for (unsigned i = firstArgumentIndex; i < m_expressionStack.size(); ++i)
             args.append(m_expressionStack[i]);
         m_expressionStack.shrink(firstArgumentIndex);
 
         ExpressionType result = Context::emptyExpression;
-        if (!m_context.addCall(functionIndex, info, args, result))
+        if (!m_context.addCall(functionIndex, calleeSignature, args, result))
             return false;
 
         if (result != Context::emptyExpression)
index 88d08ee..af133a4 100644 (file)
@@ -218,23 +218,23 @@ bool ModuleParser::parseImport()
     uint32_t importCount;
     if (!parseVarUInt32(importCount))
         return false;
-    if (!m_module->imports.tryReserveCapacity(importCount))
+    if (!m_module->imports.tryReserveCapacity(importCount) // FIXME this over-allocates when we fix the FIXMEs below.
+        || !m_module->importFunctions.tryReserveCapacity(importCount) // FIXME this over-allocates when we fix the FIXMEs below.
+        || !m_functionIndexSpace.tryReserveCapacity(importCount)) // FIXME this over-allocates when we fix the FIXMEs below. We'll allocate some more here when we know how many functions to expect.
         return false;
 
     for (uint32_t importNumber = 0; importNumber != importCount; ++importNumber) {
         Import imp;
         uint32_t moduleLen;
         uint32_t fieldLen;
-        if (!parseVarUInt32(moduleLen))
-            return false;
         String moduleString;
-        if (!consumeUTF8String(moduleString, moduleLen))
+        String fieldString;
+        if (!parseVarUInt32(moduleLen)
+            || !consumeUTF8String(moduleString, moduleLen))
             return false;
         imp.module = Identifier::fromString(m_vm, moduleString);
-        if (!parseVarUInt32(fieldLen))
-            return false;
-        String fieldString;
-        if (!consumeUTF8String(fieldString, fieldLen))
+        if (!parseVarUInt32(fieldLen)
+            || !consumeUTF8String(fieldString, fieldLen))
             return false;
         imp.field = Identifier::fromString(m_vm, fieldString);
         if (!parseExternalKind(imp.kind))
@@ -242,11 +242,13 @@ bool ModuleParser::parseImport()
         switch (imp.kind) {
         case External::Function: {
             uint32_t functionSignatureIndex;
-            if (!parseVarUInt32(functionSignatureIndex))
-                return false;
-            if (functionSignatureIndex >= m_module->signatures.size())
+            if (!parseVarUInt32(functionSignatureIndex)
+                || functionSignatureIndex >= m_module->signatures.size())
                 return false;
-            imp.functionSignature = &m_module->signatures[functionSignatureIndex];
+            imp.kindIndex = m_module->importFunctions.size();
+            Signature* signature = &m_module->signatures[functionSignatureIndex];
+            m_module->importFunctions.uncheckedAppend(signature);
+            m_functionIndexSpace.uncheckedAppend(signature);
             break;
         }
         case External::Table: {
@@ -273,23 +275,25 @@ bool ModuleParser::parseImport()
 bool ModuleParser::parseFunction()
 {
     uint32_t count;
-    if (!parseVarUInt32(count))
-        return false;
-    if (!m_module->functions.tryReserveCapacity(count))
+    if (!parseVarUInt32(count)
+        || !m_module->internalFunctionSignatures.tryReserveCapacity(count)
+        || !m_functionLocationInBinary.tryReserveCapacity(count)
+        || !m_functionIndexSpace.tryReserveCapacity(m_functionIndexSpace.size() + count))
         return false;
 
     for (uint32_t i = 0; i != count; ++i) {
         uint32_t typeNumber;
-        if (!parseVarUInt32(typeNumber))
-            return false;
-
-        if (typeNumber >= m_module->signatures.size())
+        if (!parseVarUInt32(typeNumber)
+            || typeNumber >= m_module->signatures.size())
             return false;
 
+        Signature* signature = &m_module->signatures[typeNumber];
         // The Code section fixes up start and end.
         size_t start = 0;
         size_t end = 0;
-        m_module->functions.uncheckedAppend({ &m_module->signatures[typeNumber], start, end });
+        m_module->internalFunctionSignatures.uncheckedAppend(signature);
+        m_functionLocationInBinary.uncheckedAppend({ start, end });
+        m_functionIndexSpace.uncheckedAppend(signature);
     }
 
     return true;
@@ -311,20 +315,17 @@ bool ModuleParser::parseMemory()
         return true;
 
     uint8_t flags;
-    if (!parseVarUInt1(flags))
-        return false;
-
     uint32_t size;
-    if (!parseVarUInt32(size))
-        return false;
-    if (size > maxPageCount)
+    if (!parseVarUInt1(flags)
+        || !parseVarUInt32(size)
+        || size > maxPageCount)
         return false;
 
     uint32_t capacity = maxPageCount;
     if (flags) {
-        if (!parseVarUInt32(capacity))
-            return false;
-        if (size > capacity || capacity > maxPageCount)
+        if (!parseVarUInt32(capacity)
+            || size > capacity
+            || capacity > maxPageCount)
             return false;
     }
 
@@ -345,27 +346,24 @@ bool ModuleParser::parseGlobal()
 bool ModuleParser::parseExport()
 {
     uint32_t exportCount;
-    if (!parseVarUInt32(exportCount))
-        return false;
-    if (!m_module->exports.tryReserveCapacity(exportCount))
+    if (!parseVarUInt32(exportCount)
+        || !m_module->exports.tryReserveCapacity(exportCount))
         return false;
 
     for (uint32_t exportNumber = 0; exportNumber != exportCount; ++exportNumber) {
         Export exp;
         uint32_t fieldLen;
-        if (!parseVarUInt32(fieldLen))
-            return false;
         String fieldString;
-        if (!consumeUTF8String(fieldString, fieldLen))
+        if (!parseVarUInt32(fieldLen)
+            || !consumeUTF8String(fieldString, fieldLen))
             return false;
         exp.field = Identifier::fromString(m_vm, fieldString);
         if (!parseExternalKind(exp.kind))
             return false;
         switch (exp.kind) {
         case External::Function: {
-            if (!parseVarUInt32(exp.functionIndex))
-                return false;
-            if (exp.functionIndex >= m_module->functions.size())
+            if (!parseVarUInt32(exp.functionIndex)
+                || exp.functionIndex >= m_functionIndexSpace.size())
                 return false;
             break;
         }
@@ -405,23 +403,20 @@ bool ModuleParser::parseElement()
 bool ModuleParser::parseCode()
 {
     uint32_t count;
-    if (!parseVarUInt32(count))
-        return false;
-
-    if (count != m_module->functions.size())
+    if (!parseVarUInt32(count)
+        || count != m_functionLocationInBinary.size())
         return false;
 
     for (uint32_t i = 0; i != count; ++i) {
         uint32_t functionSize;
-        if (!parseVarUInt32(functionSize))
-            return false;
-        if (functionSize > length() || functionSize > length() - m_offset)
+        if (!parseVarUInt32(functionSize)
+            || functionSize > length()
+            || functionSize > length() - m_offset)
             return false;
 
-        FunctionInformation& info = m_module->functions[i];
-        info.start = m_offset;
-        info.end = m_offset + functionSize;
-        m_offset = info.end;
+        m_functionLocationInBinary[i].start = m_offset;
+        m_functionLocationInBinary[i].end = m_offset + functionSize;
+        m_offset = m_functionLocationInBinary[i].end;
     }
 
     return true;
index 58a24d6..9262994 100644 (file)
@@ -61,6 +61,18 @@ public:
         return m_module;
     }
 
+    FunctionIndexSpace& functionIndexSpace()
+    {
+        RELEASE_ASSERT(!failed());
+        return m_functionIndexSpace;
+    }
+
+    Vector<FunctionLocationInBinary>& functionLocationInBinary()
+    {
+        RELEASE_ASSERT(!failed());
+        return m_functionLocationInBinary;
+    }
+
 private:
 #define WASM_SECTION_DECLARE_PARSER(NAME, ID, DESCRIPTION) bool WARN_UNUSED_RETURN parse ## NAME();
     FOR_EACH_WASM_SECTION(WASM_SECTION_DECLARE_PARSER)
@@ -68,6 +80,8 @@ private:
 
     VM* m_vm;
     std::unique_ptr<ModuleInformation> m_module;
+    FunctionIndexSpace m_functionIndexSpace;
+    Vector<FunctionLocationInBinary> m_functionLocationInBinary;
     bool m_failed { true };
     String m_errorMessage;
 };
index cbd67b3..eee39b4 100644 (file)
@@ -102,7 +102,7 @@ ALWAYS_INLINE bool Parser::consumeString(const char* str)
 ALWAYS_INLINE bool Parser::consumeUTF8String(String& result, size_t stringLength)
 {
     if (stringLength == 0) {
-        result = String();
+        result = emptyString();
         return true;
     }
     if (length() < stringLength || m_offset > length() - stringLength)
index 0b07ca3..7a163d7 100644 (file)
 #include "JSGlobalObject.h"
 #include "JSWebAssemblyCallee.h"
 #include "WasmB3IRGenerator.h"
+#include "WasmBinding.h"
 #include "WasmCallingConvention.h"
 #include "WasmMemory.h"
 #include "WasmModuleParser.h"
 #include "WasmValidate.h"
 #include <wtf/DataLog.h>
+#include <wtf/StdLibExtras.h>
 #include <wtf/text/StringBuilder.h>
 
 namespace JSC { namespace Wasm {
@@ -69,27 +71,52 @@ void Plan::run()
             return;
         }
         m_moduleInformation = WTFMove(moduleParser.moduleInformation());
+        m_functionLocationInBinary = WTFMove(moduleParser.functionLocationInBinary());
+        m_functionIndexSpace = WTFMove(moduleParser.functionIndexSpace());
     }
     if (verbose)
         dataLogLn("Parsed module.");
 
-    if (!m_compiledFunctions.tryReserveCapacity(m_moduleInformation->functions.size())) {
-        StringBuilder builder;
-        builder.appendLiteral("Failed allocating enough space for ");
-        builder.appendNumber(m_moduleInformation->functions.size());
-        builder.appendLiteral(" compiled functions");
-        m_errorMessage = builder.toString();
+    auto tryReserveCapacity = [this] (auto& vector, size_t size, const char* what) {
+        if (UNLIKELY(!vector.tryReserveCapacity(size))) {
+            StringBuilder builder;
+            builder.appendLiteral("Failed allocating enough space for ");
+            builder.appendNumber(size);
+            builder.append(what);
+            m_errorMessage = builder.toString();
+            return false;
+        }
+        return true;
+    };
+    Vector<Vector<UnlinkedWasmToWasmCall>> unlinkedWasmToWasmCalls;
+    if (!tryReserveCapacity(m_wasmToJSStubs, m_moduleInformation->importFunctions.size(), " WebAssembly to JavaScript stubs")
+        || !tryReserveCapacity(unlinkedWasmToWasmCalls, m_functionLocationInBinary.size(), " unlinked WebAssembly to WebAssembly calls")
+        || !tryReserveCapacity(m_wasmInternalFunctions, m_functionLocationInBinary.size(), " WebAssembly functions"))
         return;
+
+    for (unsigned importIndex = 0; importIndex < m_moduleInformation->imports.size(); ++importIndex) {
+        Import* import = &m_moduleInformation->imports[importIndex];
+        if (import->kind != External::Function)
+            continue;
+        unsigned importFunctionIndex = m_wasmToJSStubs.size();
+        if (verbose)
+            dataLogLn("Processing import function number ", importFunctionIndex, ": ", import->module, ": ", import->field);
+        Signature* signature = m_moduleInformation->importFunctions.at(import->kindIndex);
+        m_wasmToJSStubs.uncheckedAppend(importStubGenerator(m_vm, m_callLinkInfos, signature, importFunctionIndex));
+        m_functionIndexSpace[importFunctionIndex].code = m_wasmToJSStubs[importFunctionIndex].code().executableAddress();
     }
 
-    for (const FunctionInformation& info : m_moduleInformation->functions) {
+    for (unsigned functionIndex = 0; functionIndex < m_functionLocationInBinary.size(); ++functionIndex) {
         if (verbose)
-            dataLogLn("Processing function starting at: ", info.start, " and ending at: ", info.end);
-        const uint8_t* functionStart = m_source + info.start;
-        size_t functionLength = info.end - info.start;
+            dataLogLn("Processing function starting at: ", m_functionLocationInBinary[functionIndex].start, " and ending at: ", m_functionLocationInBinary[functionIndex].end);
+        const uint8_t* functionStart = m_source + m_functionLocationInBinary[functionIndex].start;
+        size_t functionLength = m_functionLocationInBinary[functionIndex].end - m_functionLocationInBinary[functionIndex].start;
         ASSERT(functionLength <= m_sourceLength);
+        Signature* signature = m_moduleInformation->internalFunctionSignatures[functionIndex];
+        unsigned functionIndexSpace = m_wasmToJSStubs.size() + functionIndex;
+        ASSERT(m_functionIndexSpace[functionIndexSpace].signature == signature);
 
-        String error = validateFunction(functionStart, functionLength, info.signature, m_moduleInformation->functions);
+        String error = validateFunction(functionStart, functionLength, signature, m_functionIndexSpace);
         if (!error.isNull()) {
             if (verbose) {
                 for (unsigned i = 0; i < functionLength; ++i)
@@ -100,14 +127,15 @@ void Plan::run()
             return;
         }
 
-        m_compiledFunctions.uncheckedAppend(parseAndCompile(*m_vm, functionStart, functionLength, m_moduleInformation->memory.get(), info.signature, m_moduleInformation->functions));
+        unlinkedWasmToWasmCalls.uncheckedAppend(Vector<UnlinkedWasmToWasmCall>());
+        m_wasmInternalFunctions.uncheckedAppend(parseAndCompile(*m_vm, functionStart, functionLength, m_moduleInformation->memory.get(), signature, unlinkedWasmToWasmCalls.at(functionIndex), m_functionIndexSpace));
+        m_functionIndexSpace[functionIndexSpace].code = m_wasmInternalFunctions[functionIndex]->code->code().executableAddress();
     }
 
-    // Patch the call sites for each function.
-    for (std::unique_ptr<FunctionCompilation>& functionPtr : m_compiledFunctions) {
-        FunctionCompilation* function = functionPtr.get();
-        for (auto& call : function->unlinkedCalls)
-            MacroAssembler::repatchCall(call.callLocation, CodeLocationLabel(m_compiledFunctions[call.functionIndex]->code->code()));
+    // Patch the call sites for each WebAssembly function.
+    for (auto& unlinked : unlinkedWasmToWasmCalls) {
+        for (auto& call : unlinked)
+            MacroAssembler::repatchCall(call.callLocation, CodeLocationLabel(m_functionIndexSpace[call.functionIndex].code));
     }
 
     m_failed = false;
@@ -116,17 +144,17 @@ void Plan::run()
 void Plan::initializeCallees(JSGlobalObject* globalObject, std::function<void(unsigned, JSWebAssemblyCallee*)> callback)
 {
     ASSERT(!failed());
-    for (unsigned i = 0; i < m_compiledFunctions.size(); i++) {
-        std::unique_ptr<FunctionCompilation>& compilation = m_compiledFunctions[i];
-        CodeLocationDataLabelPtr calleeMoveLocation = compilation->calleeMoveLocation;
-        JSWebAssemblyCallee* callee = JSWebAssemblyCallee::create(globalObject->vm(), WTFMove(compilation));
+    for (unsigned internalFunctionIndex = 0; internalFunctionIndex < m_wasmInternalFunctions.size(); ++internalFunctionIndex) {
+        WasmInternalFunction* function = m_wasmInternalFunctions[internalFunctionIndex].get();
+        CodeLocationDataLabelPtr calleeMoveLocation = function->calleeMoveLocation;
+        JSWebAssemblyCallee* callee = JSWebAssemblyCallee::create(globalObject->vm(), WTFMove(function->code), WTFMove(function->jsToWasmEntryPoint));
 
         MacroAssembler::repatchPointer(calleeMoveLocation, callee);
 
         if (verbose)
             dataLogLn("Made Wasm callee: ", RawPointer(callee));
 
-        callback(i, callee);
+        callback(internalFunctionIndex, callee);
     }
 }
 
index 63b49cc..7749270 100644 (file)
 #include "CompilationResult.h"
 #include "VM.h"
 #include "WasmFormat.h"
+#include <wtf/Bag.h>
 #include <wtf/ThreadSafeRefCounted.h>
 #include <wtf/Vector.h>
 
 namespace JSC {
 
+class CallLinkInfo;
 class JSGlobalObject;
 class JSWebAssemblyCallee;
 
@@ -58,31 +60,61 @@ public:
         RELEASE_ASSERT(failed());
         return m_errorMessage;
     }
-    
-    std::unique_ptr<ModuleInformation>& getModuleInformation()
+
+    Vector<Export>& exports() const
     {
         RELEASE_ASSERT(!failed());
-        return m_moduleInformation;
+        return m_moduleInformation->exports;
     }
+
     const Memory* memory() const
     {
         RELEASE_ASSERT(!failed());
         return m_moduleInformation->memory.get();
     }
-    size_t compiledFunctionCount() const
+
+    size_t internalFunctionCount() const
+    {
+        RELEASE_ASSERT(!failed());
+        return m_wasmInternalFunctions.size();
+    }
+    B3::Compilation* jsToWasmEntryPointForFunction(size_t i) const
+    {
+        ASSERT(i > m_wasmToJSStubs.size());
+        return m_wasmInternalFunctions.at(i - m_wasmToJSStubs.size())->jsToWasmEntryPoint.get();
+    }
+
+    std::unique_ptr<ModuleInformation>&& takeModuleInformation()
+    {
+        RELEASE_ASSERT(!failed());
+        return WTFMove(m_moduleInformation);
+    }
+
+    Bag<CallLinkInfo>&& takeCallLinkInfos()
     {
         RELEASE_ASSERT(!failed());
-        return m_compiledFunctions.size();
+        return WTFMove(m_callLinkInfos);
     }
-    const FunctionCompilation* compiledFunction(size_t i) const
+
+    Vector<WasmToJSStub>&& takeWasmToJSStubs()
+    {
+        RELEASE_ASSERT(!failed());
+        return WTFMove(m_wasmToJSStubs);
+    }
+
+    FunctionIndexSpace&& takeFunctionIndexSpace()
     {
         RELEASE_ASSERT(!failed());
-        return m_compiledFunctions.at(i).get();
+        return WTFMove(m_functionIndexSpace);
     }
 
 private:
     std::unique_ptr<ModuleInformation> m_moduleInformation;
-    CompiledFunctions m_compiledFunctions;
+    Vector<FunctionLocationInBinary> m_functionLocationInBinary;
+    Bag<CallLinkInfo> m_callLinkInfos;
+    Vector<WasmToJSStub> m_wasmToJSStubs;
+    Vector<std::unique_ptr<WasmInternalFunction>> m_wasmInternalFunctions;
+    FunctionIndexSpace m_functionIndexSpace;
 
     VM* m_vm;
     const uint8_t* m_source;
index 0409b6d..e14162b 100644 (file)
@@ -111,7 +111,7 @@ public:
     bool WARN_UNUSED_RETURN addEndToUnreachable(ControlEntry&);
 
 
-    bool WARN_UNUSED_RETURN addCall(unsigned calleeIndex, const FunctionInformation&, const Vector<ExpressionType>& args, ExpressionType& result);
+    bool WARN_UNUSED_RETURN addCall(unsigned calleeIndex, const Signature*, const Vector<ExpressionType>& args, ExpressionType& result);
 
     void dump(const Vector<ControlEntry>& controlStack, const ExpressionList& expressionStack);
 
@@ -320,12 +320,12 @@ bool Validate::addEndToUnreachable(ControlEntry& entry)
     return true;
 }
 
-bool Validate::addCall(unsigned, const FunctionInformation& info, const Vector<ExpressionType>& args, ExpressionType& result)
+bool Validate::addCall(unsigned, const Signature* signature, const Vector<ExpressionType>& args, ExpressionType& result)
 {
-    if (info.signature->arguments.size() != args.size()) {
+    if (signature->arguments.size() != args.size()) {
         StringBuilder builder;
         builder.append("Arity mismatch in call, expected: ");
-        builder.appendNumber(info.signature->arguments.size());
+        builder.appendNumber(signature->arguments.size());
         builder.append(" but got: ");
         builder.appendNumber(args.size());
         m_errorMessage = builder.toString();
@@ -333,13 +333,13 @@ bool Validate::addCall(unsigned, const FunctionInformation& info, const Vector<E
     }
 
     for (unsigned i = 0; i < args.size(); ++i) {
-        if (args[i] != info.signature->arguments[i]) {
-            m_errorMessage = makeString("Expected argument type: ", toString(info.signature->arguments[i]), " does not match passed argument type: ", toString(args[i]));
+        if (args[i] != signature->arguments[i]) {
+            m_errorMessage = makeString("Expected argument type: ", toString(signature->arguments[i]), " does not match passed argument type: ", toString(args[i]));
             return false;
         }
     }
 
-    result = info.signature->returnType;
+    result = signature->returnType;
     return true;
 }
 
@@ -367,10 +367,10 @@ void Validate::dump(const Vector<ControlEntry>&, const ExpressionList&)
     // Think of this as penance for the sin of bad error messages.
 }
 
-String validateFunction(const uint8_t* source, size_t length, const Signature* signature, const Vector<FunctionInformation>& functions)
+String validateFunction(const uint8_t* source, size_t length, const Signature* signature, const FunctionIndexSpace& functionIndexSpace)
 {
     Validate context(signature->returnType);
-    FunctionParser<Validate> validator(context, source, length, signature, functions);
+    FunctionParser<Validate> validator(context, source, length, signature, functionIndexSpace);
     if (!validator.parse()) {
         // FIXME: add better location information here. see: https://bugs.webkit.org/show_bug.cgi?id=164288
         // FIXME: We should never not have an error message if we return false.
index 76124f0..df43fa5 100644 (file)
@@ -31,7 +31,7 @@
 
 namespace JSC { namespace Wasm {
 
-String validateFunction(const uint8_t*, size_t, const Signature*, const Vector<FunctionInformation>&);
+String validateFunction(const uint8_t*, size_t, const Signature*, const FunctionIndexSpace&);
 
 } } // namespace JSC::Wasm
 
index 497ae88..39b1005 100644 (file)
@@ -38,12 +38,12 @@ JSWebAssemblyCallee::JSWebAssemblyCallee(VM& vm)
     : Base(vm, vm.webAssemblyCalleeStructure.get())
 { }
 
-void JSWebAssemblyCallee::finishCreation(VM& vm, std::unique_ptr<Wasm::FunctionCompilation>&& compilation)
+void JSWebAssemblyCallee::finishCreation(VM& vm, std::unique_ptr<B3::Compilation>&& code, std::unique_ptr<B3::Compilation>&& jsToWasmEntryPoint)
 {
     Base::finishCreation(vm);
 
-    m_code = WTFMove(compilation->code);
-    m_jsEntryPoint = WTFMove(compilation->jsEntryPoint);
+    m_code = WTFMove(code);
+    m_jsToWasmEntryPoint = WTFMove(jsToWasmEntryPoint);
 }
 
 void JSWebAssemblyCallee::destroy(JSCell* cell)
index 8b3bad4..2be9952 100644 (file)
@@ -37,10 +37,10 @@ public:
     typedef JSCell Base;
     static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal;
 
-    static JSWebAssemblyCallee* create(VM& vm, std::unique_ptr<Wasm::FunctionCompilation>&& compilation)
+    static JSWebAssemblyCallee* create(VM& vm, std::unique_ptr<B3::Compilation>&& code, std::unique_ptr<B3::Compilation>&& jsToWasmEntryPoint)
     {
         JSWebAssemblyCallee* callee = new (NotNull, allocateCell<JSWebAssemblyCallee>(vm.heap)) JSWebAssemblyCallee(vm);
-        callee->finishCreation(vm, WTFMove(compilation));
+        callee->finishCreation(vm, std::forward<std::unique_ptr<B3::Compilation>>(code), std::forward<std::unique_ptr<B3::Compilation>>(jsToWasmEntryPoint));
         return callee;
     }
 
@@ -53,14 +53,14 @@ public:
     static const bool needsDestruction = true;
     static void destroy(JSCell*);
 
-    void* jsEntryPoint() { return m_jsEntryPoint->code().executableAddress(); }
+    void* jsToWasmEntryPoint() { return m_jsToWasmEntryPoint->code().executableAddress(); }
 
 private:
-    void finishCreation(VM&, std::unique_ptr<Wasm::FunctionCompilation>&&);
+    void finishCreation(VM&, std::unique_ptr<B3::Compilation>&&, std::unique_ptr<B3::Compilation>&&);
     JSWebAssemblyCallee(VM&);
 
     std::unique_ptr<B3::Compilation> m_code;
-    std::unique_ptr<B3::Compilation> m_jsEntryPoint;
+    std::unique_ptr<B3::Compilation> m_jsToWasmEntryPoint;
 };
 
 } // namespace JSC
index 0ad2019..f430074 100644 (file)
 #include "JSModuleEnvironment.h"
 #include "JSModuleNamespaceObject.h"
 #include "JSWebAssemblyModule.h"
+#include <wtf/StdLibExtras.h>
 
 namespace JSC {
 
-JSWebAssemblyInstance* JSWebAssemblyInstance::create(VM& vm, Structure* structure, JSWebAssemblyModule* module, JSModuleNamespaceObject* moduleNamespaceObject)
+JSWebAssemblyInstance* JSWebAssemblyInstance::create(VM& vm, Structure* structure, JSWebAssemblyModule* module, JSModuleNamespaceObject* moduleNamespaceObject, unsigned numImportFunctions)
 {
-    auto* instance = new (NotNull, allocateCell<JSWebAssemblyInstance>(vm.heap)) JSWebAssemblyInstance(vm, structure);
+    auto* instance = new (NotNull, allocateCell<JSWebAssemblyInstance>(vm.heap, allocationSize(numImportFunctions))) JSWebAssemblyInstance(vm, structure, numImportFunctions);
     instance->finishCreation(vm, module, moduleNamespaceObject);
     return instance;
 }
@@ -48,9 +49,11 @@ Structure* JSWebAssemblyInstance::createStructure(VM& vm, JSGlobalObject* global
     return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
 }
 
-JSWebAssemblyInstance::JSWebAssemblyInstance(VM& vm, Structure* structure)
+JSWebAssemblyInstance::JSWebAssemblyInstance(VM& vm, Structure* structure, unsigned numImportFunctions)
     : Base(vm, structure)
+    , m_numImportFunctions(numImportFunctions)
 {
+    memset(importFunctions(), 0, m_numImportFunctions * sizeof(WriteBarrier<JSCell>));
 }
 
 void JSWebAssemblyInstance::finishCreation(VM& vm, JSWebAssemblyModule* module, JSModuleNamespaceObject* moduleNamespaceObject)
@@ -75,6 +78,8 @@ void JSWebAssemblyInstance::visitChildren(JSCell* cell, SlotVisitor& visitor)
     Base::visitChildren(thisObject, visitor);
     visitor.append(&thisObject->m_module);
     visitor.append(&thisObject->m_moduleNamespaceObject);
+    for (unsigned i = 0; i < thisObject->m_numImportFunctions; ++i)
+        visitor.append(thisObject->importFunction(i));
 }
 
 const ClassInfo JSWebAssemblyInstance::s_info = { "WebAssembly.Instance", &Base::s_info, 0, CREATE_METHOD_TABLE(JSWebAssemblyInstance) };
index b6a3c3a..5ed2598 100644 (file)
@@ -40,7 +40,7 @@ public:
     typedef JSDestructibleObject Base;
 
 
-    static JSWebAssemblyInstance* create(VM&, Structure*, JSWebAssemblyModule*, JSModuleNamespaceObject*);
+    static JSWebAssemblyInstance* create(VM&, Structure*, JSWebAssemblyModule*, JSModuleNamespaceObject*, unsigned);
     static Structure* createStructure(VM&, JSGlobalObject*, JSValue);
 
     DECLARE_INFO;
@@ -51,8 +51,39 @@ public:
         return m_module.get();
     }
 
+    WriteBarrier<JSCell>* importFunction(unsigned idx)
+    {
+        RELEASE_ASSERT(idx < m_numImportFunctions);
+        return &importFunctions()[idx];
+    }
+
+    WriteBarrier<JSCell>* importFunctions()
+    {
+        return bitwise_cast<WriteBarrier<JSCell>*>(bitwise_cast<char*>(this) + offsetOfImportFunctions());
+    }
+
+    void setImportFunction(VM& vm, JSCell* value, unsigned idx)
+    {
+        importFunction(idx)->set(vm, this, value);
+    }
+
+    static size_t offsetOfImportFunctions()
+    {
+        return WTF::roundUpToMultipleOf<sizeof(WriteBarrier<JSCell>)>(sizeof(JSWebAssemblyInstance));
+    }
+
+    static size_t offsetOfImportFunction(unsigned idx)
+    {
+        return offsetOfImportFunctions() + sizeof(WriteBarrier<JSCell>) * idx;
+    }
+
+    static size_t allocationSize(unsigned numImportFunctions)
+    {
+        return offsetOfImportFunctions() + sizeof(WriteBarrier<JSCell>) * numImportFunctions;
+    }
+
 protected:
-    JSWebAssemblyInstance(VM&, Structure*);
+    JSWebAssemblyInstance(VM&, Structure*, unsigned);
     void finishCreation(VM&, JSWebAssemblyModule*, JSModuleNamespaceObject*);
     static void destroy(JSCell*);
     static void visitChildren(JSCell*, SlotVisitor&);
@@ -60,6 +91,7 @@ protected:
 private:
     WriteBarrier<JSWebAssemblyModule> m_module;
     WriteBarrier<JSModuleNamespaceObject> m_moduleNamespaceObject;
+    unsigned m_numImportFunctions;
 };
 
 } // namespace JSC
index 08849ff..de773b8 100644 (file)
@@ -38,10 +38,9 @@ namespace JSC {
 
 const ClassInfo JSWebAssemblyModule::s_info = { "WebAssembly.Module", &Base::s_info, nullptr, CREATE_METHOD_TABLE(JSWebAssemblyModule) };
 
-JSWebAssemblyModule* JSWebAssemblyModule::create(VM& vm, Structure* structure, std::unique_ptr<Wasm::ModuleInformation>& moduleInformation,
-    SymbolTable* exportSymbolTable, unsigned calleeCount)
+JSWebAssemblyModule* JSWebAssemblyModule::create(VM& vm, Structure* structure, std::unique_ptr<Wasm::ModuleInformation>&& moduleInformation, Bag<CallLinkInfo>&& callLinkInfos, Vector<Wasm::WasmToJSStub>&& wasmToJSStubs, Wasm::FunctionIndexSpace&& functionIndexSpace, SymbolTable* exportSymbolTable, unsigned calleeCount)
 {
-    auto* instance = new (NotNull, allocateCell<JSWebAssemblyModule>(vm.heap, allocationSize(calleeCount))) JSWebAssemblyModule(vm, structure, moduleInformation, calleeCount);
+    auto* instance = new (NotNull, allocateCell<JSWebAssemblyModule>(vm.heap, allocationSize(calleeCount))) JSWebAssemblyModule(vm, structure, std::forward<std::unique_ptr<Wasm::ModuleInformation>>(moduleInformation), std::forward<Bag<CallLinkInfo>>(callLinkInfos), std::forward<Vector<Wasm::WasmToJSStub>>(wasmToJSStubs), std::forward<Wasm::FunctionIndexSpace>(functionIndexSpace), calleeCount);
     instance->finishCreation(vm, exportSymbolTable);
     return instance;
 }
@@ -51,9 +50,12 @@ Structure* JSWebAssemblyModule::createStructure(VM& vm, JSGlobalObject* globalOb
     return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
 }
 
-JSWebAssemblyModule::JSWebAssemblyModule(VM& vm, Structure* structure, std::unique_ptr<Wasm::ModuleInformation>& moduleInformation, unsigned calleeCount)
+JSWebAssemblyModule::JSWebAssemblyModule(VM& vm, Structure* structure, std::unique_ptr<Wasm::ModuleInformation>&& moduleInformation, Bag<CallLinkInfo>&& callLinkInfos, Vector<Wasm::WasmToJSStub>&& wasmToJSStubs, Wasm::FunctionIndexSpace&& functionIndexSpace, unsigned calleeCount)
     : Base(vm, structure)
     , m_moduleInformation(WTFMove(moduleInformation))
+    , m_callLinkInfos(WTFMove(callLinkInfos))
+    , m_wasmToJSStubs(WTFMove(wasmToJSStubs))
+    , m_functionIndexSpace(WTFMove(functionIndexSpace))
     , m_calleeCount(calleeCount)
 {
     memset(callees(), 0, m_calleeCount * sizeof(WriteBarrier<JSWebAssemblyCallee>));
@@ -78,6 +80,8 @@ void JSWebAssemblyModule::visitChildren(JSCell* cell, SlotVisitor& visitor)
 
     Base::visitChildren(thisObject, visitor);
     visitor.append(&thisObject->m_exportSymbolTable);
+    for (auto iter = thisObject->m_callLinkInfos.begin(); !!iter; ++iter)
+        (*iter)->visitWeak(*thisObject->vm());
     for (unsigned i = 0; i < thisObject->m_calleeCount; i++) {
         WriteBarrier<JSWebAssemblyCallee>* callee = &thisObject->callees()[i];
         visitor.append(callee);
index 1aab233..05d2cf0 100644 (file)
@@ -30,6 +30,8 @@
 #include "JSDestructibleObject.h"
 #include "JSObject.h"
 #include "WasmFormat.h"
+#include <wtf/Bag.h>
+#include <wtf/Vector.h>
 
 namespace JSC {
 
@@ -40,16 +42,20 @@ class JSWebAssemblyModule : public JSDestructibleObject {
 public:
     typedef JSDestructibleObject Base;
 
-    static JSWebAssemblyModule* create(VM&, Structure*, std::unique_ptr<Wasm::ModuleInformation>&, SymbolTable* exports, unsigned calleeCount);
+    static JSWebAssemblyModule* create(VM&, Structure*, std::unique_ptr<Wasm::ModuleInformation>&&, Bag<CallLinkInfo>&&, Vector<Wasm::WasmToJSStub>&&, Wasm::FunctionIndexSpace&&, SymbolTable*, unsigned);
     static Structure* createStructure(VM&, JSGlobalObject*, JSValue);
 
     DECLARE_INFO;
 
     const Wasm::ModuleInformation& moduleInformation() const { return *m_moduleInformation.get(); }
     SymbolTable* exportSymbolTable() const { return m_exportSymbolTable.get(); }
+    Wasm::Signature* signatureForFunctionIndexSpace(unsigned functionIndexSpace) const { return m_functionIndexSpace.at(functionIndexSpace).signature; }
+    unsigned importCount() const { return m_wasmToJSStubs.size(); }
 
-    JSWebAssemblyCallee* callee(unsigned calleeIndex)
+    JSWebAssemblyCallee* calleeFromFunctionIndexSpace(unsigned functionIndexSpace)
     {
+        RELEASE_ASSERT(functionIndexSpace >= importCount());
+        unsigned calleeIndex = functionIndexSpace - importCount();
         RELEASE_ASSERT(calleeIndex < m_calleeCount);
         return callees()[calleeIndex].get();
     }
@@ -60,7 +66,7 @@ public:
     }
 
 protected:
-    JSWebAssemblyModule(VM&, Structure*, std::unique_ptr<Wasm::ModuleInformation>&, unsigned calleeCount);
+    JSWebAssemblyModule(VM&, Structure*, std::unique_ptr<Wasm::ModuleInformation>&&, Bag<CallLinkInfo>&&, Vector<Wasm::WasmToJSStub>&&, Wasm::FunctionIndexSpace&&, unsigned calleeCount);
     void finishCreation(VM&, SymbolTable*);
     static void destroy(JSCell*);
     static void visitChildren(JSCell*, SlotVisitor&);
@@ -77,7 +83,10 @@ private:
     }
 
     std::unique_ptr<Wasm::ModuleInformation> m_moduleInformation;
+    Bag<CallLinkInfo> m_callLinkInfos;
     WriteBarrier<SymbolTable> m_exportSymbolTable;
+    Vector<Wasm::WasmToJSStub> m_wasmToJSStubs;
+    Wasm::FunctionIndexSpace m_functionIndexSpace;
     unsigned m_calleeCount;
 };
 
index c055dd6..da454a1 100644 (file)
@@ -97,7 +97,11 @@ static EncodedJSValue JSC_HOST_CALL callWebAssemblyFunction(ExecState* exec)
     ProtoCallFrame protoCallFrame;
     protoCallFrame.init(nullptr, wasmFunction, firstArgument, argCount, remainingArgs);
     
-    EncodedJSValue rawResult = vmEntryToWasm(wasmFunction->webAssemblyCallee()->jsEntryPoint(), &vm, &protoCallFrame);
+    JSWebAssemblyInstance* prevJSWebAssemblyInstance = vm.topJSWebAssemblyInstance;
+    vm.topJSWebAssemblyInstance = wasmFunction->instance();
+    EncodedJSValue rawResult = vmEntryToWasm(wasmFunction->webAssemblyCallee()->jsToWasmEntryPoint(), &vm, &protoCallFrame);
+    vm.topJSWebAssemblyInstance = prevJSWebAssemblyInstance;
+
     // FIXME is this correct? https://bugs.webkit.org/show_bug.cgi?id=164876
     switch (signature->returnType) {
     case Wasm::Void:
index 0cb79db..7cc562c 100644 (file)
@@ -56,7 +56,7 @@ public:
     static Structure* createStructure(VM&, JSGlobalObject*, JSValue);
 
     JSWebAssemblyCallee* webAssemblyCallee() const { return m_wasmCallee.get(); }
-    const JSWebAssemblyInstance* instance() const { return m_instance.get(); }
+    JSWebAssemblyInstance* instance() const { return m_instance.get(); }
     const Wasm::Signature* signature()
     { 
         ASSERT(m_signature);
index 2952dd0..f3b7fde 100644 (file)
 #include "FunctionPrototype.h"
 #include "JSCInlines.h"
 #include "JSModuleEnvironment.h"
+#include "JSModuleNamespaceObject.h"
 #include "JSWebAssemblyInstance.h"
 #include "JSWebAssemblyModule.h"
+#include "WebAssemblyFunction.h"
 #include "WebAssemblyInstancePrototype.h"
 #include "WebAssemblyModuleRecord.h"
 
@@ -73,21 +75,95 @@ static EncodedJSValue JSC_HOST_CALL constructJSWebAssemblyInstance(ExecState* st
 
     Identifier moduleKey = Identifier::fromUid(PrivateName(PrivateName::Description, "WebAssemblyInstance"));
     WebAssemblyModuleRecord* moduleRecord = WebAssemblyModuleRecord::create(state, vm, globalObject->webAssemblyModuleRecordStructure(), moduleKey, moduleInformation);
-    RETURN_IF_EXCEPTION(scope, encodedJSValue());
+    RETURN_IF_EXCEPTION(scope, { });
 
     Structure* instanceStructure = InternalFunction::createSubclassStructure(state, state->newTarget(), globalObject->WebAssemblyInstanceStructure());
-    RETURN_IF_EXCEPTION(scope, encodedJSValue());
-
-    JSWebAssemblyInstance* instance = JSWebAssemblyInstance::create(vm, instanceStructure, jsModule, moduleRecord->getModuleNamespace(state));
-    RETURN_IF_EXCEPTION(scope, encodedJSValue());
+    RETURN_IF_EXCEPTION(scope, { });
+
+    JSWebAssemblyInstance* instance = JSWebAssemblyInstance::create(vm, instanceStructure, jsModule, moduleRecord->getModuleNamespace(state), moduleInformation.imports.size());
+    RETURN_IF_EXCEPTION(scope, { });
+
+    // Let funcs, memories and tables be initially-empty lists of callable JavaScript objects, WebAssembly.Memory objects and WebAssembly.Table objects, respectively.
+    // Let imports be an initially-empty list of external values.
+    unsigned numImportFunctions = 0;
+
+    // FIXME implement Table https://bugs.webkit.org/show_bug.cgi?id=164135
+    // FIXME implement Memory https://bugs.webkit.org/show_bug.cgi?id=164134
+    // FIXME implement Global https://bugs.webkit.org/show_bug.cgi?id=164133
+
+    // For each import i in module.imports:
+    for (auto& import : moduleInformation.imports) {
+        // 1. Let o be the resultant value of performing Get(importObject, i.module_name).
+        JSValue importModuleValue = importObject->get(state, import.module);
+        RETURN_IF_EXCEPTION(scope, { });
+        // 2. If Type(o) is not Object, throw a TypeError.
+        if (!importModuleValue.isObject())
+            return JSValue::encode(throwException(state, scope, createTypeError(state, ASCIILiteral("import must be an object"), defaultSourceAppender, runtimeTypeForValue(importModuleValue))));
+        // 3. Let v be the value of performing Get(o, i.item_name)
+        JSObject* object = jsCast<JSObject*>(importModuleValue);
+        JSValue value = object->get(state, import.field);
+        RETURN_IF_EXCEPTION(scope, { });
+        switch (import.kind) {
+        case Wasm::External::Function: {
+            // 4. If i is a function import:
+            // i. If IsCallable(v) is false, throw a TypeError.
+            if (!value.isFunction())
+                return JSValue::encode(throwException(state, scope, createTypeError(state, ASCIILiteral("import function must be callable"), defaultSourceAppender, runtimeTypeForValue(value))));
+            JSCell* cell = value.asCell();
+            // ii. If v is an Exported Function Exotic Object:
+            if (WebAssemblyFunction* importedExports = jsDynamicCast<WebAssemblyFunction*>(object)) {
+                // FIXME handle Function Exotic Object properly. https://bugs.webkit.org/show_bug.cgi?id=165282
+                // a. If the signature of v does not match the signature of i, throw a TypeError.
+                // b. Let closure be v.[[Closure]].
+                RELEASE_ASSERT_NOT_REACHED();
+                UNUSED_PARAM(importedExports);
+                break;
+            }
+            // iii. Otherwise:
+            // a. Let closure be a new host function of the given signature which calls v by coercing WebAssembly arguments to JavaScript arguments via ToJSValue and returns the result, if any, by coercing via ToWebAssemblyValue.
+            // Note: done as part of Plan compilation.
+            // iv. Append v to funcs.
+            instance->setImportFunction(vm, cell, numImportFunctions++);
+            // v. Append closure to imports.
+            break;
+        }
+        case Wasm::External::Table: {
+            // 7. Otherwise (i is a table import):
+            // FIXME implement Table https://bugs.webkit.org/show_bug.cgi?id=164135
+            // i. If v is not a WebAssembly.Table object, throw a TypeError.
+            // ii. Append v to tables.
+            // iii. Append v.[[Table]] to imports.
+            RELEASE_ASSERT_NOT_REACHED();
+            break;
+        }
+        case Wasm::External::Memory: {
+            // 6. If i is a memory import:
+            // FIXME implement Memory https://bugs.webkit.org/show_bug.cgi?id=164134
+            // i. If v is not a WebAssembly.Memory object, throw a TypeError.
+            // ii. Append v to memories.
+            // iii. Append v.[[Memory]] to imports.
+            RELEASE_ASSERT_NOT_REACHED();
+            break;
+        }
+        case Wasm::External::Global: {
+            // 5. If i is a global import:
+            // FIXME implement Global https://bugs.webkit.org/show_bug.cgi?id=164133
+            // i. If i is not an immutable global, throw a TypeError.
+            // ii. If Type(v) is not Number, throw a TypeError.
+            // iii. Append ToWebAssemblyValue(v) to imports.
+            RELEASE_ASSERT_NOT_REACHED();
+            break;
+        }
+        }
+    }
 
     moduleRecord->link(state, instance);
-    RETURN_IF_EXCEPTION(scope, encodedJSValue());
+    RETURN_IF_EXCEPTION(scope, { });
     if (verbose)
         moduleRecord->dump();
     JSValue startResult = moduleRecord->evaluate(state);
     UNUSED_PARAM(startResult);
-    RETURN_IF_EXCEPTION(scope, encodedJSValue());
+    RETURN_IF_EXCEPTION(scope, { });
 
     return JSValue::encode(instance);
 }
index e8aae13..8b9ca07 100644 (file)
@@ -79,17 +79,18 @@ static EncodedJSValue JSC_HOST_CALL constructJSWebAssemblyModule(ExecState* stat
 
     // On success, a new WebAssembly.Module object is returned with [[Module]] set to the validated Ast.module.
     auto* structure = InternalFunction::createSubclassStructure(state, state->newTarget(), asInternalFunction(state->jsCallee())->globalObject()->WebAssemblyModuleStructure());
-    RETURN_IF_EXCEPTION(scope, encodedJSValue());
+    RETURN_IF_EXCEPTION(scope, { });
 
     // The export symbol table is the same for all Instances of a Module.
     SymbolTable* exportSymbolTable = SymbolTable::create(vm);
-    for (auto& exp : plan.getModuleInformation()->exports) {
+    for (auto& exp : plan.exports()) {
         auto offset = exportSymbolTable->takeNextScopeOffset(NoLockingNecessary);
         exportSymbolTable->set(NoLockingNecessary, exp.field.impl(), SymbolTableEntry(VarOffset(offset)));
     }
 
-    unsigned calleeCount = plan.compiledFunctionCount();
-    JSWebAssemblyModule* result = JSWebAssemblyModule::create(vm, structure, plan.getModuleInformation(), exportSymbolTable, calleeCount);
+    // Only wasm-internal functions have a callee, stubs to JS do not.
+    unsigned calleeCount = plan.internalFunctionCount();
+    JSWebAssemblyModule* result = JSWebAssemblyModule::create(vm, structure, plan.takeModuleInformation(), plan.takeCallLinkInfos(), plan.takeWasmToJSStubs(), plan.takeFunctionIndexSpace(), exportSymbolTable, calleeCount);
     plan.initializeCallees(state->jsCallee()->globalObject(), 
         [&] (unsigned calleeIndex, JSWebAssemblyCallee* callee) {
             result->callees()[calleeIndex].set(vm, result, callee);
index dace16f..51c9d79 100644 (file)
@@ -105,8 +105,10 @@ void WebAssemblyModuleRecord::link(ExecState* state, JSWebAssemblyInstance* inst
     UNUSED_PARAM(scope);
     auto* globalObject = state->lexicalGlobalObject();
 
-    const Wasm::ModuleInformation& moduleInformation = instance->module()->moduleInformation();
-    SymbolTable* exportSymbolTable = instance->module()->exportSymbolTable();
+    JSWebAssemblyModule* module = instance->module();
+    const Wasm::ModuleInformation& moduleInformation = module->moduleInformation();
+    SymbolTable* exportSymbolTable = module->exportSymbolTable();
+    unsigned importCount = module->importCount();
 
     // FIXME wire up the imports. https://bugs.webkit.org/show_bug.cgi?id=165118
 
@@ -119,12 +121,16 @@ void WebAssemblyModuleRecord::link(ExecState* state, JSWebAssemblyInstance* inst
             // 1. If e is a closure c:
             //   i. If there is an Exported Function Exotic Object func in funcs whose func.[[Closure]] equals c, then return func.
             //   ii. (Note: At most one wrapper is created for any closure, so func is unique, even if there are multiple occurrances in the list. Moreover, if the item was an import that is already an Exported Function Exotic Object, then the original function object will be found. For imports that are regular JS functions, a new wrapper will be created.)
+            if (exp.functionIndex < importCount) {
+                // FIXME Implement re-exporting an import. https://bugs.webkit.org/show_bug.cgi?id=165510
+                RELEASE_ASSERT_NOT_REACHED();
+            }
             //   iii. Otherwise:
             //     a. Let func be an Exported Function Exotic Object created from c.
             //     b. Append func to funcs.
             //     c. Return func.
-            JSWebAssemblyCallee* wasmCallee = instance->module()->callee(exp.functionIndex);
-            Wasm::Signature* signature = moduleInformation.functions.at(exp.functionIndex).signature;
+            JSWebAssemblyCallee* wasmCallee = module->calleeFromFunctionIndexSpace(exp.functionIndex);
+            Wasm::Signature* signature = module->signatureForFunctionIndexSpace(exp.functionIndex);
             WebAssemblyFunction* function = WebAssemblyFunction::create(vm, globalObject, signature->arguments.size(), exp.field.string(), instance, wasmCallee, signature);
             exportedValue = function;
             break;
diff --git a/Source/JavaScriptCore/wasm/js/WebAssemblyToJSCallee.cpp b/Source/JavaScriptCore/wasm/js/WebAssemblyToJSCallee.cpp
new file mode 100644 (file)
index 0000000..24ea801
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2016 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 "WebAssemblyToJSCallee.h"
+
+#if ENABLE(WEBASSEMBLY)
+
+#include "JSCInlines.h"
+
+namespace JSC {
+
+const ClassInfo WebAssemblyToJSCallee::s_info = { "WebAssemblyToJSCallee", nullptr, 0, CREATE_METHOD_TABLE(WebAssemblyToJSCallee) };
+
+WebAssemblyToJSCallee* WebAssemblyToJSCallee::create(VM& vm, Structure* structure)
+{
+    WebAssemblyToJSCallee* callee = new (NotNull, allocateCell<WebAssemblyToJSCallee>(vm.heap)) WebAssemblyToJSCallee(vm, structure);
+    callee->finishCreation(vm);
+    return callee;
+}
+
+Structure* WebAssemblyToJSCallee::createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
+{
+    return Structure::create(vm, globalObject, prototype, TypeInfo(CellType, StructureFlags), info());
+}
+
+WebAssemblyToJSCallee::WebAssemblyToJSCallee(VM& vm, Structure* structure)
+    : Base(vm, structure)
+{ }
+
+void WebAssemblyToJSCallee::finishCreation(VM& vm)
+{
+    Base::finishCreation(vm);
+}
+
+void WebAssemblyToJSCallee::destroy(JSCell* cell)
+{
+    WebAssemblyToJSCallee* thisObject = jsCast<WebAssemblyToJSCallee*>(cell);
+    thisObject->WebAssemblyToJSCallee::~WebAssemblyToJSCallee();
+}
+
+} // namespace JSC
+
+#endif // ENABLE(WEBASSEMBLY)
diff --git a/Source/JavaScriptCore/wasm/js/WebAssemblyToJSCallee.h b/Source/JavaScriptCore/wasm/js/WebAssemblyToJSCallee.h
new file mode 100644 (file)
index 0000000..a34e3d1
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2016 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 "JSCell.h"
+
+namespace JSC {
+
+class WebAssemblyToJSCallee : public JSCell {
+public:
+    typedef JSCell Base;
+    static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal;
+
+    static WebAssemblyToJSCallee* create(VM&, Structure*);
+    static Structure* createStructure(VM&, JSGlobalObject*, JSValue);
+
+    DECLARE_EXPORT_INFO;
+    static const bool needsDestruction = true;
+    static void destroy(JSCell*);
+
+private:
+    void finishCreation(VM&);
+    WebAssemblyToJSCallee(VM&, Structure* structure);
+};
+
+} // namespace JSC
+
+#endif // ENABLE(WEBASSEMBLY)