Title: [213745] trunk
Revision
213745
Author
sbar...@apple.com
Date
2017-03-10 18:04:37 -0800 (Fri, 10 Mar 2017)

Log Message

WebAssembly: Make more demos run
https://bugs.webkit.org/show_bug.cgi?id=165510
<rdar://problem/29760310>

Reviewed by Keith Miller.

JSTests:

* wasm/Builder.js:
(export.default.Builder.prototype._registerSectionBuilders.const.section.in.WASM.description.section.switch.section.case.string_appeared_here.this.section):
* wasm/js-api/wrapper-function.js: Added.
(exportImport):
(return.new.WebAssembly.Module):
(assert.throws.makeInstance):
(assert.throws.Bar):
(assert.throws):

Source/_javascript_Core:

This patch makes another Wasm demo run:
https://kripken.github.io/BananaBread/cube2/bb.html

This patch fixes two bugs:
1. When WebAssemblyFunctionType was added, we did not properly
update the last JS type value.
2. Our code for our JS -> Wasm entrypoint was wrong. It lead to bad
code generation where we would emit B3 that would write over r12
and rbx (on x86) which is invalid since those are our pinned registers.
This patch just rewrites the entrypoint to use hand written assembler
code. I was planning on doing this anyways because it's a compile
time speed boost.

Also, this patch adds support for some new API features:
We can now export an import, either via a direct export, or via a Table and the
Element section. I've added a new class called WebAssemblyWrapperFunction that
just wraps over a JSObject that is a function. Wrapper functions have types
associated with them, so if they're re-imported, or called via call_indirect,
they can be type checked.

* CMakeLists.txt:
* _javascript_Core.xcodeproj/project.pbxproj:
* runtime/JSGlobalObject.cpp:
(JSC::JSGlobalObject::init):
(JSC::JSGlobalObject::visitChildren):
* runtime/JSGlobalObject.h:
(JSC::JSGlobalObject::webAssemblyWrapperFunctionStructure):
* runtime/JSType.h:
* wasm/JSWebAssemblyCodeBlock.h:
(JSC::JSWebAssemblyCodeBlock::wasmToJsCallStubForImport):
* wasm/WasmB3IRGenerator.cpp:
(JSC::Wasm::createJSToWasmWrapper):
* wasm/WasmCallingConvention.h:
(JSC::Wasm::CallingConvention::headerSizeInBytes):
* wasm/js/JSWebAssemblyHelpers.h:
(JSC::isWebAssemblyHostFunction):
* wasm/js/JSWebAssemblyInstance.cpp:
(JSC::JSWebAssemblyInstance::JSWebAssemblyInstance):
* wasm/js/JSWebAssemblyInstance.h:
(JSC::JSWebAssemblyInstance::importFunction):
(JSC::JSWebAssemblyInstance::importFunctions):
(JSC::JSWebAssemblyInstance::setImportFunction):
* wasm/js/JSWebAssemblyTable.cpp:
(JSC::JSWebAssemblyTable::JSWebAssemblyTable):
(JSC::JSWebAssemblyTable::grow):
(JSC::JSWebAssemblyTable::clearFunction):
(JSC::JSWebAssemblyTable::setFunction):
* wasm/js/JSWebAssemblyTable.h:
(JSC::JSWebAssemblyTable::getFunction):
* wasm/js/WebAssemblyFunction.cpp:
(JSC::callWebAssemblyFunction):
* wasm/js/WebAssemblyInstanceConstructor.cpp:
(JSC::WebAssemblyInstanceConstructor::createInstance):
* wasm/js/WebAssemblyModuleRecord.cpp:
(JSC::WebAssemblyModuleRecord::link):
(JSC::WebAssemblyModuleRecord::evaluate):
* wasm/js/WebAssemblyModuleRecord.h:
* wasm/js/WebAssemblyTablePrototype.cpp:
(JSC::webAssemblyTableProtoFuncGet):
(JSC::webAssemblyTableProtoFuncSet):
* wasm/js/WebAssemblyWrapperFunction.cpp: Added.
(JSC::callWebAssemblyWrapperFunction):
(JSC::WebAssemblyWrapperFunction::WebAssemblyWrapperFunction):
(JSC::WebAssemblyWrapperFunction::create):
(JSC::WebAssemblyWrapperFunction::finishCreation):
(JSC::WebAssemblyWrapperFunction::createStructure):
(JSC::WebAssemblyWrapperFunction::visitChildren):
* wasm/js/WebAssemblyWrapperFunction.h: Added.
(JSC::WebAssemblyWrapperFunction::signatureIndex):
(JSC::WebAssemblyWrapperFunction::wasmEntrypoint):
(JSC::WebAssemblyWrapperFunction::function):

Modified Paths

Added Paths

Diff

Modified: trunk/JSTests/ChangeLog (213744 => 213745)


--- trunk/JSTests/ChangeLog	2017-03-11 01:56:08 UTC (rev 213744)
+++ trunk/JSTests/ChangeLog	2017-03-11 02:04:37 UTC (rev 213745)
@@ -1,3 +1,20 @@
+2017-03-10  Saam Barati  <sbar...@apple.com>
+
+        WebAssembly: Make more demos run
+        https://bugs.webkit.org/show_bug.cgi?id=165510
+        <rdar://problem/29760310>
+
+        Reviewed by Keith Miller.
+
+        * wasm/Builder.js:
+        (export.default.Builder.prototype._registerSectionBuilders.const.section.in.WASM.description.section.switch.section.case.string_appeared_here.this.section):
+        * wasm/js-api/wrapper-function.js: Added.
+        (exportImport):
+        (return.new.WebAssembly.Module):
+        (assert.throws.makeInstance):
+        (assert.throws.Bar):
+        (assert.throws):
+
 2017-03-10  Mark Lam  <mark....@apple.com>
 
         JSC: BindingNode::bindValue doesn't increase the scope's reference count.

Modified: trunk/JSTests/wasm/Builder.js (213744 => 213745)


--- trunk/JSTests/wasm/Builder.js	2017-03-11 01:56:08 UTC (rev 213744)
+++ trunk/JSTests/wasm/Builder.js	2017-03-11 02:04:37 UTC (rev 213745)
@@ -579,7 +579,10 @@
                 break;
 
             case "Element":
-                this[section] = function() {
+                this[section] = function(...args) {
+                    if (args.length !== 0)
+                        throw new Error("You're doing it wrong. This element does not take arguments. You must chain the call with another Element()");
+
                     const s = this._addSection(section);
                     const elementBuilder = {
                         End: () => this,

Added: trunk/JSTests/wasm/js-api/wrapper-function.js (0 => 213745)


--- trunk/JSTests/wasm/js-api/wrapper-function.js	                        (rev 0)
+++ trunk/JSTests/wasm/js-api/wrapper-function.js	2017-03-11 02:04:37 UTC (rev 213745)
@@ -0,0 +1,146 @@
+import Builder from '../Builder.js';
+import * as assert from '../assert.js';
+
+
+function exportImport(type) {
+    let builder = (new Builder())
+        .Type().End()
+        .Import()
+            .Function("imp", "f", type)
+        .End()
+        .Function().End()
+        .Export()
+            .Function("func", {module: "imp", field: "f"})
+        .End()
+        .Code().End();
+    return new WebAssembly.Module(builder.WebAssembly().get());
+}
+
+{
+    let type = { params: ["i32"], ret: "i32" };
+    let module = exportImport(type);
+    let called = false;
+    let foo = (i) => {
+        called = true;
+        return i + 42;
+    };
+    let instance = new WebAssembly.Instance(module, {imp: {f: foo}});
+    assert.truthy(instance.exports.func !== foo);
+    for (let i = 0; i < 100; i++) {
+        let r1 = instance.exports.func(i);
+        assert.truthy(called);
+        called = false;
+        let r2 = foo(i);
+        called = false;
+        assert.eq(r1, r2);
+    }
+
+    {
+        let builder = (new Builder())
+            .Type().End()
+            .Import()
+                .Function("imp", "f", {params: []})
+            .End()
+            .Function().End()
+            .Code().End();
+        let module = new WebAssembly.Module(builder.WebAssembly().get());
+        // This should not type check.
+        assert.throws(() => new WebAssembly.Instance(module, {imp: {f: instance.exports.func}}), WebAssembly.LinkError, "imported function's signature doesn't match the provided WebAssembly function's signature");
+    }
+
+}
+
+{
+    const tableDescription = {element: "anyfunc", initial: 2};
+    function makeInstance(type, imp) {
+        const builder = new Builder()
+            .Type()
+                .Func(["i32"], "i32")
+                .Func(["i32", "i32"], "i32")
+            .End()
+            .Import()
+                .Table("imp", "table", tableDescription)
+                .Function("imp", "f1", {params: ["i32"], ret:"i32"})
+                .Function("imp", "f2", {params: ["i32", "i32"], ret:"i32"})
+            .End()
+            .Function().End()
+            .Export()
+                .Function("foo")
+            .End()
+            .Element()
+                .Element({offset: 0, functionIndices: [0, 1]})
+            .End()
+            .Code()
+                .Function("foo", 1)
+                    .GetLocal(1) // parameter to call
+                    .GetLocal(0) // call index
+                    .CallIndirect(0, 0) // calling function of type ['i32'] => 'i32'
+                    .Return()
+                .End()
+            .End();
+        let module = new WebAssembly.Module(builder.WebAssembly().get());
+        return new WebAssembly.Instance(module, imp);
+    }
+
+    function Bar(){};
+    noInline(Bar);
+    let called = false;
+    let foo = (i) => {
+        called = true;
+        new Bar;
+        return i*42;
+    }
+    let table = new WebAssembly.Table(tableDescription);
+    let inst = makeInstance({params:['i32'], ret:"i32"}, {imp: {f1: foo, f2:foo, table}});
+    for (let i = 0; i < 1000; i++) {
+        let r1 = inst.exports.foo(0, i);
+        assert.truthy(called);
+        called = false;
+        let r2 = foo(i);
+        assert.truthy(called);
+        called = false;
+        assert.eq(r1, r2);
+    }
+    for (let i = 0; i < 1000; i++) {
+        assert.throws(() => inst.exports.foo(1, i), WebAssembly.RuntimeError, "call_indirect to a signature that does not match");
+        assert.truthy(!called);
+    }
+    for (let i = 0; i < 1000; i++) {
+        let r1 = table.get(0)(i);
+        table.set(0, table.get(0)); // just make sure setting a wrapper function works.
+        assert.truthy(called);
+        called = false;
+        let r2 = table.get(1)(i);
+        assert.truthy(called);
+        called = false;
+        assert.eq(r1, r2);
+    }
+
+    {
+        let nextInst = makeInstance({params:['i32'], ret:"i32"}, {imp: {f1: table.get(0), f2:inst.exports.foo, table}});
+        for (let i = 0; i < 1000; i++) {
+            let r1 = nextInst.exports.foo(0, i);
+            assert.truthy(called);
+            called = false;
+            let r2 = foo(i);
+            assert.truthy(called);
+            called = false;
+            assert.eq(r1, r2);
+        }
+
+        for (let i = 0; i < 1000; i++) {
+            assert.throws(() => nextInst.exports.foo(1, i), WebAssembly.RuntimeError, "call_indirect to a signature that does not match");
+            assert.truthy(!called);
+        }
+
+        for (let i = 0; i < 1000; i++) {
+            let r1 = table.get(1)(0, i);
+            assert.truthy(called);
+            called = false;
+            let r2 = foo(i);
+            assert.truthy(called);
+            called = false;
+            assert.eq(r1, r2);
+        }
+    }
+}

Modified: trunk/Source/_javascript_Core/CMakeLists.txt (213744 => 213745)


--- trunk/Source/_javascript_Core/CMakeLists.txt	2017-03-11 01:56:08 UTC (rev 213744)
+++ trunk/Source/_javascript_Core/CMakeLists.txt	2017-03-11 02:04:37 UTC (rev 213745)
@@ -968,6 +968,7 @@
     wasm/js/WebAssemblyTableConstructor.cpp
     wasm/js/WebAssemblyTablePrototype.cpp
     wasm/js/WebAssemblyToJSCallee.cpp
+    wasm/js/WebAssemblyWrapperFunction.cpp
 
     yarr/RegularExpression.cpp
     yarr/YarrCanonicalizeUCS2.cpp

Modified: trunk/Source/_javascript_Core/ChangeLog (213744 => 213745)


--- trunk/Source/_javascript_Core/ChangeLog	2017-03-11 01:56:08 UTC (rev 213744)
+++ trunk/Source/_javascript_Core/ChangeLog	2017-03-11 02:04:37 UTC (rev 213745)
@@ -1,3 +1,83 @@
+2017-03-10  Saam Barati  <sbar...@apple.com>
+
+        WebAssembly: Make more demos run
+        https://bugs.webkit.org/show_bug.cgi?id=165510
+        <rdar://problem/29760310>
+
+        Reviewed by Keith Miller.
+
+        This patch makes another Wasm demo run:
+        https://kripken.github.io/BananaBread/cube2/bb.html
+        
+        This patch fixes two bugs:
+        1. When WebAssemblyFunctionType was added, we did not properly
+        update the last JS type value.
+        2. Our code for our JS -> Wasm entrypoint was wrong. It lead to bad
+        code generation where we would emit B3 that would write over r12
+        and rbx (on x86) which is invalid since those are our pinned registers.
+        This patch just rewrites the entrypoint to use hand written assembler
+        code. I was planning on doing this anyways because it's a compile
+        time speed boost.
+        
+        Also, this patch adds support for some new API features:
+        We can now export an import, either via a direct export, or via a Table and the
+        Element section. I've added a new class called WebAssemblyWrapperFunction that
+        just wraps over a JSObject that is a function. Wrapper functions have types
+        associated with them, so if they're re-imported, or called via call_indirect,
+        they can be type checked.
+
+        * CMakeLists.txt:
+        * _javascript_Core.xcodeproj/project.pbxproj:
+        * runtime/JSGlobalObject.cpp:
+        (JSC::JSGlobalObject::init):
+        (JSC::JSGlobalObject::visitChildren):
+        * runtime/JSGlobalObject.h:
+        (JSC::JSGlobalObject::webAssemblyWrapperFunctionStructure):
+        * runtime/JSType.h:
+        * wasm/JSWebAssemblyCodeBlock.h:
+        (JSC::JSWebAssemblyCodeBlock::wasmToJsCallStubForImport):
+        * wasm/WasmB3IRGenerator.cpp:
+        (JSC::Wasm::createJSToWasmWrapper):
+        * wasm/WasmCallingConvention.h:
+        (JSC::Wasm::CallingConvention::headerSizeInBytes):
+        * wasm/js/JSWebAssemblyHelpers.h:
+        (JSC::isWebAssemblyHostFunction):
+        * wasm/js/JSWebAssemblyInstance.cpp:
+        (JSC::JSWebAssemblyInstance::JSWebAssemblyInstance):
+        * wasm/js/JSWebAssemblyInstance.h:
+        (JSC::JSWebAssemblyInstance::importFunction):
+        (JSC::JSWebAssemblyInstance::importFunctions):
+        (JSC::JSWebAssemblyInstance::setImportFunction):
+        * wasm/js/JSWebAssemblyTable.cpp:
+        (JSC::JSWebAssemblyTable::JSWebAssemblyTable):
+        (JSC::JSWebAssemblyTable::grow):
+        (JSC::JSWebAssemblyTable::clearFunction):
+        (JSC::JSWebAssemblyTable::setFunction):
+        * wasm/js/JSWebAssemblyTable.h:
+        (JSC::JSWebAssemblyTable::getFunction):
+        * wasm/js/WebAssemblyFunction.cpp:
+        (JSC::callWebAssemblyFunction):
+        * wasm/js/WebAssemblyInstanceConstructor.cpp:
+        (JSC::WebAssemblyInstanceConstructor::createInstance):
+        * wasm/js/WebAssemblyModuleRecord.cpp:
+        (JSC::WebAssemblyModuleRecord::link):
+        (JSC::WebAssemblyModuleRecord::evaluate):
+        * wasm/js/WebAssemblyModuleRecord.h:
+        * wasm/js/WebAssemblyTablePrototype.cpp:
+        (JSC::webAssemblyTableProtoFuncGet):
+        (JSC::webAssemblyTableProtoFuncSet):
+        * wasm/js/WebAssemblyWrapperFunction.cpp: Added.
+        (JSC::callWebAssemblyWrapperFunction):
+        (JSC::WebAssemblyWrapperFunction::WebAssemblyWrapperFunction):
+        (JSC::WebAssemblyWrapperFunction::create):
+        (JSC::WebAssemblyWrapperFunction::finishCreation):
+        (JSC::WebAssemblyWrapperFunction::createStructure):
+        (JSC::WebAssemblyWrapperFunction::visitChildren):
+        * wasm/js/WebAssemblyWrapperFunction.h: Added.
+        (JSC::WebAssemblyWrapperFunction::signatureIndex):
+        (JSC::WebAssemblyWrapperFunction::wasmEntrypoint):
+        (JSC::WebAssemblyWrapperFunction::function):
+
 2017-03-10  Mark Lam  <mark....@apple.com>
 
         JSC: BindingNode::bindValue doesn't increase the scope's reference count.

Modified: trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj (213744 => 213745)


--- trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj	2017-03-11 01:56:08 UTC (rev 213744)
+++ trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj	2017-03-11 02:04:37 UTC (rev 213745)
@@ -1312,6 +1312,8 @@
 		52C0611F1AA51E1C00B4ADBA /* RuntimeType.h in Headers */ = {isa = PBXBuildFile; fileRef = 52C0611D1AA51E1B00B4ADBA /* RuntimeType.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		52C952B719A289850069B386 /* TypeProfiler.h in Headers */ = {isa = PBXBuildFile; fileRef = 52C952B619A289850069B386 /* TypeProfiler.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		52C952B919A28A1C0069B386 /* TypeProfiler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 52C952B819A28A1C0069B386 /* TypeProfiler.cpp */; };
+		52F6C35D1E71EB080081F4CC /* WebAssemblyWrapperFunction.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 52F6C35B1E71EB080081F4CC /* WebAssemblyWrapperFunction.cpp */; };
+		52F6C35E1E71EB080081F4CC /* WebAssemblyWrapperFunction.h in Headers */ = {isa = PBXBuildFile; fileRef = 52F6C35C1E71EB080081F4CC /* WebAssemblyWrapperFunction.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		531374BD1D5CE67600AF7A0B /* WasmPlan.h in Headers */ = {isa = PBXBuildFile; fileRef = 531374BC1D5CE67600AF7A0B /* WasmPlan.h */; };
 		531374BF1D5CE95000AF7A0B /* WasmPlan.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 531374BE1D5CE95000AF7A0B /* WasmPlan.cpp */; };
 		533B15DF1DC7F463004D500A /* WasmOps.h in Headers */ = {isa = PBXBuildFile; fileRef = 533B15DE1DC7F463004D500A /* WasmOps.h */; settings = {ATTRIBUTES = (Private, ); }; };
@@ -3789,6 +3791,8 @@
 		52C0611D1AA51E1B00B4ADBA /* RuntimeType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RuntimeType.h; sourceTree = "<group>"; };
 		52C952B619A289850069B386 /* TypeProfiler.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TypeProfiler.h; sourceTree = "<group>"; };
 		52C952B819A28A1C0069B386 /* TypeProfiler.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = TypeProfiler.cpp; sourceTree = "<group>"; };
+		52F6C35B1E71EB080081F4CC /* WebAssemblyWrapperFunction.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = WebAssemblyWrapperFunction.cpp; path = js/WebAssemblyWrapperFunction.cpp; sourceTree = "<group>"; };
+		52F6C35C1E71EB080081F4CC /* WebAssemblyWrapperFunction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = WebAssemblyWrapperFunction.h; path = js/WebAssemblyWrapperFunction.h; sourceTree = "<group>"; };
 		531374BC1D5CE67600AF7A0B /* WasmPlan.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WasmPlan.h; sourceTree = "<group>"; };
 		531374BE1D5CE95000AF7A0B /* WasmPlan.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WasmPlan.cpp; sourceTree = "<group>"; };
 		533B15DE1DC7F463004D500A /* WasmOps.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WasmOps.h; sourceTree = "<group>"; };
@@ -7908,6 +7912,8 @@
 				AD2FCBC31DB58DA400B3E736 /* WebAssemblyTablePrototype.h */,
 				ADBC54D21DF8EA00005BF738 /* WebAssemblyToJSCallee.cpp */,
 				ADBC54D31DF8EA00005BF738 /* WebAssemblyToJSCallee.h */,
+				52F6C35B1E71EB080081F4CC /* WebAssemblyWrapperFunction.cpp */,
+				52F6C35C1E71EB080081F4CC /* WebAssemblyWrapperFunction.h */,
 			);
 			name = js;
 			sourceTree = "<group>";
@@ -8245,6 +8251,7 @@
 				0F21C27D14BE727A00ADC64B /* CodeSpecializationKind.h in Headers */,
 				0F0B83A714BCF50700885B4F /* CodeType.h in Headers */,
 				0FA762051DB9242900B7A2FD /* CollectionScope.h in Headers */,
+				52F6C35E1E71EB080081F4CC /* WebAssemblyWrapperFunction.h in Headers */,
 				A53243981856A489002ED692 /* CombinedDomains.json in Headers */,
 				BC18C3F30E16F5CD00B34460 /* CommonIdentifiers.h in Headers */,
 				0F15F15F14B7A73E005DE37D /* CommonSlowPaths.h in Headers */,
@@ -10358,6 +10365,7 @@
 				A503FA19188E0FB000110F14 /* _javascript_CallFrame.cpp in Sources */,
 				1429D92F0ED22D7000B89619 /* JIT.cpp in Sources */,
 				FE1220281BE7F5910039E6F2 /* JITAddGenerator.cpp in Sources */,
+				52F6C35D1E71EB080081F4CC /* WebAssemblyWrapperFunction.cpp in Sources */,
 				86A90ED00EE7D51F00AB350D /* JITArithmetic.cpp in Sources */,
 				A75706DE118A2BCF0057F88F /* JITArithmetic32_64.cpp in Sources */,
 				FE3A06B11C10CB8400390FDD /* JITBitAndGenerator.cpp in Sources */,

Modified: trunk/Source/_javascript_Core/runtime/JSGlobalObject.cpp (213744 => 213745)


--- trunk/Source/_javascript_Core/runtime/JSGlobalObject.cpp	2017-03-11 01:56:08 UTC (rev 213744)
+++ trunk/Source/_javascript_Core/runtime/JSGlobalObject.cpp	2017-03-11 02:04:37 UTC (rev 213745)
@@ -892,6 +892,7 @@
         m_webAssemblyStructure.set(vm, this, JSWebAssembly::createStructure(vm, this, webAssemblyPrototype));
         m_webAssemblyModuleRecordStructure.set(vm, this, WebAssemblyModuleRecord::createStructure(vm, this, m_objectPrototype.get()));
         m_webAssemblyFunctionStructure.set(vm, this, WebAssemblyFunction::createStructure(vm, this, m_functionPrototype.get()));
+        m_webAssemblyWrapperFunctionStructure.set(vm, this, WebAssemblyWrapperFunction::createStructure(vm, this, m_functionPrototype.get()));
         auto* webAssembly = JSWebAssembly::create(vm, this, m_webAssemblyStructure.get());
         putDirectWithoutTransition(vm, Identifier::fromString(exec, "WebAssembly"), webAssembly, DontEnum);
 
@@ -1272,6 +1273,7 @@
     visitor.append(thisObject->m_webAssemblyStructure);
     visitor.append(thisObject->m_webAssemblyModuleRecordStructure);
     visitor.append(thisObject->m_webAssemblyFunctionStructure);
+    visitor.append(thisObject->m_webAssemblyWrapperFunctionStructure);
     FOR_EACH_WEBASSEMBLY_CONSTRUCTOR_TYPE(VISIT_SIMPLE_TYPE)
 #endif // ENABLE(WEBASSEMBLY)
 

Modified: trunk/Source/_javascript_Core/runtime/JSGlobalObject.h (213744 => 213745)


--- trunk/Source/_javascript_Core/runtime/JSGlobalObject.h	2017-03-11 01:56:08 UTC (rev 213744)
+++ trunk/Source/_javascript_Core/runtime/JSGlobalObject.h	2017-03-11 02:04:37 UTC (rev 213745)
@@ -345,6 +345,7 @@
     WriteBarrier<Structure> m_webAssemblyStructure;
     WriteBarrier<Structure> m_webAssemblyModuleRecordStructure;
     WriteBarrier<Structure> m_webAssemblyFunctionStructure;
+    WriteBarrier<Structure> m_webAssemblyWrapperFunctionStructure;
     FOR_EACH_WEBASSEMBLY_CONSTRUCTOR_TYPE(DEFINE_STORAGE_FOR_SIMPLE_TYPE)
 #endif // ENABLE(WEBASSEMBLY)
 
@@ -612,6 +613,7 @@
 #if ENABLE(WEBASSEMBLY)
     Structure* webAssemblyModuleRecordStructure() const { return m_webAssemblyModuleRecordStructure.get(); }
     Structure* webAssemblyFunctionStructure() const { return m_webAssemblyFunctionStructure.get(); }
+    Structure* webAssemblyWrapperFunctionStructure() const { return m_webAssemblyWrapperFunctionStructure.get(); }
 #endif // ENABLE(WEBASSEMBLY)
 
     JS_EXPORT_PRIVATE void setRemoteDebuggingEnabled(bool);

Modified: trunk/Source/_javascript_Core/runtime/JSType.h (213744 => 213745)


--- trunk/Source/_javascript_Core/runtime/JSType.h	2017-03-11 01:56:08 UTC (rev 213744)
+++ trunk/Source/_javascript_Core/runtime/JSType.h	2017-03-11 02:04:37 UTC (rev 213745)
@@ -97,7 +97,7 @@
 
     WebAssemblyFunctionType,
 
-    LastJSCObjectType = JSSetType,
+    LastJSCObjectType = WebAssemblyFunctionType,
     MaxJSType = 0b11111111,
 };
 

Modified: trunk/Source/_javascript_Core/wasm/JSWebAssemblyCodeBlock.h (213744 => 213745)


--- trunk/Source/_javascript_Core/wasm/JSWebAssemblyCodeBlock.h	2017-03-11 01:56:08 UTC (rev 213744)
+++ trunk/Source/_javascript_Core/wasm/JSWebAssemblyCodeBlock.h	2017-03-11 02:04:37 UTC (rev 213745)
@@ -94,6 +94,12 @@
         return bitwise_cast<WriteBarrier<JSWebAssemblyCallee>*>(bitwise_cast<char*>(this) + offsetOfCallees());
     }
 
+    void* wasmToJsCallStubForImport(unsigned importIndex)
+    {
+        RELEASE_ASSERT(importIndex < m_wasmExitStubs.size());
+        return m_wasmExitStubs[importIndex].wasmToJs.code().executableAddress();
+    }
+
 private:
     JSWebAssemblyCodeBlock(VM&, JSWebAssemblyModule*, Bag<CallLinkInfo>&&, Vector<Wasm::WasmExitStubs>&&, Wasm::Memory::Mode, unsigned calleeCount);
     DECLARE_EXPORT_INFO;

Modified: trunk/Source/_javascript_Core/wasm/WasmB3IRGenerator.cpp (213744 => 213745)


--- trunk/Source/_javascript_Core/wasm/WasmB3IRGenerator.cpp	2017-03-11 01:56:08 UTC (rev 213744)
+++ trunk/Source/_javascript_Core/wasm/WasmB3IRGenerator.cpp	2017-03-11 02:04:37 UTC (rev 213745)
@@ -1039,85 +1039,165 @@
 
 static void createJSToWasmWrapper(VM& vm, CompilationContext& compilationContext, WasmInternalFunction& function, const Signature* signature, const ModuleInformation& info)
 {
-    Procedure proc;
-    BasicBlock* block = proc.addBlock();
+    CCallHelpers& jit = *compilationContext.jsEntrypointJIT;
 
-    Origin origin;
+    jit.emitFunctionPrologue();
 
-    jscCallingConvention().setupFrameInPrologue(&function.jsToWasmCalleeMoveLocation, proc, origin, block);
+    // FIXME Stop using 0 as codeBlocks. https://bugs.webkit.org/show_bug.cgi?id=165321
+    jit.store64(CCallHelpers::TrustedImm64(0), CCallHelpers::Address(GPRInfo::callFrameRegister, CallFrameSlot::codeBlock * static_cast<int>(sizeof(Register))));
+    MacroAssembler::DataLabelPtr calleeMoveLocation = jit.moveWithPatch(MacroAssembler::TrustedImmPtr(nullptr), GPRInfo::nonPreservedNonReturnGPR);
+    jit.storePtr(GPRInfo::nonPreservedNonReturnGPR, CCallHelpers::Address(GPRInfo::callFrameRegister, CallFrameSlot::callee * static_cast<int>(sizeof(Register))));
+    CodeLocationDataLabelPtr* linkedCalleeMove = &function.jsToWasmCalleeMoveLocation;
+    jit.addLinkTask([=] (LinkBuffer& linkBuffer) {
+        *linkedCalleeMove = linkBuffer.locationOf(calleeMoveLocation);
+    });
 
-    if (!ASSERT_DISABLED) {
-        // This should be guaranteed by our JS wrapper that handles calls to us.
-        // Just prevent against crazy when ASSERT is enabled.
-        Value* framePointer = block->appendNew<B3::Value>(proc, B3::FramePointer, origin);
-        Value* offSetOfArgumentCount = block->appendNew<Const64Value>(proc, origin, CallFrameSlot::argumentCount * sizeof(Register));
-        Value* argumentCount = block->appendNew<MemoryValue>(proc, Load, Int32, origin,
-            block->appendNew<Value>(proc, Add, origin, framePointer, offSetOfArgumentCount));
+    RegisterSet toSave;
+    const PinnedRegisterInfo& pinnedRegs = PinnedRegisterInfo::get();
+    toSave.set(pinnedRegs.baseMemoryPointer);
+    for (const PinnedSizeRegisterInfo& regInfo : pinnedRegs.sizeRegisters)
+        toSave.set(regInfo.sizeRegister);
 
-        Value* expectedArgumentCount = block->appendNew<Const32Value>(proc, origin, signature->argumentCount());
+#if !ASSERT_DISABLED
+    unsigned toSaveSize = toSave.numberOfSetGPRs();
+    // They should all be callee saves.
+    toSave.filter(RegisterSet::calleeSaveRegisters());
+    ASSERT(toSave.numberOfSetGPRs() == toSaveSize);
+#endif
 
-        CheckValue* argumentCountCheck = block->appendNew<CheckValue>(proc, Check, origin,
-            block->appendNew<Value>(proc, Above, origin, expectedArgumentCount, argumentCount));
+    RegisterAtOffsetList registersToSpill(toSave, RegisterAtOffsetList::OffsetBaseType::FramePointerBased);
+    function.jsToWasmEntrypoint.calleeSaveRegisters = registersToSpill;
 
-        argumentCountCheck->setGenerator([] (CCallHelpers& jit, const StackmapGenerationParams&) {
-            jit.breakpoint();
-        });
+    unsigned totalFrameSize = registersToSpill.size() * sizeof(void*);
+    totalFrameSize += WasmCallingConvention::headerSizeInBytes();
+    totalFrameSize -= sizeof(CallerFrameAndPC);
+    unsigned numGPRs = 0;
+    unsigned numFPRs = 0;
+    for (unsigned i = 0; i < signature->argumentCount(); i++) {
+        switch (signature->argument(i)) {
+        case Wasm::I64:
+        case Wasm::I32:
+            if (numGPRs >= wasmCallingConvention().m_gprArgs.size())
+                totalFrameSize += sizeof(void*);
+            ++numGPRs;
+            break;
+        case Wasm::F32:
+        case Wasm::F64:
+            if (numFPRs >= wasmCallingConvention().m_fprArgs.size())
+                totalFrameSize += sizeof(void*);
+            ++numFPRs;
+            break;
+        default:
+            RELEASE_ASSERT_NOT_REACHED();
+        }
     }
 
-    // FIXME The instance is currently set by the C++ code in WebAssemblyFunction::call. We shouldn't go through the extra C++ hoop. https://bugs.webkit.org/show_bug.cgi?id=166486
-    Value* instance = block->appendNew<MemoryValue>(proc, Load, pointerType(), Origin(),
-        block->appendNew<ConstPtrValue>(proc, Origin(), &vm.topJSWebAssemblyInstance));
-    restoreWebAssemblyGlobalState(vm, info.memory, instance, proc, block);
+    totalFrameSize = WTF::roundUpToMultipleOf(stackAlignmentBytes(), totalFrameSize);
+    jit.subPtr(MacroAssembler::TrustedImm32(totalFrameSize), MacroAssembler::stackPointerRegister);
 
-    // Get our arguments.
-    Vector<Value*> arguments;
-    jscCallingConvention().loadArguments(signature, proc, block, origin, [&] (Value* argument, unsigned) {
-        arguments.append(argument);
-    });
+    // We save all these registers regardless of having a memory or not.
+    // The reason is that we use one of these as a scratch. That said,
+    // almost all real wasm programs use memory, so it's not really
+    // worth optimizing for the case that they don't.
+    for (const RegisterAtOffset& regAtOffset : registersToSpill) {
+        GPRReg reg = regAtOffset.reg().gpr();
+        ptrdiff_t offset = regAtOffset.offset();
+        jit.storePtr(reg, CCallHelpers::Address(GPRInfo::callFrameRegister, offset));
+    }
 
-    // Move the arguments into place.
-    Value* result = wasmCallingConvention().setupCall(proc, block, origin, arguments, toB3Type(signature->returnType()), [&] (PatchpointValue* patchpoint) {
-        CompilationContext* context = &compilationContext;
+    {
+        CCallHelpers::Address calleeFrame = CCallHelpers::Address(MacroAssembler::stackPointerRegister, -static_cast<ptrdiff_t>(sizeof(CallerFrameAndPC)));
+        numGPRs = 0;
+        numFPRs = 0;
+        // We're going to set the pinned registers after this. So
+        // we can use this as a scratch for now since we saved it above.
+        GPRReg scratchReg = pinnedRegs.baseMemoryPointer;
 
-        // wasm -> wasm calls clobber pinned registers unconditionally. This JS -> wasm transition must therefore restore these pinned registers (which are usually callee-saved) to account for this.
-        const PinnedRegisterInfo* pinnedRegs = &PinnedRegisterInfo::get();
-        RegisterSet clobbers;
-        clobbers.set(pinnedRegs->baseMemoryPointer);
-        for (auto info : pinnedRegs->sizeRegisters)
-            clobbers.set(info.sizeRegister);
-        patchpoint->effects.writesPinned = true;
-        patchpoint->clobber(clobbers);
+        ptrdiff_t jsOffset = CallFrameSlot::thisArgument * sizeof(void*);
+        ptrdiff_t wasmOffset = CallFrame::headerSizeInRegisters * sizeof(void*);
+        for (unsigned i = 0; i < signature->argumentCount(); i++) {
+            switch (signature->argument(i)) {
+            case Wasm::I32:
+            case Wasm::I64:
+                if (numGPRs >= wasmCallingConvention().m_gprArgs.size()) {
+                    if (signature->argument(i) == Wasm::I32) {
+                        jit.load32(CCallHelpers::Address(GPRInfo::callFrameRegister, jsOffset), scratchReg);
+                        jit.store32(scratchReg, calleeFrame.withOffset(wasmOffset));
+                    } else {
+                        jit.load64(CCallHelpers::Address(GPRInfo::callFrameRegister, jsOffset), scratchReg);
+                        jit.store64(scratchReg, calleeFrame.withOffset(wasmOffset));
+                    }
+                    wasmOffset += sizeof(void*);
+                } else {
+                    if (signature->argument(i) == Wasm::I32)
+                        jit.load32(CCallHelpers::Address(GPRInfo::callFrameRegister, jsOffset), wasmCallingConvention().m_gprArgs[numGPRs].gpr());
+                    else
+                        jit.load64(CCallHelpers::Address(GPRInfo::callFrameRegister, jsOffset), wasmCallingConvention().m_gprArgs[numGPRs].gpr());
+                }
+                ++numGPRs;
+                break;
+            case Wasm::F32:
+            case Wasm::F64:
+                if (numFPRs >= wasmCallingConvention().m_fprArgs.size()) {
+                    if (signature->argument(i) == Wasm::F32) {
+                        jit.load32(CCallHelpers::Address(GPRInfo::callFrameRegister, jsOffset), scratchReg);
+                        jit.store32(scratchReg, calleeFrame.withOffset(wasmOffset));
+                    } else {
+                        jit.load64(CCallHelpers::Address(GPRInfo::callFrameRegister, jsOffset), scratchReg);
+                        jit.store64(scratchReg, calleeFrame.withOffset(wasmOffset));
+                    }
+                    wasmOffset += sizeof(void*);
+                } else {
+                    if (signature->argument(i) == Wasm::F32)
+                        jit.loadFloat(CCallHelpers::Address(GPRInfo::callFrameRegister, jsOffset), wasmCallingConvention().m_fprArgs[numFPRs].fpr());
+                    else
+                        jit.loadDouble(CCallHelpers::Address(GPRInfo::callFrameRegister, jsOffset), wasmCallingConvention().m_fprArgs[numFPRs].fpr());
+                }
+                ++numFPRs;
+                break;
+            default:
+                RELEASE_ASSERT_NOT_REACHED();
+            }
 
-        patchpoint->setGenerator([context] (CCallHelpers& jit, const B3::StackmapGenerationParams&) {
-            AllowMacroScratchRegisterUsage allowScratch(jit);
+            jsOffset += sizeof(void*);
+        }
+    }
 
-            CCallHelpers::Call call = jit.call();
-            context->jsEntrypointToWasmEntrypointCall = call;
-        });
-    });
+    if (!!info.memory) {
+        GPRReg baseMemory = pinnedRegs.baseMemoryPointer;
+        jit.loadPtr(&vm.topJSWebAssemblyInstance, baseMemory);
+        jit.loadPtr(CCallHelpers::Address(baseMemory, JSWebAssemblyInstance::offsetOfMemory()), baseMemory);
+        const auto& sizeRegs = pinnedRegs.sizeRegisters;
+        ASSERT(sizeRegs.size() >= 1);
+        ASSERT(!sizeRegs[0].sizeOffset); // The following code assumes we start at 0, and calculates subsequent size registers relative to 0.
+        jit.loadPtr(CCallHelpers::Address(baseMemory, JSWebAssemblyMemory::offsetOfSize()), sizeRegs[0].sizeRegister);
+        jit.loadPtr(CCallHelpers::Address(baseMemory, JSWebAssemblyMemory::offsetOfMemory()), baseMemory);
+        for (unsigned i = 1; i < sizeRegs.size(); ++i)
+            jit.add64(CCallHelpers::TrustedImm32(-sizeRegs[i].sizeOffset), sizeRegs[0].sizeRegister, sizeRegs[i].sizeRegister);
+    }
 
-    // Return the result, if needed.
+    compilationContext.jsEntrypointToWasmEntrypointCall = jit.call();
+
+    for (const RegisterAtOffset& regAtOffset : registersToSpill) {
+        GPRReg reg = regAtOffset.reg().gpr();
+        ASSERT(reg != GPRInfo::returnValueGPR);
+        ptrdiff_t offset = regAtOffset.offset();
+        jit.loadPtr(CCallHelpers::Address(GPRInfo::callFrameRegister, offset), reg);
+    }
+
     switch (signature->returnType()) {
-    case Wasm::Void:
-        block->appendNewControlValue(proc, B3::Return, origin);
+    case Wasm::F32:
+        jit.moveFloatTo32(FPRInfo::returnValueFPR, GPRInfo::returnValueGPR);
         break;
-    case Wasm::F32:
     case Wasm::F64:
-        result = block->appendNew<Value>(proc, BitwiseCast, origin, result);
-        FALLTHROUGH;
-    case Wasm::I32:
-    case Wasm::I64:
-        block->appendNewControlValue(proc, B3::Return, origin, result);
+        jit.moveDoubleTo64(FPRInfo::returnValueFPR, GPRInfo::returnValueGPR);
         break;
-    case Wasm::Func:
-    case Wasm::Anyfunc:
-        RELEASE_ASSERT_NOT_REACHED();
+    default:
+        break;
     }
 
-    B3::prepareForGeneration(proc);
-    B3::generate(proc, *compilationContext.jsEntrypointJIT);
-    compilationContext.jsEntrypointByproducts = proc.releaseByproducts();
-    function.jsToWasmEntrypoint.calleeSaveRegisters = proc.calleeSaveRegisters();
+    jit.emitFunctionEpilogue();
+    jit.ret();
 }
 
 Expected<std::unique_ptr<WasmInternalFunction>, String> parseAndCompile(VM& vm, CompilationContext& compilationContext, const uint8_t* functionStart, size_t functionLength, const Signature* signature, Vector<UnlinkedWasmToWasmCall>& unlinkedWasmToWasmCalls, const ModuleInformation& info, const Vector<SignatureIndex>& moduleSignatureIndicesToUniquedSignatureIndices, unsigned optLevel)

Modified: trunk/Source/_javascript_Core/wasm/WasmCallingConvention.h (213744 => 213745)


--- trunk/Source/_javascript_Core/wasm/WasmCallingConvention.h	2017-03-11 01:56:08 UTC (rev 213744)
+++ trunk/Source/_javascript_Core/wasm/WasmCallingConvention.h	2017-03-11 02:04:37 UTC (rev 213745)
@@ -84,6 +84,7 @@
     }
 
 public:
+    static unsigned headerSizeInBytes() { return headerSize; }
     void setupFrameInPrologue(CodeLocationDataLabelPtr* calleeMoveLocation, B3::Procedure& proc, B3::Origin origin, B3::BasicBlock* block) const
     {
         static_assert(CallFrameSlot::callee * sizeof(Register) < headerSize, "We rely on this here for now.");

Modified: trunk/Source/_javascript_Core/wasm/js/JSWebAssemblyHelpers.h (213744 => 213745)


--- trunk/Source/_javascript_Core/wasm/js/JSWebAssemblyHelpers.h	2017-03-11 01:56:08 UTC (rev 213744)
+++ trunk/Source/_javascript_Core/wasm/js/JSWebAssemblyHelpers.h	2017-03-11 02:04:37 UTC (rev 213745)
@@ -29,6 +29,8 @@
 
 #include "JSArrayBuffer.h"
 #include "JSCJSValue.h"
+#include "WebAssemblyFunction.h"
+#include "WebAssemblyWrapperFunction.h"
 
 namespace JSC {
 
@@ -71,6 +73,36 @@
     return arrayBufferView ? static_cast<uint8_t*>(arrayBufferView->vector()) : static_cast<uint8_t*>(arrayBuffer->impl()->data());
 }
 
+ALWAYS_INLINE bool isWebAssemblyHostFunction(VM& vm, JSObject* object, WebAssemblyFunction*& wasmFunction, WebAssemblyWrapperFunction*& wasmWrapperFunction)
+{
+    if (object->inherits(vm, WebAssemblyFunction::info())) {
+        wasmFunction = jsCast<WebAssemblyFunction*>(object);
+        wasmWrapperFunction = nullptr;
+        return true;
+    }
+    if (object->inherits(vm, WebAssemblyWrapperFunction::info())) {
+        wasmWrapperFunction = jsCast<WebAssemblyWrapperFunction*>(object);
+        wasmFunction = nullptr;
+        return true;
+    }
+    return false;
+}
+
+ALWAYS_INLINE bool isWebAssemblyHostFunction(VM& vm, JSValue value, WebAssemblyFunction*& wasmFunction, WebAssemblyWrapperFunction*& wasmWrapperFunction)
+{
+    if (!value.isObject())
+        return false;
+    return isWebAssemblyHostFunction(vm, jsCast<JSObject*>(value), wasmFunction, wasmWrapperFunction);
+}
+
+
+ALWAYS_INLINE bool isWebAssemblyHostFunction(VM& vm, JSObject* object)
+{
+    WebAssemblyFunction* unused;
+    WebAssemblyWrapperFunction* unused2;
+    return isWebAssemblyHostFunction(vm, object, unused, unused2);
+}
+
 } // namespace JSC
 
 #endif // ENABLE(WEBASSEMBLY)

Modified: trunk/Source/_javascript_Core/wasm/js/JSWebAssemblyInstance.cpp (213744 => 213745)


--- trunk/Source/_javascript_Core/wasm/js/JSWebAssemblyInstance.cpp	2017-03-11 01:56:08 UTC (rev 213744)
+++ trunk/Source/_javascript_Core/wasm/js/JSWebAssemblyInstance.cpp	2017-03-11 02:04:37 UTC (rev 213745)
@@ -67,7 +67,7 @@
     : Base(vm, structure)
     , m_numImportFunctions(numImportFunctions)
 {
-    memset(importFunctions(), 0, m_numImportFunctions * sizeof(WriteBarrier<JSCell>));
+    memset(importFunctions(), 0, m_numImportFunctions * sizeof(WriteBarrier<JSObject>));
 }
 
 void JSWebAssemblyInstance::finishCreation(VM& vm, JSWebAssemblyModule* module, JSModuleNamespaceObject* moduleNamespaceObject)

Modified: trunk/Source/_javascript_Core/wasm/js/JSWebAssemblyInstance.h (213744 => 213745)


--- trunk/Source/_javascript_Core/wasm/js/JSWebAssemblyInstance.h	2017-03-11 01:56:08 UTC (rev 213744)
+++ trunk/Source/_javascript_Core/wasm/js/JSWebAssemblyInstance.h	2017-03-11 02:04:37 UTC (rev 213745)
@@ -60,18 +60,18 @@
         return m_codeBlock.get();
     }
 
-    WriteBarrier<JSCell>* importFunction(unsigned idx)
+    WriteBarrier<JSObject>* importFunction(unsigned idx)
     {
         RELEASE_ASSERT(idx < m_numImportFunctions);
         return &importFunctions()[idx];
     }
 
-    WriteBarrier<JSCell>* importFunctions()
+    WriteBarrier<JSObject>* importFunctions()
     {
-        return bitwise_cast<WriteBarrier<JSCell>*>(bitwise_cast<char*>(this) + offsetOfImportFunctions());
+        return bitwise_cast<WriteBarrier<JSObject>*>(bitwise_cast<char*>(this) + offsetOfImportFunctions());
     }
 
-    void setImportFunction(VM& vm, JSCell* value, unsigned idx)
+    void setImportFunction(VM& vm, JSObject* value, unsigned idx)
     {
         importFunction(idx)->set(vm, this, value);
     }

Modified: trunk/Source/_javascript_Core/wasm/js/JSWebAssemblyTable.cpp (213744 => 213745)


--- trunk/Source/_javascript_Core/wasm/js/JSWebAssemblyTable.cpp	2017-03-11 01:56:08 UTC (rev 213744)
+++ trunk/Source/_javascript_Core/wasm/js/JSWebAssemblyTable.cpp	2017-03-11 02:04:37 UTC (rev 213745)
@@ -64,11 +64,11 @@
     // FIXME: It might be worth trying to pre-allocate maximum here. The spec recommends doing so.
     // But for now, we're not doing that.
     m_functions = MallocPtr<Wasm::CallableFunction>::malloc(sizeof(Wasm::CallableFunction) * static_cast<size_t>(m_size));
-    m_jsFunctions = MallocPtr<WriteBarrier<WebAssemblyFunction>>::malloc(sizeof(WriteBarrier<WebAssemblyFunction>) * static_cast<size_t>(m_size));
+    m_jsFunctions = MallocPtr<WriteBarrier<JSObject>>::malloc(sizeof(WriteBarrier<JSObject>) * static_cast<size_t>(m_size));
     for (uint32_t i = 0; i < m_size; ++i) {
         new (&m_functions.get()[i]) Wasm::CallableFunction();
         ASSERT(m_functions.get()[i].signatureIndex == Wasm::Signature::invalidIndex); // We rely on this in compiled code.
-        new (&m_jsFunctions.get()[i]) WriteBarrier<WebAssemblyFunction>();
+        new (&m_jsFunctions.get()[i]) WriteBarrier<JSObject>();
     }
 }
 
@@ -106,11 +106,11 @@
         return false;
 
     m_functions.realloc(sizeof(Wasm::CallableFunction) * static_cast<size_t>(newSize));
-    m_jsFunctions.realloc(sizeof(WriteBarrier<WebAssemblyFunction>) * static_cast<size_t>(newSize));
+    m_jsFunctions.realloc(sizeof(WriteBarrier<JSObject>) * static_cast<size_t>(newSize));
 
     for (uint32_t i = m_size; i < newSize; ++i) {
         new (&m_functions.get()[i]) Wasm::CallableFunction();
-        new (&m_jsFunctions.get()[i]) WriteBarrier<WebAssemblyFunction>();
+        new (&m_jsFunctions.get()[i]) WriteBarrier<JSObject>();
     }
     m_size = newSize;
     return true;
@@ -119,7 +119,7 @@
 void JSWebAssemblyTable::clearFunction(uint32_t index)
 {
     RELEASE_ASSERT(index < m_size);
-    m_jsFunctions.get()[index] = WriteBarrier<WebAssemblyFunction>();
+    m_jsFunctions.get()[index] = WriteBarrier<JSObject>();
     m_functions.get()[index] = Wasm::CallableFunction();
     ASSERT(m_functions.get()[index].signatureIndex == Wasm::Signature::invalidIndex); // We rely on this in compiled code.
 }
@@ -131,6 +131,13 @@
     m_functions.get()[index] = Wasm::CallableFunction(function->signatureIndex(), function->wasmEntrypoint());
 }
 
+void JSWebAssemblyTable::setFunction(VM& vm, uint32_t index, WebAssemblyWrapperFunction* function)
+{
+    RELEASE_ASSERT(index < m_size);
+    m_jsFunctions.get()[index].set(vm, this, function);
+    m_functions.get()[index] = Wasm::CallableFunction(function->signatureIndex(), function->wasmEntrypoint());
+}
+
 } // namespace JSC
 
 #endif // ENABLE(WEBASSEMBLY)

Modified: trunk/Source/_javascript_Core/wasm/js/JSWebAssemblyTable.h (213744 => 213745)


--- trunk/Source/_javascript_Core/wasm/js/JSWebAssemblyTable.h	2017-03-11 01:56:08 UTC (rev 213744)
+++ trunk/Source/_javascript_Core/wasm/js/JSWebAssemblyTable.h	2017-03-11 02:04:37 UTC (rev 213745)
@@ -29,6 +29,7 @@
 
 #include "JSDestructibleObject.h"
 #include "JSObject.h"
+#include "WebAssemblyWrapperFunction.h"
 #include "WebAssemblyFunction.h"
 #include <wtf/MallocPtr.h>
 
@@ -50,7 +51,7 @@
     std::optional<uint32_t> maximum() const { return m_maximum; }
     uint32_t size() const { return m_size; }
     bool grow(uint32_t newSize) WARN_UNUSED_RETURN;
-    WebAssemblyFunction* getFunction(uint32_t index)
+    JSObject* getFunction(uint32_t index)
     {
         RELEASE_ASSERT(index < m_size);
         return m_jsFunctions.get()[index].get();
@@ -57,6 +58,7 @@
     }
     void clearFunction(uint32_t index);
     void setFunction(VM&, uint32_t index, WebAssemblyFunction*);
+    void setFunction(VM&, uint32_t index, WebAssemblyWrapperFunction*);
 
     static ptrdiff_t offsetOfSize() { return OBJECT_OFFSETOF(JSWebAssemblyTable, m_size); }
     static ptrdiff_t offsetOfFunctions() { return OBJECT_OFFSETOF(JSWebAssemblyTable, m_functions); }
@@ -74,7 +76,7 @@
     static void visitChildren(JSCell*, SlotVisitor&);
 
     MallocPtr<Wasm::CallableFunction> m_functions;
-    MallocPtr<WriteBarrier<WebAssemblyFunction>> m_jsFunctions;
+    MallocPtr<WriteBarrier<JSObject>> m_jsFunctions;
     std::optional<uint32_t> m_maximum;
     uint32_t m_size;
 };

Modified: trunk/Source/_javascript_Core/wasm/js/WebAssemblyInstanceConstructor.cpp (213744 => 213745)


--- trunk/Source/_javascript_Core/wasm/js/WebAssemblyInstanceConstructor.cpp	2017-03-11 01:56:08 UTC (rev 213744)
+++ trunk/Source/_javascript_Core/wasm/js/WebAssemblyInstanceConstructor.cpp	2017-03-11 02:04:37 UTC (rev 213745)
@@ -32,6 +32,7 @@
 #include "JSCInlines.h"
 #include "JSModuleEnvironment.h"
 #include "JSModuleNamespaceObject.h"
+#include "JSWebAssemblyHelpers.h"
 #include "JSWebAssemblyInstance.h"
 #include "JSWebAssemblyLinkError.h"
 #include "JSWebAssemblyMemory.h"
@@ -129,15 +130,23 @@
             if (!value.isFunction())
                 return exception(createJSWebAssemblyLinkError(exec, vm, ASCIILiteral("import function must be callable")));
 
-            JSCell* cell = value.asCell();
+            JSObject* function = jsCast<JSObject*>(value);
             // ii. If v is an Exported Function Exotic Object:
-            if (WebAssemblyFunction* importedExport = jsDynamicCast<WebAssemblyFunction*>(vm, cell)) {
+            WebAssemblyFunction* wasmFunction;
+            WebAssemblyWrapperFunction* wasmWrapperFunction;
+            if (isWebAssemblyHostFunction(vm, function, wasmFunction, wasmWrapperFunction)) {
                 // a. If the signature of v does not match the signature of i, throw a WebAssembly.LinkError.
-                Wasm::SignatureIndex importedSignatureIndex = importedExport->signatureIndex();
+                Wasm::SignatureIndex importedSignatureIndex;
+                if (wasmFunction)
+                    importedSignatureIndex = wasmFunction->signatureIndex();
+                else {
+                    importedSignatureIndex = wasmWrapperFunction->signatureIndex();
+                    // b. Let closure be v.[[Closure]].
+                    function = wasmWrapperFunction->function();
+                }
                 Wasm::SignatureIndex expectedSignatureIndex = moduleInformation.importFunctionSignatureIndices[import.kindIndex];
                 if (importedSignatureIndex != expectedSignatureIndex)
                     return exception(createJSWebAssemblyLinkError(exec, vm, ASCIILiteral("imported function's signature doesn't match the provided WebAssembly function's signature")));
-                // b. Let closure be v.[[Closure]].
             }
             // 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.
@@ -146,7 +155,7 @@
             // Note: adding the JSCell to the instance list fulfills closure requirements b. above (the WebAssembly.Instance wil be kept alive) and v. below (the JSFunction).
 
             ASSERT(numImportFunctions == import.kindIndex);
-            instance->setImportFunction(vm, cell, numImportFunctions++);
+            instance->setImportFunction(vm, function, numImportFunctions++);
             // v. Append closure to imports.
             break;
         }

Modified: trunk/Source/_javascript_Core/wasm/js/WebAssemblyModuleRecord.cpp (213744 => 213745)


--- trunk/Source/_javascript_Core/wasm/js/WebAssemblyModuleRecord.cpp	2017-03-11 01:56:08 UTC (rev 213744)
+++ trunk/Source/_javascript_Core/wasm/js/WebAssemblyModuleRecord.cpp	2017-03-11 02:04:37 UTC (rev 213745)
@@ -32,6 +32,7 @@
 #include "JSCInlines.h"
 #include "JSLexicalEnvironment.h"
 #include "JSModuleEnvironment.h"
+#include "JSWebAssemblyHelpers.h"
 #include "JSWebAssemblyInstance.h"
 #include "JSWebAssemblyLinkError.h"
 #include "JSWebAssemblyModule.h"
@@ -110,19 +111,26 @@
             //   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.kindIndex < functionImportCount) {
-                // FIXME Implement re-exporting an import. https://bugs.webkit.org/show_bug.cgi?id=165510
-                RELEASE_ASSERT_NOT_REACHED();
+                unsigned functionIndex = exp.kindIndex;
+                JSObject* functionImport = instance->importFunction(functionIndex)->get();
+                if (isWebAssemblyHostFunction(vm, functionImport))
+                    exportedValue = functionImport;
+                else {
+                    Wasm::SignatureIndex signatureIndex = module->signatureIndexFromFunctionIndexSpace(functionIndex);
+                    exportedValue = WebAssemblyWrapperFunction::create(vm, globalObject, functionImport, functionIndex, codeBlock, signatureIndex);
+                }
+            } else {
+                //   iii. Otherwise:
+                //     a. Let func be an Exported Function Exotic Object created from c.
+                //     b. Append func to funcs.
+                //     c. Return func.
+                JSWebAssemblyCallee* jsEntrypointCallee = codeBlock->jsEntrypointCalleeFromFunctionIndexSpace(exp.kindIndex);
+                JSWebAssemblyCallee* wasmEntrypointCallee = codeBlock->wasmEntrypointCalleeFromFunctionIndexSpace(exp.kindIndex);
+                Wasm::SignatureIndex signatureIndex = module->signatureIndexFromFunctionIndexSpace(exp.kindIndex);
+                const Wasm::Signature* signature = Wasm::SignatureInformation::get(&vm, signatureIndex);
+                WebAssemblyFunction* function = WebAssemblyFunction::create(vm, globalObject, signature->argumentCount(), exp.field.string(), instance, jsEntrypointCallee, wasmEntrypointCallee, signatureIndex);
+                exportedValue = function;
             }
-            //   iii. Otherwise:
-            //     a. Let func be an Exported Function Exotic Object created from c.
-            //     b. Append func to funcs.
-            //     c. Return func.
-            JSWebAssemblyCallee* jsEntrypointCallee = codeBlock->jsEntrypointCalleeFromFunctionIndexSpace(exp.kindIndex);
-            JSWebAssemblyCallee* wasmEntrypointCallee = codeBlock->wasmEntrypointCalleeFromFunctionIndexSpace(exp.kindIndex);
-            Wasm::SignatureIndex signatureIndex = module->signatureIndexFromFunctionIndexSpace(exp.kindIndex);
-            const Wasm::Signature* signature = Wasm::SignatureInformation::get(&vm, signatureIndex);
-            WebAssemblyFunction* function = WebAssemblyFunction::create(vm, globalObject, signature->argumentCount(), exp.field.string(), instance, jsEntrypointCallee, wasmEntrypointCallee, signatureIndex);
-            exportedValue = function;
             break;
         }
         case Wasm::ExternalKind::Table: {
@@ -184,7 +192,7 @@
         ASSERT(!signature->argumentCount());
         ASSERT(signature->returnType() == Wasm::Void);
         if (startFunctionIndexSpace < codeBlock->functionImportCount()) {
-            JSCell* startFunction = instance->importFunction(startFunctionIndexSpace)->get();
+            JSObject* startFunction = instance->importFunction(startFunctionIndexSpace)->get();
             m_startFunction.set(vm, this, startFunction);
         } else {
             JSWebAssemblyCallee* jsEntrypointCallee = codeBlock->jsEntrypointCalleeFromFunctionIndexSpace(startFunctionIndexSpace);
@@ -241,14 +249,28 @@
                 // for the import.
                 // https://bugs.webkit.org/show_bug.cgi?id=165510
                 uint32_t functionIndex = element.functionIndices[i];
+                Wasm::SignatureIndex signatureIndex = module->signatureIndexFromFunctionIndexSpace(functionIndex);
                 if (functionIndex < codeBlock->functionImportCount()) {
-                    return JSValue::decode(
-                        throwVMRangeError(state, scope, ASCIILiteral("Element is setting the table value with an import. This is not yet implemented. FIXME.")));
+                    JSObject* functionImport = jsCast<JSObject*>(m_instance->importFunction(functionIndex)->get());
+                    if (isWebAssemblyHostFunction(vm, functionImport)) {
+                        WebAssemblyFunction* wasmFunction = jsDynamicCast<WebAssemblyFunction*>(vm, functionImport);
+                        // If we ever import a WebAssemblyWrapperFunction, we set the import as the unwrapped value.
+                        // Because a WebAssemblyWrapperFunction can never wrap another WebAssemblyWrapperFunction,
+                        // the only type this could be is WebAssemblyFunction.
+                        RELEASE_ASSERT(wasmFunction);
+                        table->setFunction(vm, tableIndex, wasmFunction);
+                        ++tableIndex;
+                        continue;
+                    }
+
+                    table->setFunction(vm, tableIndex,
+                        WebAssemblyWrapperFunction::create(vm, m_instance->globalObject(), functionImport, functionIndex, codeBlock, signatureIndex));
+                    ++tableIndex;
+                    continue;
                 }
 
                 JSWebAssemblyCallee* jsEntrypointCallee = codeBlock->jsEntrypointCalleeFromFunctionIndexSpace(functionIndex);
                 JSWebAssemblyCallee* wasmEntrypointCallee = codeBlock->wasmEntrypointCalleeFromFunctionIndexSpace(functionIndex);
-                Wasm::SignatureIndex signatureIndex = module->signatureIndexFromFunctionIndexSpace(functionIndex);
                 const Wasm::Signature* signature = Wasm::SignatureInformation::get(&vm, signatureIndex);
                 // FIXME: Say we export local function "foo" at function index 0.
                 // What if we also set it to the table an Element w/ index 0.
@@ -288,7 +310,7 @@
         }
     }
 
-    if (JSCell* startFunction = m_startFunction.get()) {
+    if (JSObject* startFunction = m_startFunction.get()) {
         CallData callData;
         CallType callType = JSC::getCallData(startFunction, callData);
         call(state, startFunction, callType, callData, jsUndefined(), state->emptyList());

Modified: trunk/Source/_javascript_Core/wasm/js/WebAssemblyModuleRecord.h (213744 => 213745)


--- trunk/Source/_javascript_Core/wasm/js/WebAssemblyModuleRecord.h	2017-03-11 01:56:08 UTC (rev 213744)
+++ trunk/Source/_javascript_Core/wasm/js/WebAssemblyModuleRecord.h	2017-03-11 02:04:37 UTC (rev 213745)
@@ -59,7 +59,7 @@
     static void visitChildren(JSCell*, SlotVisitor&);
 
     WriteBarrier<JSWebAssemblyInstance> m_instance;
-    WriteBarrier<JSCell> m_startFunction;
+    WriteBarrier<JSObject> m_startFunction;
 };
 
 } // namespace JSC

Modified: trunk/Source/_javascript_Core/wasm/js/WebAssemblyTablePrototype.cpp (213744 => 213745)


--- trunk/Source/_javascript_Core/wasm/js/WebAssemblyTablePrototype.cpp	2017-03-11 01:56:08 UTC (rev 213744)
+++ trunk/Source/_javascript_Core/wasm/js/WebAssemblyTablePrototype.cpp	2017-03-11 02:04:37 UTC (rev 213745)
@@ -106,7 +106,7 @@
         return { };
     }
 
-    if (WebAssemblyFunction* result = table->getFunction(index))
+    if (JSObject* result = table->getFunction(index))
         return JSValue::encode(result);
     return JSValue::encode(jsNull());
 }
@@ -120,8 +120,9 @@
     RETURN_IF_EXCEPTION(throwScope, encodedJSValue());
 
     JSValue value = exec->argument(1);
-    WebAssemblyFunction* function = jsDynamicCast<WebAssemblyFunction*>(vm, value);
-    if (!value.isNull() && !function) {
+    WebAssemblyFunction* wasmFunction;
+    WebAssemblyWrapperFunction* wasmWrapperFunction;
+    if (!value.isNull() && !isWebAssemblyHostFunction(vm, value, wasmFunction, wasmWrapperFunction)) {
         throwException(exec, throwScope,
             createTypeError(exec, ASCIILiteral("WebAssembly.Table.prototype.set expects the second argument to be null or an instance of WebAssembly.Function")));
         return { };
@@ -139,8 +140,12 @@
     if (value.isNull())
         table->clearFunction(index);
     else {
-        ASSERT(!!function);
-        table->setFunction(vm, index, function);
+        ASSERT(value.isObject() && isWebAssemblyHostFunction(vm, jsCast<JSObject*>(value), wasmFunction, wasmWrapperFunction));
+        ASSERT(!!wasmFunction || !!wasmWrapperFunction);
+        if (wasmFunction)
+            table->setFunction(vm, index, wasmFunction);
+        else
+            table->setFunction(vm, index, wasmWrapperFunction);
     }
     
     return JSValue::encode(jsUndefined());

Added: trunk/Source/_javascript_Core/wasm/js/WebAssemblyWrapperFunction.cpp (0 => 213745)


--- trunk/Source/_javascript_Core/wasm/js/WebAssemblyWrapperFunction.cpp	                        (rev 0)
+++ trunk/Source/_javascript_Core/wasm/js/WebAssemblyWrapperFunction.cpp	2017-03-11 02:04:37 UTC (rev 213745)
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2017 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 "WebAssemblyWrapperFunction.h"
+
+#if ENABLE(WEBASSEMBLY)
+
+#include "Error.h"
+#include "FunctionPrototype.h"
+#include "JSCInlines.h"
+
+namespace JSC {
+
+const ClassInfo WebAssemblyWrapperFunction::s_info = { "WebAssemblyWrapperFunction", &Base::s_info, nullptr, CREATE_METHOD_TABLE(WebAssemblyWrapperFunction) };
+
+static EncodedJSValue JSC_HOST_CALL callWebAssemblyWrapperFunction(ExecState* exec)
+{
+    VM& vm = exec->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
+    WebAssemblyWrapperFunction* wasmFunction = jsDynamicCast<WebAssemblyWrapperFunction*>(vm, exec->jsCallee());
+    if (!wasmFunction)
+        return JSValue::encode(throwException(exec, scope, createTypeError(exec, "expected a WebAssembly function")));
+
+    CallData callData;
+    JSObject* function = wasmFunction->function();
+    CallType callType = function->methodTable(vm)->getCallData(function, callData);
+    RELEASE_ASSERT(callType != CallType::None);
+    scope.release();
+    return JSValue::encode(call(exec, function, callType, callData, jsUndefined(), ArgList(exec)));
+}
+
+WebAssemblyWrapperFunction::WebAssemblyWrapperFunction(VM& vm, JSGlobalObject* globalObject, Structure* structure, Wasm::SignatureIndex signatureIndex, void* wasmEntrypointCode)
+    : Base(vm, globalObject, structure)
+    , m_wasmEntrypointCode(wasmEntrypointCode)
+    , m_signatureIndex(signatureIndex)
+{ }
+
+WebAssemblyWrapperFunction* WebAssemblyWrapperFunction::create(VM& vm, JSGlobalObject* globalObject, JSObject* function, unsigned importIndex, JSWebAssemblyCodeBlock* codeBlock, Wasm::SignatureIndex signatureIndex)
+{
+    ASSERT_WITH_MESSAGE(!function->inherits(vm, WebAssemblyWrapperFunction::info()), "We should never double wrap a wrapper function.");
+    String name = "";
+    NativeExecutable* executable = vm.getHostFunction(callWebAssemblyWrapperFunction, NoIntrinsic, callHostFunctionAsConstructor, nullptr, name);
+    WebAssemblyWrapperFunction* result = new (NotNull, allocateCell<WebAssemblyWrapperFunction>(vm.heap)) WebAssemblyWrapperFunction(vm, globalObject, globalObject->webAssemblyWrapperFunctionStructure(), signatureIndex, codeBlock->wasmToJsCallStubForImport(importIndex));
+    const Wasm::Signature* signature = Wasm::SignatureInformation::get(&vm, signatureIndex);
+    result->finishCreation(vm, executable, signature->argumentCount(), name, function, codeBlock);
+    return result;
+}
+
+void WebAssemblyWrapperFunction::finishCreation(VM& vm, NativeExecutable* executable, unsigned length, const String& name, JSObject* function, JSWebAssemblyCodeBlock* codeBlock)
+{
+    Base::finishCreation(vm, executable, length, name);
+    RELEASE_ASSERT(JSValue(function).isFunction());
+    m_function.set(vm, this, function);
+    m_codeBlock.set(vm, this, codeBlock);
+}
+
+Structure* WebAssemblyWrapperFunction::createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
+{
+    ASSERT(globalObject);
+    return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
+}
+
+void WebAssemblyWrapperFunction::visitChildren(JSCell* cell, SlotVisitor& visitor)
+{
+    WebAssemblyWrapperFunction* thisObject = jsCast<WebAssemblyWrapperFunction*>(cell);
+    ASSERT_GC_OBJECT_INHERITS(thisObject, info());
+    Base::visitChildren(thisObject, visitor);
+
+    visitor.append(thisObject->m_codeBlock);
+    visitor.append(thisObject->m_function);
+}
+
+} // namespace JSC
+
+#endif // ENABLE(WEBASSEMBLY)

Copied: trunk/Source/_javascript_Core/wasm/js/WebAssemblyWrapperFunction.h (from rev 213744, trunk/Source/_javascript_Core/wasm/js/WebAssemblyModuleRecord.h) (0 => 213745)


--- trunk/Source/_javascript_Core/wasm/js/WebAssemblyWrapperFunction.h	                        (rev 0)
+++ trunk/Source/_javascript_Core/wasm/js/WebAssemblyWrapperFunction.h	2017-03-11 02:04:37 UTC (rev 213745)
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2017 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 "JSFunction.h"
+#include "JSWebAssemblyCodeBlock.h"
+
+namespace JSC {
+
+class WebAssemblyWrapperFunction : public JSFunction {
+public:
+    typedef JSFunction Base;
+
+    const static unsigned StructureFlags = Base::StructureFlags;
+
+    DECLARE_INFO;
+
+    static WebAssemblyWrapperFunction* create(VM&, JSGlobalObject*, JSObject*, unsigned importIndex, JSWebAssemblyCodeBlock*, Wasm::SignatureIndex);
+    static Structure* createStructure(VM&, JSGlobalObject*, JSValue);
+
+    Wasm::SignatureIndex signatureIndex() const { return m_signatureIndex; }
+    void* wasmEntrypoint() { return m_wasmEntrypointCode; }
+    JSObject* function() { return m_function.get(); }
+
+protected:
+    static void visitChildren(JSCell*, SlotVisitor&);
+
+    void finishCreation(VM&, NativeExecutable*, unsigned length, const String& name, JSObject*, JSWebAssemblyCodeBlock*);
+
+private:
+    WebAssemblyWrapperFunction(VM&, JSGlobalObject*, Structure*, Wasm::SignatureIndex, void* wasmEntrypointCode);
+
+    // We keep a reference to our CodeBlock because we have a raw
+    // pointer to asm code that it owns.
+    WriteBarrier<JSWebAssemblyCodeBlock> m_codeBlock;
+    WriteBarrier<JSObject> m_function;
+    void* m_wasmEntrypointCode;
+    Wasm::SignatureIndex m_signatureIndex;
+};
+
+} // namespace JSC
+
+#endif // ENABLE(WEBASSEMBLY)
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to