| Differences between
and this patch
- JSTests/ChangeLog +17 lines
Lines 1-3 JSTests/ChangeLog_sec1
1
2017-03-10  Saam Barati  <sbarati@apple.com>
2
3
        WebAssembly: Make more demos run
4
        https://bugs.webkit.org/show_bug.cgi?id=165510
5
        <rdar://problem/29760310>
6
7
        Reviewed by Keith Miller.
8
9
        * wasm/Builder.js:
10
        (export.default.Builder.prototype._registerSectionBuilders.const.section.in.WASM.description.section.switch.section.case.string_appeared_here.this.section):
11
        * wasm/js-api/wrapper-function.js: Added.
12
        (exportImport):
13
        (return.new.WebAssembly.Module):
14
        (assert.throws.makeInstance):
15
        (assert.throws.Bar):
16
        (assert.throws):
17
1
2017-03-09  Caio Lima  <ticaiolima@gmail.com>
18
2017-03-09  Caio Lima  <ticaiolima@gmail.com>
2
19
3
        [ESnext] Implement Object Rest - Implementing Object Rest Destructuring
20
        [ESnext] Implement Object Rest - Implementing Object Rest Destructuring
- JSTests/wasm/Builder.js -1 / +4 lines
Lines 579-585 export default class Builder { JSTests/wasm/Builder.js_sec1
579
                break;
579
                break;
580
580
581
            case "Element":
581
            case "Element":
582
                this[section] = function() {
582
                this[section] = function(...args) {
583
                    if (args.length !== 0)
584
                        throw new Error("You're doing it wrong. This element does not take arguments. You must chain the call with another Element()");
585
583
                    const s = this._addSection(section);
586
                    const s = this._addSection(section);
584
                    const elementBuilder = {
587
                    const elementBuilder = {
585
                        End: () => this,
588
                        End: () => this,
- JSTests/wasm/js-api/wrapper-function.js +146 lines
Line 0 JSTests/wasm/js-api/wrapper-function.js_sec1
1
import Builder from '../Builder.js';
2
import * as assert from '../assert.js';
3
4
5
function exportImport(type) {
6
    let builder = (new Builder())
7
        .Type().End()
8
        .Import()
9
            .Function("imp", "f", type)
10
        .End()
11
        .Function().End()
12
        .Export()
13
            .Function("func", {module: "imp", field: "f"})
14
        .End()
15
        .Code().End();
16
    return new WebAssembly.Module(builder.WebAssembly().get());
17
}
18
19
{
20
    let type = { params: ["i32"], ret: "i32" };
21
    let module = exportImport(type);
22
    let called = false;
23
    let foo = (i) => {
24
        called = true;
25
        return i + 42;
26
    };
27
    let instance = new WebAssembly.Instance(module, {imp: {f: foo}});
28
    assert.truthy(instance.exports.func !== foo);
29
    for (let i = 0; i < 100; i++) {
30
        let r1 = instance.exports.func(i);
31
        assert.truthy(called);
32
        called = false;
33
        let r2 = foo(i);
34
        called = false;
35
        assert.eq(r1, r2);
36
    }
37
38
    {
39
        let builder = (new Builder())
40
            .Type().End()
41
            .Import()
42
                .Function("imp", "f", {params: []})
43
            .End()
44
            .Function().End()
45
            .Code().End();
46
        let module = new WebAssembly.Module(builder.WebAssembly().get());
47
        // This should not type check.
48
        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");
49
    }
50
51
}
52
53
{
54
    const tableDescription = {element: "anyfunc", initial: 2};
55
    function makeInstance(type, imp) {
56
        const builder = new Builder()
57
            .Type()
58
                .Func(["i32"], "i32")
59
                .Func(["i32", "i32"], "i32")
60
            .End()
61
            .Import()
62
                .Table("imp", "table", tableDescription)
63
                .Function("imp", "f1", {params: ["i32"], ret:"i32"})
64
                .Function("imp", "f2", {params: ["i32", "i32"], ret:"i32"})
65
            .End()
66
            .Function().End()
67
            .Export()
68
                .Function("foo")
69
            .End()
70
            .Element()
71
                .Element({offset: 0, functionIndices: [0, 1]})
72
            .End()
73
            .Code()
74
                .Function("foo", 1)
75
                    .GetLocal(1) // parameter to call
76
                    .GetLocal(0) // call index
77
                    .CallIndirect(0, 0) // calling function of type ['i32'] => 'i32'
78
                    .Return()
79
                .End()
80
            .End();
81
        let module = new WebAssembly.Module(builder.WebAssembly().get());
82
        return new WebAssembly.Instance(module, imp);
83
    }
84
85
    function Bar(){};
86
    noInline(Bar);
87
    let called = false;
88
    let foo = (i) => {
89
        called = true;
90
        new Bar;
91
        return i*42;
92
    }
93
    let table = new WebAssembly.Table(tableDescription);
94
    let inst = makeInstance({params:['i32'], ret:"i32"}, {imp: {f1: foo, f2:foo, table}});
95
    for (let i = 0; i < 1000; i++) {
96
        let r1 = inst.exports.foo(0, i);
97
        assert.truthy(called);
98
        called = false;
99
        let r2 = foo(i);
100
        assert.truthy(called);
101
        called = false;
102
        assert.eq(r1, r2);
103
    }
104
    for (let i = 0; i < 1000; i++) {
105
        assert.throws(() => inst.exports.foo(1, i), WebAssembly.RuntimeError, "call_indirect to a signature that does not match");
106
        assert.truthy(!called);
107
    }
108
    for (let i = 0; i < 1000; i++) {
109
        let r1 = table.get(0)(i);
110
        table.set(0, table.get(0)); // just make sure setting a wrapper function works.
111
        assert.truthy(called);
112
        called = false;
113
        let r2 = table.get(1)(i);
114
        assert.truthy(called);
115
        called = false;
116
        assert.eq(r1, r2);
117
    }
118
119
    {
120
        let nextInst = makeInstance({params:['i32'], ret:"i32"}, {imp: {f1: table.get(0), f2:inst.exports.foo, table}});
121
        for (let i = 0; i < 1000; i++) {
122
            let r1 = nextInst.exports.foo(0, i);
123
            assert.truthy(called);
124
            called = false;
125
            let r2 = foo(i);
126
            assert.truthy(called);
127
            called = false;
128
            assert.eq(r1, r2);
129
        }
130
131
        for (let i = 0; i < 1000; i++) {
132
            assert.throws(() => nextInst.exports.foo(1, i), WebAssembly.RuntimeError, "call_indirect to a signature that does not match");
133
            assert.truthy(!called);
134
        }
135
136
        for (let i = 0; i < 1000; i++) {
137
            let r1 = table.get(1)(0, i);
138
            assert.truthy(called);
139
            called = false;
140
            let r2 = foo(i);
141
            assert.truthy(called);
142
            called = false;
143
            assert.eq(r1, r2);
144
        }
145
    }
146
}
- Source/JavaScriptCore/ChangeLog +80 lines
Lines 1-3 Source/JavaScriptCore/ChangeLog_sec1
1
2017-03-10  Saam Barati  <sbarati@apple.com>
2
3
        WebAssembly: Make more demos run
4
        https://bugs.webkit.org/show_bug.cgi?id=165510
5
        <rdar://problem/29760310>
6
7
        Reviewed by Keith Miller.
8
9
        This patch makes another Wasm demo run:
10
        https://kripken.github.io/BananaBread/cube2/bb.html
11
        
12
        This patch fixes two bugs:
13
        1. When WebAssemblyFunctionType was added, we did not properly
14
        update the last JS type value.
15
        2. Our code for our JS -> Wasm entrypoint was wrong. It lead to bad
16
        code generation where we would emit B3 that would write over r12
17
        and rbx (on x86) which is invalid since those are our pinned registers.
18
        This patch just rewrites the entrypoint to use hand written assembler
19
        code. I was planning on doing this anyways because it's a compile
20
        time speed boost.
21
        
22
        Also, this patch adds support for some new API features:
23
        We can now export an import, either via a direct export, or via a Table and the
24
        Element section. I've added a new class called WebAssemblyWrapperFunction that
25
        just wraps over a JSObject that is a function. Wrapper functions have types
26
        associated with them, so if they're re-imported, or called via call_indirect,
27
        they can be type checked.
28
29
        * CMakeLists.txt:
30
        * JavaScriptCore.xcodeproj/project.pbxproj:
31
        * runtime/JSGlobalObject.cpp:
32
        (JSC::JSGlobalObject::init):
33
        (JSC::JSGlobalObject::visitChildren):
34
        * runtime/JSGlobalObject.h:
35
        (JSC::JSGlobalObject::webAssemblyWrapperFunctionStructure):
36
        * runtime/JSType.h:
37
        * wasm/JSWebAssemblyCodeBlock.h:
38
        (JSC::JSWebAssemblyCodeBlock::wasmToJsCallStubForImport):
39
        * wasm/WasmB3IRGenerator.cpp:
40
        (JSC::Wasm::createJSToWasmWrapper):
41
        * wasm/WasmCallingConvention.h:
42
        (JSC::Wasm::CallingConvention::headerSizeInBytes):
43
        * wasm/js/JSWebAssemblyHelpers.h:
44
        (JSC::isWebAssemblyHostFunction):
45
        * wasm/js/JSWebAssemblyInstance.cpp:
46
        (JSC::JSWebAssemblyInstance::JSWebAssemblyInstance):
47
        * wasm/js/JSWebAssemblyInstance.h:
48
        (JSC::JSWebAssemblyInstance::importFunction):
49
        (JSC::JSWebAssemblyInstance::importFunctions):
50
        (JSC::JSWebAssemblyInstance::setImportFunction):
51
        * wasm/js/JSWebAssemblyTable.cpp:
52
        (JSC::JSWebAssemblyTable::JSWebAssemblyTable):
53
        (JSC::JSWebAssemblyTable::grow):
54
        (JSC::JSWebAssemblyTable::clearFunction):
55
        (JSC::JSWebAssemblyTable::setFunction):
56
        * wasm/js/JSWebAssemblyTable.h:
57
        (JSC::JSWebAssemblyTable::getFunction):
58
        * wasm/js/WebAssemblyFunction.cpp:
59
        (JSC::callWebAssemblyFunction):
60
        * wasm/js/WebAssemblyInstanceConstructor.cpp:
61
        (JSC::WebAssemblyInstanceConstructor::createInstance):
62
        * wasm/js/WebAssemblyModuleRecord.cpp:
63
        (JSC::WebAssemblyModuleRecord::link):
64
        (JSC::WebAssemblyModuleRecord::evaluate):
65
        * wasm/js/WebAssemblyModuleRecord.h:
66
        * wasm/js/WebAssemblyTablePrototype.cpp:
67
        (JSC::webAssemblyTableProtoFuncGet):
68
        (JSC::webAssemblyTableProtoFuncSet):
69
        * wasm/js/WebAssemblyWrapperFunction.cpp: Added.
70
        (JSC::callWebAssemblyWrapperFunction):
71
        (JSC::WebAssemblyWrapperFunction::WebAssemblyWrapperFunction):
72
        (JSC::WebAssemblyWrapperFunction::create):
73
        (JSC::WebAssemblyWrapperFunction::finishCreation):
74
        (JSC::WebAssemblyWrapperFunction::createStructure):
75
        (JSC::WebAssemblyWrapperFunction::visitChildren):
76
        * wasm/js/WebAssemblyWrapperFunction.h: Added.
77
        (JSC::WebAssemblyWrapperFunction::signatureIndex):
78
        (JSC::WebAssemblyWrapperFunction::wasmEntrypoint):
79
        (JSC::WebAssemblyWrapperFunction::function):
80
1
2017-03-04  Filip Pizlo  <fpizlo@apple.com>
81
2017-03-04  Filip Pizlo  <fpizlo@apple.com>
2
82
3
        B3 should have comprehensive support for atomic operations
83
        B3 should have comprehensive support for atomic operations
- Source/JavaScriptCore/CMakeLists.txt +1 lines
Lines 967-972 set(JavaScriptCore_SOURCES Source/JavaScriptCore/CMakeLists.txt_sec1
967
    wasm/js/WebAssemblyTableConstructor.cpp
967
    wasm/js/WebAssemblyTableConstructor.cpp
968
    wasm/js/WebAssemblyTablePrototype.cpp
968
    wasm/js/WebAssemblyTablePrototype.cpp
969
    wasm/js/WebAssemblyToJSCallee.cpp
969
    wasm/js/WebAssemblyToJSCallee.cpp
970
    wasm/js/WebAssemblyWrapperFunction.cpp
970
971
971
    yarr/RegularExpression.cpp
972
    yarr/RegularExpression.cpp
972
    yarr/YarrCanonicalizeUCS2.cpp
973
    yarr/YarrCanonicalizeUCS2.cpp
- Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj +8 lines
Lines 1312-1317 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec1
1312
		52C0611F1AA51E1C00B4ADBA /* RuntimeType.h in Headers */ = {isa = PBXBuildFile; fileRef = 52C0611D1AA51E1B00B4ADBA /* RuntimeType.h */; settings = {ATTRIBUTES = (Private, ); }; };
1312
		52C0611F1AA51E1C00B4ADBA /* RuntimeType.h in Headers */ = {isa = PBXBuildFile; fileRef = 52C0611D1AA51E1B00B4ADBA /* RuntimeType.h */; settings = {ATTRIBUTES = (Private, ); }; };
1313
		52C952B719A289850069B386 /* TypeProfiler.h in Headers */ = {isa = PBXBuildFile; fileRef = 52C952B619A289850069B386 /* TypeProfiler.h */; settings = {ATTRIBUTES = (Private, ); }; };
1313
		52C952B719A289850069B386 /* TypeProfiler.h in Headers */ = {isa = PBXBuildFile; fileRef = 52C952B619A289850069B386 /* TypeProfiler.h */; settings = {ATTRIBUTES = (Private, ); }; };
1314
		52C952B919A28A1C0069B386 /* TypeProfiler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 52C952B819A28A1C0069B386 /* TypeProfiler.cpp */; };
1314
		52C952B919A28A1C0069B386 /* TypeProfiler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 52C952B819A28A1C0069B386 /* TypeProfiler.cpp */; };
1315
		52F6C35D1E71EB080081F4CC /* WebAssemblyWrapperFunction.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 52F6C35B1E71EB080081F4CC /* WebAssemblyWrapperFunction.cpp */; };
1316
		52F6C35E1E71EB080081F4CC /* WebAssemblyWrapperFunction.h in Headers */ = {isa = PBXBuildFile; fileRef = 52F6C35C1E71EB080081F4CC /* WebAssemblyWrapperFunction.h */; settings = {ATTRIBUTES = (Private, ); }; };
1315
		531374BD1D5CE67600AF7A0B /* WasmPlan.h in Headers */ = {isa = PBXBuildFile; fileRef = 531374BC1D5CE67600AF7A0B /* WasmPlan.h */; };
1317
		531374BD1D5CE67600AF7A0B /* WasmPlan.h in Headers */ = {isa = PBXBuildFile; fileRef = 531374BC1D5CE67600AF7A0B /* WasmPlan.h */; };
1316
		531374BF1D5CE95000AF7A0B /* WasmPlan.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 531374BE1D5CE95000AF7A0B /* WasmPlan.cpp */; };
1318
		531374BF1D5CE95000AF7A0B /* WasmPlan.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 531374BE1D5CE95000AF7A0B /* WasmPlan.cpp */; };
1317
		533B15DF1DC7F463004D500A /* WasmOps.h in Headers */ = {isa = PBXBuildFile; fileRef = 533B15DE1DC7F463004D500A /* WasmOps.h */; settings = {ATTRIBUTES = (Private, ); }; };
1319
		533B15DF1DC7F463004D500A /* WasmOps.h in Headers */ = {isa = PBXBuildFile; fileRef = 533B15DE1DC7F463004D500A /* WasmOps.h */; settings = {ATTRIBUTES = (Private, ); }; };
Lines 3787-3792 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec2
3787
		52C0611D1AA51E1B00B4ADBA /* RuntimeType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RuntimeType.h; sourceTree = "<group>"; };
3789
		52C0611D1AA51E1B00B4ADBA /* RuntimeType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RuntimeType.h; sourceTree = "<group>"; };
3788
		52C952B619A289850069B386 /* TypeProfiler.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TypeProfiler.h; sourceTree = "<group>"; };
3790
		52C952B619A289850069B386 /* TypeProfiler.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TypeProfiler.h; sourceTree = "<group>"; };
3789
		52C952B819A28A1C0069B386 /* TypeProfiler.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = TypeProfiler.cpp; sourceTree = "<group>"; };
3791
		52C952B819A28A1C0069B386 /* TypeProfiler.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = TypeProfiler.cpp; sourceTree = "<group>"; };
3792
		52F6C35B1E71EB080081F4CC /* WebAssemblyWrapperFunction.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = WebAssemblyWrapperFunction.cpp; path = js/WebAssemblyWrapperFunction.cpp; sourceTree = "<group>"; };
3793
		52F6C35C1E71EB080081F4CC /* WebAssemblyWrapperFunction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = WebAssemblyWrapperFunction.h; path = js/WebAssemblyWrapperFunction.h; sourceTree = "<group>"; };
3790
		531374BC1D5CE67600AF7A0B /* WasmPlan.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WasmPlan.h; sourceTree = "<group>"; };
3794
		531374BC1D5CE67600AF7A0B /* WasmPlan.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WasmPlan.h; sourceTree = "<group>"; };
3791
		531374BE1D5CE95000AF7A0B /* WasmPlan.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WasmPlan.cpp; sourceTree = "<group>"; };
3795
		531374BE1D5CE95000AF7A0B /* WasmPlan.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WasmPlan.cpp; sourceTree = "<group>"; };
3792
		533B15DE1DC7F463004D500A /* WasmOps.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WasmOps.h; sourceTree = "<group>"; };
3796
		533B15DE1DC7F463004D500A /* WasmOps.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WasmOps.h; sourceTree = "<group>"; };
Lines 7902-7907 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec3
7902
				AD2FCBC31DB58DA400B3E736 /* WebAssemblyTablePrototype.h */,
7906
				AD2FCBC31DB58DA400B3E736 /* WebAssemblyTablePrototype.h */,
7903
				ADBC54D21DF8EA00005BF738 /* WebAssemblyToJSCallee.cpp */,
7907
				ADBC54D21DF8EA00005BF738 /* WebAssemblyToJSCallee.cpp */,
7904
				ADBC54D31DF8EA00005BF738 /* WebAssemblyToJSCallee.h */,
7908
				ADBC54D31DF8EA00005BF738 /* WebAssemblyToJSCallee.h */,
7909
				52F6C35B1E71EB080081F4CC /* WebAssemblyWrapperFunction.cpp */,
7910
				52F6C35C1E71EB080081F4CC /* WebAssemblyWrapperFunction.h */,
7905
			);
7911
			);
7906
			name = js;
7912
			name = js;
7907
			sourceTree = "<group>";
7913
			sourceTree = "<group>";
Lines 8239-8244 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec4
8239
				0F21C27D14BE727A00ADC64B /* CodeSpecializationKind.h in Headers */,
8245
				0F21C27D14BE727A00ADC64B /* CodeSpecializationKind.h in Headers */,
8240
				0F0B83A714BCF50700885B4F /* CodeType.h in Headers */,
8246
				0F0B83A714BCF50700885B4F /* CodeType.h in Headers */,
8241
				0FA762051DB9242900B7A2FD /* CollectionScope.h in Headers */,
8247
				0FA762051DB9242900B7A2FD /* CollectionScope.h in Headers */,
8248
				52F6C35E1E71EB080081F4CC /* WebAssemblyWrapperFunction.h in Headers */,
8242
				A53243981856A489002ED692 /* CombinedDomains.json in Headers */,
8249
				A53243981856A489002ED692 /* CombinedDomains.json in Headers */,
8243
				BC18C3F30E16F5CD00B34460 /* CommonIdentifiers.h in Headers */,
8250
				BC18C3F30E16F5CD00B34460 /* CommonIdentifiers.h in Headers */,
8244
				0F15F15F14B7A73E005DE37D /* CommonSlowPaths.h in Headers */,
8251
				0F15F15F14B7A73E005DE37D /* CommonSlowPaths.h in Headers */,
Lines 10350-10355 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec5
10350
				A503FA19188E0FB000110F14 /* JavaScriptCallFrame.cpp in Sources */,
10357
				A503FA19188E0FB000110F14 /* JavaScriptCallFrame.cpp in Sources */,
10351
				1429D92F0ED22D7000B89619 /* JIT.cpp in Sources */,
10358
				1429D92F0ED22D7000B89619 /* JIT.cpp in Sources */,
10352
				FE1220281BE7F5910039E6F2 /* JITAddGenerator.cpp in Sources */,
10359
				FE1220281BE7F5910039E6F2 /* JITAddGenerator.cpp in Sources */,
10360
				52F6C35D1E71EB080081F4CC /* WebAssemblyWrapperFunction.cpp in Sources */,
10353
				86A90ED00EE7D51F00AB350D /* JITArithmetic.cpp in Sources */,
10361
				86A90ED00EE7D51F00AB350D /* JITArithmetic.cpp in Sources */,
10354
				A75706DE118A2BCF0057F88F /* JITArithmetic32_64.cpp in Sources */,
10362
				A75706DE118A2BCF0057F88F /* JITArithmetic32_64.cpp in Sources */,
10355
				FE3A06B11C10CB8400390FDD /* JITBitAndGenerator.cpp in Sources */,
10363
				FE3A06B11C10CB8400390FDD /* JITBitAndGenerator.cpp in Sources */,
- Source/JavaScriptCore/runtime/JSGlobalObject.cpp +2 lines
Lines 892-897 putDirectWithoutTransition(vm, vm.proper Source/JavaScriptCore/runtime/JSGlobalObject.cpp_sec1
892
        m_webAssemblyStructure.set(vm, this, JSWebAssembly::createStructure(vm, this, webAssemblyPrototype));
892
        m_webAssemblyStructure.set(vm, this, JSWebAssembly::createStructure(vm, this, webAssemblyPrototype));
893
        m_webAssemblyModuleRecordStructure.set(vm, this, WebAssemblyModuleRecord::createStructure(vm, this, m_objectPrototype.get()));
893
        m_webAssemblyModuleRecordStructure.set(vm, this, WebAssemblyModuleRecord::createStructure(vm, this, m_objectPrototype.get()));
894
        m_webAssemblyFunctionStructure.set(vm, this, WebAssemblyFunction::createStructure(vm, this, m_functionPrototype.get()));
894
        m_webAssemblyFunctionStructure.set(vm, this, WebAssemblyFunction::createStructure(vm, this, m_functionPrototype.get()));
895
        m_webAssemblyWrapperFunctionStructure.set(vm, this, WebAssemblyWrapperFunction::createStructure(vm, this, m_functionPrototype.get()));
895
        auto* webAssembly = JSWebAssembly::create(vm, this, m_webAssemblyStructure.get());
896
        auto* webAssembly = JSWebAssembly::create(vm, this, m_webAssemblyStructure.get());
896
        putDirectWithoutTransition(vm, Identifier::fromString(exec, "WebAssembly"), webAssembly, DontEnum);
897
        putDirectWithoutTransition(vm, Identifier::fromString(exec, "WebAssembly"), webAssembly, DontEnum);
897
898
Lines 1272-1277 void JSGlobalObject::visitChildren(JSCel Source/JavaScriptCore/runtime/JSGlobalObject.cpp_sec2
1272
    visitor.append(thisObject->m_webAssemblyStructure);
1273
    visitor.append(thisObject->m_webAssemblyStructure);
1273
    visitor.append(thisObject->m_webAssemblyModuleRecordStructure);
1274
    visitor.append(thisObject->m_webAssemblyModuleRecordStructure);
1274
    visitor.append(thisObject->m_webAssemblyFunctionStructure);
1275
    visitor.append(thisObject->m_webAssemblyFunctionStructure);
1276
    visitor.append(thisObject->m_webAssemblyWrapperFunctionStructure);
1275
    FOR_EACH_WEBASSEMBLY_CONSTRUCTOR_TYPE(VISIT_SIMPLE_TYPE)
1277
    FOR_EACH_WEBASSEMBLY_CONSTRUCTOR_TYPE(VISIT_SIMPLE_TYPE)
1276
#endif // ENABLE(WEBASSEMBLY)
1278
#endif // ENABLE(WEBASSEMBLY)
1277
1279
- Source/JavaScriptCore/runtime/JSGlobalObject.h +2 lines
Lines 345-350 public: Source/JavaScriptCore/runtime/JSGlobalObject.h_sec1
345
    WriteBarrier<Structure> m_webAssemblyStructure;
345
    WriteBarrier<Structure> m_webAssemblyStructure;
346
    WriteBarrier<Structure> m_webAssemblyModuleRecordStructure;
346
    WriteBarrier<Structure> m_webAssemblyModuleRecordStructure;
347
    WriteBarrier<Structure> m_webAssemblyFunctionStructure;
347
    WriteBarrier<Structure> m_webAssemblyFunctionStructure;
348
    WriteBarrier<Structure> m_webAssemblyWrapperFunctionStructure;
348
    FOR_EACH_WEBASSEMBLY_CONSTRUCTOR_TYPE(DEFINE_STORAGE_FOR_SIMPLE_TYPE)
349
    FOR_EACH_WEBASSEMBLY_CONSTRUCTOR_TYPE(DEFINE_STORAGE_FOR_SIMPLE_TYPE)
349
#endif // ENABLE(WEBASSEMBLY)
350
#endif // ENABLE(WEBASSEMBLY)
350
351
Lines 612-617 public: Source/JavaScriptCore/runtime/JSGlobalObject.h_sec2
612
#if ENABLE(WEBASSEMBLY)
613
#if ENABLE(WEBASSEMBLY)
613
    Structure* webAssemblyModuleRecordStructure() const { return m_webAssemblyModuleRecordStructure.get(); }
614
    Structure* webAssemblyModuleRecordStructure() const { return m_webAssemblyModuleRecordStructure.get(); }
614
    Structure* webAssemblyFunctionStructure() const { return m_webAssemblyFunctionStructure.get(); }
615
    Structure* webAssemblyFunctionStructure() const { return m_webAssemblyFunctionStructure.get(); }
616
    Structure* webAssemblyWrapperFunctionStructure() const { return m_webAssemblyWrapperFunctionStructure.get(); }
615
#endif // ENABLE(WEBASSEMBLY)
617
#endif // ENABLE(WEBASSEMBLY)
616
618
617
    JS_EXPORT_PRIVATE void setRemoteDebuggingEnabled(bool);
619
    JS_EXPORT_PRIVATE void setRemoteDebuggingEnabled(bool);
- Source/JavaScriptCore/runtime/JSType.h -1 / +1 lines
Lines 97-103 enum JSType : uint8_t { Source/JavaScriptCore/runtime/JSType.h_sec1
97
97
98
    WebAssemblyFunctionType,
98
    WebAssemblyFunctionType,
99
99
100
    LastJSCObjectType = JSSetType,
100
    LastJSCObjectType = WebAssemblyFunctionType,
101
    MaxJSType = 0b11111111,
101
    MaxJSType = 0b11111111,
102
};
102
};
103
103
- Source/JavaScriptCore/wasm/JSWebAssemblyCodeBlock.h +6 lines
Lines 94-99 public: Source/JavaScriptCore/wasm/JSWebAssemblyCodeBlock.h_sec1
94
        return bitwise_cast<WriteBarrier<JSWebAssemblyCallee>*>(bitwise_cast<char*>(this) + offsetOfCallees());
94
        return bitwise_cast<WriteBarrier<JSWebAssemblyCallee>*>(bitwise_cast<char*>(this) + offsetOfCallees());
95
    }
95
    }
96
96
97
    void* wasmToJsCallStubForImport(unsigned importIndex)
98
    {
99
        RELEASE_ASSERT(importIndex < m_wasmExitStubs.size());
100
        return m_wasmExitStubs[importIndex].wasmToJs.code().executableAddress();
101
    }
102
97
private:
103
private:
98
    JSWebAssemblyCodeBlock(VM&, JSWebAssemblyModule*, Bag<CallLinkInfo>&&, Vector<Wasm::WasmExitStubs>&&, Wasm::Memory::Mode, unsigned calleeCount);
104
    JSWebAssemblyCodeBlock(VM&, JSWebAssemblyModule*, Bag<CallLinkInfo>&&, Vector<Wasm::WasmExitStubs>&&, Wasm::Memory::Mode, unsigned calleeCount);
99
    DECLARE_EXPORT_INFO;
105
    DECLARE_EXPORT_INFO;
- Source/JavaScriptCore/wasm/WasmB3IRGenerator.cpp -62 / +142 lines
Lines 1039-1123 void B3IRGenerator::dump(const Vector<Co Source/JavaScriptCore/wasm/WasmB3IRGenerator.cpp_sec1
1039
1039
1040
static void createJSToWasmWrapper(VM& vm, CompilationContext& compilationContext, WasmInternalFunction& function, const Signature* signature, const ModuleInformation& info)
1040
static void createJSToWasmWrapper(VM& vm, CompilationContext& compilationContext, WasmInternalFunction& function, const Signature* signature, const ModuleInformation& info)
1041
{
1041
{
1042
    Procedure proc;
1042
    CCallHelpers& jit = *compilationContext.jsEntrypointJIT;
1043
    BasicBlock* block = proc.addBlock();
1044
1043
1045
    Origin origin;
1044
    jit.emitFunctionPrologue();
1046
1045
1047
    jscCallingConvention().setupFrameInPrologue(&function.jsToWasmCalleeMoveLocation, proc, origin, block);
1046
    // FIXME Stop using 0 as codeBlocks. https://bugs.webkit.org/show_bug.cgi?id=165321
1047
    jit.store64(CCallHelpers::TrustedImm64(0), CCallHelpers::Address(GPRInfo::callFrameRegister, CallFrameSlot::codeBlock * static_cast<int>(sizeof(Register))));
1048
    MacroAssembler::DataLabelPtr calleeMoveLocation = jit.moveWithPatch(MacroAssembler::TrustedImmPtr(nullptr), GPRInfo::nonPreservedNonReturnGPR);
1049
    jit.storePtr(GPRInfo::nonPreservedNonReturnGPR, CCallHelpers::Address(GPRInfo::callFrameRegister, CallFrameSlot::callee * static_cast<int>(sizeof(Register))));
1050
    CodeLocationDataLabelPtr* linkedCalleeMove = &function.jsToWasmCalleeMoveLocation;
1051
    jit.addLinkTask([=] (LinkBuffer& linkBuffer) {
1052
        *linkedCalleeMove = linkBuffer.locationOf(calleeMoveLocation);
1053
    });
1054
1055
    RegisterSet toSave;
1056
    const PinnedRegisterInfo& pinnedRegs = PinnedRegisterInfo::get();
1057
    toSave.set(pinnedRegs.baseMemoryPointer);
1058
    for (const PinnedSizeRegisterInfo& regInfo : pinnedRegs.sizeRegisters)
1059
        toSave.set(regInfo.sizeRegister);
1060
1061
#if !ASSERT_DISABLED
1062
    unsigned toSaveSize = toSave.numberOfSetGPRs();
1063
    // They should all be callee saves.
1064
    toSave.filter(RegisterSet::calleeSaveRegisters());
1065
    ASSERT(toSave.numberOfSetGPRs() == toSaveSize);
1066
#endif
1048
1067
1049
    if (!ASSERT_DISABLED) {
1068
    RegisterAtOffsetList registersToSpill(toSave, RegisterAtOffsetList::OffsetBaseType::FramePointerBased);
1050
        // This should be guaranteed by our JS wrapper that handles calls to us.
1069
    function.jsToWasmEntrypoint.calleeSaveRegisters = registersToSpill;
1051
        // Just prevent against crazy when ASSERT is enabled.
1052
        Value* framePointer = block->appendNew<B3::Value>(proc, B3::FramePointer, origin);
1053
        Value* offSetOfArgumentCount = block->appendNew<Const64Value>(proc, origin, CallFrameSlot::argumentCount * sizeof(Register));
1054
        Value* argumentCount = block->appendNew<MemoryValue>(proc, Load, Int32, origin,
1055
            block->appendNew<Value>(proc, Add, origin, framePointer, offSetOfArgumentCount));
1056
1070
1057
        Value* expectedArgumentCount = block->appendNew<Const32Value>(proc, origin, signature->argumentCount());
1071
    unsigned totalFrameSize = registersToSpill.size() * sizeof(void*);
1072
    totalFrameSize += WasmCallingConvention::headerSizeInBytes();
1073
    totalFrameSize -= sizeof(CallerFrameAndPC);
1074
    unsigned numGPRs = 0;
1075
    unsigned numFPRs = 0;
1076
    for (unsigned i = 0; i < signature->argumentCount(); i++) {
1077
        switch (signature->argument(i)) {
1078
        case Wasm::I64:
1079
        case Wasm::I32:
1080
            if (numGPRs >= wasmCallingConvention().m_gprArgs.size())
1081
                totalFrameSize += sizeof(void*);
1082
            ++numGPRs;
1083
            break;
1084
        case Wasm::F32:
1085
        case Wasm::F64:
1086
            if (numFPRs >= wasmCallingConvention().m_fprArgs.size())
1087
                totalFrameSize += sizeof(void*);
1088
            ++numFPRs;
1089
            break;
1090
        default:
1091
            RELEASE_ASSERT_NOT_REACHED();
1092
        }
1093
    }
1058
1094
1059
        CheckValue* argumentCountCheck = block->appendNew<CheckValue>(proc, Check, origin,
1095
    totalFrameSize = WTF::roundUpToMultipleOf(stackAlignmentBytes(), totalFrameSize);
1060
            block->appendNew<Value>(proc, Above, origin, expectedArgumentCount, argumentCount));
1096
    jit.subPtr(MacroAssembler::TrustedImm32(totalFrameSize), MacroAssembler::stackPointerRegister);
1061
1097
1062
        argumentCountCheck->setGenerator([] (CCallHelpers& jit, const StackmapGenerationParams&) {
1098
    // We save all these registers regardless of having a memory or not.
1063
            jit.breakpoint();
1099
    // The reason is that we use one of these as a scratch. That said,
1064
        });
1100
    // almost all real wasm programs use memory, so it's not really
1101
    // worth optimizing for the case that they don't.
1102
    for (const RegisterAtOffset& regAtOffset : registersToSpill) {
1103
        GPRReg reg = regAtOffset.reg().gpr();
1104
        ptrdiff_t offset = regAtOffset.offset();
1105
        jit.storePtr(reg, CCallHelpers::Address(GPRInfo::callFrameRegister, offset));
1065
    }
1106
    }
1066
1107
1067
    // 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
1108
    {
1068
    Value* instance = block->appendNew<MemoryValue>(proc, Load, pointerType(), Origin(),
1109
        CCallHelpers::Address calleeFrame = CCallHelpers::Address(MacroAssembler::stackPointerRegister, -static_cast<ptrdiff_t>(sizeof(CallerFrameAndPC)));
1069
        block->appendNew<ConstPtrValue>(proc, Origin(), &vm.topJSWebAssemblyInstance));
1110
        numGPRs = 0;
1070
    restoreWebAssemblyGlobalState(vm, info.memory, instance, proc, block);
1111
        numFPRs = 0;
1071
1112
        // We're going to set the pinned registers after this. So
1072
    // Get our arguments.
1113
        // we can use this as a scratch for now since we saved it above.
1073
    Vector<Value*> arguments;
1114
        GPRReg scratchReg = pinnedRegs.baseMemoryPointer;
1074
    jscCallingConvention().loadArguments(signature, proc, block, origin, [&] (Value* argument, unsigned) {
1115
1075
        arguments.append(argument);
1116
        ptrdiff_t jsOffset = CallFrameSlot::thisArgument * sizeof(void*);
1076
    });
1117
        ptrdiff_t wasmOffset = CallFrame::headerSizeInRegisters * sizeof(void*);
1077
1118
        for (unsigned i = 0; i < signature->argumentCount(); i++) {
1078
    // Move the arguments into place.
1119
            switch (signature->argument(i)) {
1079
    Value* result = wasmCallingConvention().setupCall(proc, block, origin, arguments, toB3Type(signature->returnType()), [&] (PatchpointValue* patchpoint) {
1120
            case Wasm::I32:
1080
        CompilationContext* context = &compilationContext;
1121
            case Wasm::I64:
1081
1122
                if (numGPRs >= wasmCallingConvention().m_gprArgs.size()) {
1082
        // 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.
1123
                    if (signature->argument(i) == Wasm::I32) {
1083
        const PinnedRegisterInfo* pinnedRegs = &PinnedRegisterInfo::get();
1124
                        jit.load32(CCallHelpers::Address(GPRInfo::callFrameRegister, jsOffset), scratchReg);
1084
        RegisterSet clobbers;
1125
                        jit.store32(scratchReg, calleeFrame.withOffset(wasmOffset));
1085
        clobbers.set(pinnedRegs->baseMemoryPointer);
1126
                    } else {
1086
        for (auto info : pinnedRegs->sizeRegisters)
1127
                        jit.load64(CCallHelpers::Address(GPRInfo::callFrameRegister, jsOffset), scratchReg);
1087
            clobbers.set(info.sizeRegister);
1128
                        jit.store64(scratchReg, calleeFrame.withOffset(wasmOffset));
1088
        patchpoint->effects.writesPinned = true;
1129
                    }
1089
        patchpoint->clobber(clobbers);
1130
                    wasmOffset += sizeof(void*);
1131
                } else {
1132
                    if (signature->argument(i) == Wasm::I32)
1133
                        jit.load32(CCallHelpers::Address(GPRInfo::callFrameRegister, jsOffset), wasmCallingConvention().m_gprArgs[numGPRs].gpr());
1134
                    else
1135
                        jit.load64(CCallHelpers::Address(GPRInfo::callFrameRegister, jsOffset), wasmCallingConvention().m_gprArgs[numGPRs].gpr());
1136
                }
1137
                ++numGPRs;
1138
                break;
1139
            case Wasm::F32:
1140
            case Wasm::F64:
1141
                if (numFPRs >= wasmCallingConvention().m_fprArgs.size()) {
1142
                    if (signature->argument(i) == Wasm::F32) {
1143
                        jit.load32(CCallHelpers::Address(GPRInfo::callFrameRegister, jsOffset), scratchReg);
1144
                        jit.store32(scratchReg, calleeFrame.withOffset(wasmOffset));
1145
                    } else {
1146
                        jit.load64(CCallHelpers::Address(GPRInfo::callFrameRegister, jsOffset), scratchReg);
1147
                        jit.store64(scratchReg, calleeFrame.withOffset(wasmOffset));
1148
                    }
1149
                    wasmOffset += sizeof(void*);
1150
                } else {
1151
                    if (signature->argument(i) == Wasm::F32)
1152
                        jit.loadFloat(CCallHelpers::Address(GPRInfo::callFrameRegister, jsOffset), wasmCallingConvention().m_fprArgs[numFPRs].fpr());
1153
                    else
1154
                        jit.loadDouble(CCallHelpers::Address(GPRInfo::callFrameRegister, jsOffset), wasmCallingConvention().m_fprArgs[numFPRs].fpr());
1155
                }
1156
                ++numFPRs;
1157
                break;
1158
            default:
1159
                RELEASE_ASSERT_NOT_REACHED();
1160
            }
1090
1161
1091
        patchpoint->setGenerator([context] (CCallHelpers& jit, const B3::StackmapGenerationParams&) {
1162
            jsOffset += sizeof(void*);
1092
            AllowMacroScratchRegisterUsage allowScratch(jit);
1163
        }
1164
    }
1093
1165
1094
            CCallHelpers::Call call = jit.call();
1166
    if (!!info.memory) {
1095
            context->jsEntrypointToWasmEntrypointCall = call;
1167
        GPRReg baseMemory = pinnedRegs.baseMemoryPointer;
1096
        });
1168
        jit.loadPtr(&vm.topJSWebAssemblyInstance, baseMemory);
1097
    });
1169
        jit.loadPtr(CCallHelpers::Address(baseMemory, JSWebAssemblyInstance::offsetOfMemory()), baseMemory);
1170
        const auto& sizeRegs = pinnedRegs.sizeRegisters;
1171
        ASSERT(sizeRegs.size() >= 1);
1172
        ASSERT(!sizeRegs[0].sizeOffset); // The following code assumes we start at 0, and calculates subsequent size registers relative to 0.
1173
        jit.loadPtr(CCallHelpers::Address(baseMemory, JSWebAssemblyMemory::offsetOfSize()), sizeRegs[0].sizeRegister);
1174
        jit.loadPtr(CCallHelpers::Address(baseMemory, JSWebAssemblyMemory::offsetOfMemory()), baseMemory);
1175
        for (unsigned i = 1; i < sizeRegs.size(); ++i)
1176
            jit.add64(CCallHelpers::TrustedImm32(-sizeRegs[i].sizeOffset), sizeRegs[0].sizeRegister, sizeRegs[i].sizeRegister);
1177
    }
1178
1179
    compilationContext.jsEntrypointToWasmEntrypointCall = jit.call();
1180
1181
    for (const RegisterAtOffset& regAtOffset : registersToSpill) {
1182
        GPRReg reg = regAtOffset.reg().gpr();
1183
        ASSERT(reg != GPRInfo::returnValueGPR);
1184
        ptrdiff_t offset = regAtOffset.offset();
1185
        jit.loadPtr(CCallHelpers::Address(GPRInfo::callFrameRegister, offset), reg);
1186
    }
1098
1187
1099
    // Return the result, if needed.
1100
    switch (signature->returnType()) {
1188
    switch (signature->returnType()) {
1101
    case Wasm::Void:
1102
        block->appendNewControlValue(proc, B3::Return, origin);
1103
        break;
1104
    case Wasm::F32:
1189
    case Wasm::F32:
1190
        jit.moveFloatTo32(FPRInfo::returnValueFPR, GPRInfo::returnValueGPR);
1191
        break;
1105
    case Wasm::F64:
1192
    case Wasm::F64:
1106
        result = block->appendNew<Value>(proc, BitwiseCast, origin, result);
1193
        jit.moveDoubleTo64(FPRInfo::returnValueFPR, GPRInfo::returnValueGPR);
1107
        FALLTHROUGH;
1194
        break;
1108
    case Wasm::I32:
1195
    default:
1109
    case Wasm::I64:
1110
        block->appendNewControlValue(proc, B3::Return, origin, result);
1111
        break;
1196
        break;
1112
    case Wasm::Func:
1113
    case Wasm::Anyfunc:
1114
        RELEASE_ASSERT_NOT_REACHED();
1115
    }
1197
    }
1116
1198
1117
    B3::prepareForGeneration(proc);
1199
    jit.emitFunctionEpilogue();
1118
    B3::generate(proc, *compilationContext.jsEntrypointJIT);
1200
    jit.ret();
1119
    compilationContext.jsEntrypointByproducts = proc.releaseByproducts();
1120
    function.jsToWasmEntrypoint.calleeSaveRegisters = proc.calleeSaveRegisters();
1121
}
1201
}
1122
1202
1123
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)
1203
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)
- Source/JavaScriptCore/wasm/WasmCallingConvention.h +1 lines
Lines 84-89 private: Source/JavaScriptCore/wasm/WasmCallingConvention.h_sec1
84
    }
84
    }
85
85
86
public:
86
public:
87
    static unsigned headerSizeInBytes() { return headerSize; }
87
    void setupFrameInPrologue(CodeLocationDataLabelPtr* calleeMoveLocation, B3::Procedure& proc, B3::Origin origin, B3::BasicBlock* block) const
88
    void setupFrameInPrologue(CodeLocationDataLabelPtr* calleeMoveLocation, B3::Procedure& proc, B3::Origin origin, B3::BasicBlock* block) const
88
    {
89
    {
89
        static_assert(CallFrameSlot::callee * sizeof(Register) < headerSize, "We rely on this here for now.");
90
        static_assert(CallFrameSlot::callee * sizeof(Register) < headerSize, "We rely on this here for now.");
- Source/JavaScriptCore/wasm/js/JSWebAssemblyHelpers.h +32 lines
Lines 29-34 Source/JavaScriptCore/wasm/js/JSWebAssemblyHelpers.h_sec1
29
29
30
#include "JSArrayBuffer.h"
30
#include "JSArrayBuffer.h"
31
#include "JSCJSValue.h"
31
#include "JSCJSValue.h"
32
#include "WebAssemblyFunction.h"
33
#include "WebAssemblyWrapperFunction.h"
32
34
33
namespace JSC {
35
namespace JSC {
34
36
Lines 71-76 ALWAYS_INLINE uint8_t* getWasmBufferFrom Source/JavaScriptCore/wasm/js/JSWebAssemblyHelpers.h_sec2
71
    return arrayBufferView ? static_cast<uint8_t*>(arrayBufferView->vector()) : static_cast<uint8_t*>(arrayBuffer->impl()->data());
73
    return arrayBufferView ? static_cast<uint8_t*>(arrayBufferView->vector()) : static_cast<uint8_t*>(arrayBuffer->impl()->data());
72
}
74
}
73
75
76
ALWAYS_INLINE bool isWebAssemblyHostFunction(VM& vm, JSObject* object, WebAssemblyFunction*& wasmFunction, WebAssemblyWrapperFunction*& wasmWrapperFunction)
77
{
78
    if (object->inherits(vm, WebAssemblyFunction::info())) {
79
        wasmFunction = jsCast<WebAssemblyFunction*>(object);
80
        wasmWrapperFunction = nullptr;
81
        return true;
82
    }
83
    if (object->inherits(vm, WebAssemblyWrapperFunction::info())) {
84
        wasmWrapperFunction = jsCast<WebAssemblyWrapperFunction*>(object);
85
        wasmFunction = nullptr;
86
        return true;
87
    }
88
    return false;
89
}
90
91
ALWAYS_INLINE bool isWebAssemblyHostFunction(VM& vm, JSValue value, WebAssemblyFunction*& wasmFunction, WebAssemblyWrapperFunction*& wasmWrapperFunction)
92
{
93
    if (!value.isObject())
94
        return false;
95
    return isWebAssemblyHostFunction(vm, jsCast<JSObject*>(value), wasmFunction, wasmWrapperFunction);
96
}
97
98
99
ALWAYS_INLINE bool isWebAssemblyHostFunction(VM& vm, JSObject* object)
100
{
101
    WebAssemblyFunction* unused;
102
    WebAssemblyWrapperFunction* unused2;
103
    return isWebAssemblyHostFunction(vm, object, unused, unused2);
104
}
105
74
} // namespace JSC
106
} // namespace JSC
75
107
76
#endif // ENABLE(WEBASSEMBLY)
108
#endif // ENABLE(WEBASSEMBLY)
- Source/JavaScriptCore/wasm/js/JSWebAssemblyInstance.cpp -1 / +1 lines
Lines 67-73 JSWebAssemblyInstance::JSWebAssemblyInst Source/JavaScriptCore/wasm/js/JSWebAssemblyInstance.cpp_sec1
67
    : Base(vm, structure)
67
    : Base(vm, structure)
68
    , m_numImportFunctions(numImportFunctions)
68
    , m_numImportFunctions(numImportFunctions)
69
{
69
{
70
    memset(importFunctions(), 0, m_numImportFunctions * sizeof(WriteBarrier<JSCell>));
70
    memset(importFunctions(), 0, m_numImportFunctions * sizeof(WriteBarrier<JSObject>));
71
}
71
}
72
72
73
void JSWebAssemblyInstance::finishCreation(VM& vm, JSWebAssemblyModule* module, JSModuleNamespaceObject* moduleNamespaceObject)
73
void JSWebAssemblyInstance::finishCreation(VM& vm, JSWebAssemblyModule* module, JSModuleNamespaceObject* moduleNamespaceObject)
- Source/JavaScriptCore/wasm/js/JSWebAssemblyInstance.h -4 / +4 lines
Lines 60-77 public: Source/JavaScriptCore/wasm/js/JSWebAssemblyInstance.h_sec1
60
        return m_codeBlock.get();
60
        return m_codeBlock.get();
61
    }
61
    }
62
62
63
    WriteBarrier<JSCell>* importFunction(unsigned idx)
63
    WriteBarrier<JSObject>* importFunction(unsigned idx)
64
    {
64
    {
65
        RELEASE_ASSERT(idx < m_numImportFunctions);
65
        RELEASE_ASSERT(idx < m_numImportFunctions);
66
        return &importFunctions()[idx];
66
        return &importFunctions()[idx];
67
    }
67
    }
68
68
69
    WriteBarrier<JSCell>* importFunctions()
69
    WriteBarrier<JSObject>* importFunctions()
70
    {
70
    {
71
        return bitwise_cast<WriteBarrier<JSCell>*>(bitwise_cast<char*>(this) + offsetOfImportFunctions());
71
        return bitwise_cast<WriteBarrier<JSObject>*>(bitwise_cast<char*>(this) + offsetOfImportFunctions());
72
    }
72
    }
73
73
74
    void setImportFunction(VM& vm, JSCell* value, unsigned idx)
74
    void setImportFunction(VM& vm, JSObject* value, unsigned idx)
75
    {
75
    {
76
        importFunction(idx)->set(vm, this, value);
76
        importFunction(idx)->set(vm, this, value);
77
    }
77
    }
- Source/JavaScriptCore/wasm/js/JSWebAssemblyTable.cpp -5 / +12 lines
Lines 64-74 JSWebAssemblyTable::JSWebAssemblyTable(V Source/JavaScriptCore/wasm/js/JSWebAssemblyTable.cpp_sec1
64
    // FIXME: It might be worth trying to pre-allocate maximum here. The spec recommends doing so.
64
    // FIXME: It might be worth trying to pre-allocate maximum here. The spec recommends doing so.
65
    // But for now, we're not doing that.
65
    // But for now, we're not doing that.
66
    m_functions = MallocPtr<Wasm::CallableFunction>::malloc(sizeof(Wasm::CallableFunction) * static_cast<size_t>(m_size));
66
    m_functions = MallocPtr<Wasm::CallableFunction>::malloc(sizeof(Wasm::CallableFunction) * static_cast<size_t>(m_size));
67
    m_jsFunctions = MallocPtr<WriteBarrier<WebAssemblyFunction>>::malloc(sizeof(WriteBarrier<WebAssemblyFunction>) * static_cast<size_t>(m_size));
67
    m_jsFunctions = MallocPtr<WriteBarrier<JSObject>>::malloc(sizeof(WriteBarrier<JSObject>) * static_cast<size_t>(m_size));
68
    for (uint32_t i = 0; i < m_size; ++i) {
68
    for (uint32_t i = 0; i < m_size; ++i) {
69
        new (&m_functions.get()[i]) Wasm::CallableFunction();
69
        new (&m_functions.get()[i]) Wasm::CallableFunction();
70
        ASSERT(m_functions.get()[i].signatureIndex == Wasm::Signature::invalidIndex); // We rely on this in compiled code.
70
        ASSERT(m_functions.get()[i].signatureIndex == Wasm::Signature::invalidIndex); // We rely on this in compiled code.
71
        new (&m_jsFunctions.get()[i]) WriteBarrier<WebAssemblyFunction>();
71
        new (&m_jsFunctions.get()[i]) WriteBarrier<JSObject>();
72
    }
72
    }
73
}
73
}
74
74
Lines 106-116 bool JSWebAssemblyTable::grow(uint32_t n Source/JavaScriptCore/wasm/js/JSWebAssemblyTable.cpp_sec2
106
        return false;
106
        return false;
107
107
108
    m_functions.realloc(sizeof(Wasm::CallableFunction) * static_cast<size_t>(newSize));
108
    m_functions.realloc(sizeof(Wasm::CallableFunction) * static_cast<size_t>(newSize));
109
    m_jsFunctions.realloc(sizeof(WriteBarrier<WebAssemblyFunction>) * static_cast<size_t>(newSize));
109
    m_jsFunctions.realloc(sizeof(WriteBarrier<JSObject>) * static_cast<size_t>(newSize));
110
110
111
    for (uint32_t i = m_size; i < newSize; ++i) {
111
    for (uint32_t i = m_size; i < newSize; ++i) {
112
        new (&m_functions.get()[i]) Wasm::CallableFunction();
112
        new (&m_functions.get()[i]) Wasm::CallableFunction();
113
        new (&m_jsFunctions.get()[i]) WriteBarrier<WebAssemblyFunction>();
113
        new (&m_jsFunctions.get()[i]) WriteBarrier<JSObject>();
114
    }
114
    }
115
    m_size = newSize;
115
    m_size = newSize;
116
    return true;
116
    return true;
Lines 119-125 bool JSWebAssemblyTable::grow(uint32_t n Source/JavaScriptCore/wasm/js/JSWebAssemblyTable.cpp_sec3
119
void JSWebAssemblyTable::clearFunction(uint32_t index)
119
void JSWebAssemblyTable::clearFunction(uint32_t index)
120
{
120
{
121
    RELEASE_ASSERT(index < m_size);
121
    RELEASE_ASSERT(index < m_size);
122
    m_jsFunctions.get()[index] = WriteBarrier<WebAssemblyFunction>();
122
    m_jsFunctions.get()[index] = WriteBarrier<JSObject>();
123
    m_functions.get()[index] = Wasm::CallableFunction();
123
    m_functions.get()[index] = Wasm::CallableFunction();
124
    ASSERT(m_functions.get()[index].signatureIndex == Wasm::Signature::invalidIndex); // We rely on this in compiled code.
124
    ASSERT(m_functions.get()[index].signatureIndex == Wasm::Signature::invalidIndex); // We rely on this in compiled code.
125
}
125
}
Lines 131-136 void JSWebAssemblyTable::setFunction(VM& Source/JavaScriptCore/wasm/js/JSWebAssemblyTable.cpp_sec4
131
    m_functions.get()[index] = Wasm::CallableFunction(function->signatureIndex(), function->wasmEntrypoint());
131
    m_functions.get()[index] = Wasm::CallableFunction(function->signatureIndex(), function->wasmEntrypoint());
132
}
132
}
133
133
134
void JSWebAssemblyTable::setFunction(VM& vm, uint32_t index, WebAssemblyWrapperFunction* function)
135
{
136
    RELEASE_ASSERT(index < m_size);
137
    m_jsFunctions.get()[index].set(vm, this, function);
138
    m_functions.get()[index] = Wasm::CallableFunction(function->signatureIndex(), function->wasmEntrypoint());
139
}
140
134
} // namespace JSC
141
} // namespace JSC
135
142
136
#endif // ENABLE(WEBASSEMBLY)
143
#endif // ENABLE(WEBASSEMBLY)
- Source/JavaScriptCore/wasm/js/JSWebAssemblyTable.h -2 / +4 lines
Lines 29-34 Source/JavaScriptCore/wasm/js/JSWebAssemblyTable.h_sec1
29
29
30
#include "JSDestructibleObject.h"
30
#include "JSDestructibleObject.h"
31
#include "JSObject.h"
31
#include "JSObject.h"
32
#include "WebAssemblyWrapperFunction.h"
32
#include "WebAssemblyFunction.h"
33
#include "WebAssemblyFunction.h"
33
#include <wtf/MallocPtr.h>
34
#include <wtf/MallocPtr.h>
34
35
Lines 50-62 public: Source/JavaScriptCore/wasm/js/JSWebAssemblyTable.h_sec2
50
    std::optional<uint32_t> maximum() const { return m_maximum; }
51
    std::optional<uint32_t> maximum() const { return m_maximum; }
51
    uint32_t size() const { return m_size; }
52
    uint32_t size() const { return m_size; }
52
    bool grow(uint32_t newSize) WARN_UNUSED_RETURN;
53
    bool grow(uint32_t newSize) WARN_UNUSED_RETURN;
53
    WebAssemblyFunction* getFunction(uint32_t index)
54
    JSObject* getFunction(uint32_t index)
54
    {
55
    {
55
        RELEASE_ASSERT(index < m_size);
56
        RELEASE_ASSERT(index < m_size);
56
        return m_jsFunctions.get()[index].get();
57
        return m_jsFunctions.get()[index].get();
57
    }
58
    }
58
    void clearFunction(uint32_t index);
59
    void clearFunction(uint32_t index);
59
    void setFunction(VM&, uint32_t index, WebAssemblyFunction*);
60
    void setFunction(VM&, uint32_t index, WebAssemblyFunction*);
61
    void setFunction(VM&, uint32_t index, WebAssemblyWrapperFunction*);
60
62
61
    static ptrdiff_t offsetOfSize() { return OBJECT_OFFSETOF(JSWebAssemblyTable, m_size); }
63
    static ptrdiff_t offsetOfSize() { return OBJECT_OFFSETOF(JSWebAssemblyTable, m_size); }
62
    static ptrdiff_t offsetOfFunctions() { return OBJECT_OFFSETOF(JSWebAssemblyTable, m_functions); }
64
    static ptrdiff_t offsetOfFunctions() { return OBJECT_OFFSETOF(JSWebAssemblyTable, m_functions); }
Lines 74-80 private: Source/JavaScriptCore/wasm/js/JSWebAssemblyTable.h_sec3
74
    static void visitChildren(JSCell*, SlotVisitor&);
76
    static void visitChildren(JSCell*, SlotVisitor&);
75
77
76
    MallocPtr<Wasm::CallableFunction> m_functions;
78
    MallocPtr<Wasm::CallableFunction> m_functions;
77
    MallocPtr<WriteBarrier<WebAssemblyFunction>> m_jsFunctions;
79
    MallocPtr<WriteBarrier<JSObject>> m_jsFunctions;
78
    std::optional<uint32_t> m_maximum;
80
    std::optional<uint32_t> m_maximum;
79
    uint32_t m_size;
81
    uint32_t m_size;
80
};
82
};
- Source/JavaScriptCore/wasm/js/WebAssemblyInstanceConstructor.cpp -5 / +14 lines
Lines 32-37 Source/JavaScriptCore/wasm/js/WebAssemblyInstanceConstructor.cpp_sec1
32
#include "JSCInlines.h"
32
#include "JSCInlines.h"
33
#include "JSModuleEnvironment.h"
33
#include "JSModuleEnvironment.h"
34
#include "JSModuleNamespaceObject.h"
34
#include "JSModuleNamespaceObject.h"
35
#include "JSWebAssemblyHelpers.h"
35
#include "JSWebAssemblyInstance.h"
36
#include "JSWebAssemblyInstance.h"
36
#include "JSWebAssemblyLinkError.h"
37
#include "JSWebAssemblyLinkError.h"
37
#include "JSWebAssemblyMemory.h"
38
#include "JSWebAssemblyMemory.h"
Lines 129-143 JSWebAssemblyInstance* WebAssemblyInstan Source/JavaScriptCore/wasm/js/WebAssemblyInstanceConstructor.cpp_sec2
129
            if (!value.isFunction())
130
            if (!value.isFunction())
130
                return exception(createJSWebAssemblyLinkError(exec, vm, ASCIILiteral("import function must be callable")));
131
                return exception(createJSWebAssemblyLinkError(exec, vm, ASCIILiteral("import function must be callable")));
131
132
132
            JSCell* cell = value.asCell();
133
            JSObject* function = jsCast<JSObject*>(value);
133
            // ii. If v is an Exported Function Exotic Object:
134
            // ii. If v is an Exported Function Exotic Object:
134
            if (WebAssemblyFunction* importedExport = jsDynamicCast<WebAssemblyFunction*>(vm, cell)) {
135
            WebAssemblyFunction* wasmFunction;
136
            WebAssemblyWrapperFunction* wasmWrapperFunction;
137
            if (isWebAssemblyHostFunction(vm, function, wasmFunction, wasmWrapperFunction)) {
135
                // a. If the signature of v does not match the signature of i, throw a WebAssembly.LinkError.
138
                // a. If the signature of v does not match the signature of i, throw a WebAssembly.LinkError.
136
                Wasm::SignatureIndex importedSignatureIndex = importedExport->signatureIndex();
139
                Wasm::SignatureIndex importedSignatureIndex;
140
                if (wasmFunction)
141
                    importedSignatureIndex = wasmFunction->signatureIndex();
142
                else {
143
                    importedSignatureIndex = wasmWrapperFunction->signatureIndex();
144
                    // b. Let closure be v.[[Closure]].
145
                    function = wasmWrapperFunction->function();
146
                }
137
                Wasm::SignatureIndex expectedSignatureIndex = moduleInformation.importFunctionSignatureIndices[import.kindIndex];
147
                Wasm::SignatureIndex expectedSignatureIndex = moduleInformation.importFunctionSignatureIndices[import.kindIndex];
138
                if (importedSignatureIndex != expectedSignatureIndex)
148
                if (importedSignatureIndex != expectedSignatureIndex)
139
                    return exception(createJSWebAssemblyLinkError(exec, vm, ASCIILiteral("imported function's signature doesn't match the provided WebAssembly function's signature")));
149
                    return exception(createJSWebAssemblyLinkError(exec, vm, ASCIILiteral("imported function's signature doesn't match the provided WebAssembly function's signature")));
140
                // b. Let closure be v.[[Closure]].
141
            }
150
            }
142
            // iii. Otherwise:
151
            // iii. Otherwise:
143
            // 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.
152
            // 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.
Lines 146-152 JSWebAssemblyInstance* WebAssemblyInstan Source/JavaScriptCore/wasm/js/WebAssemblyInstanceConstructor.cpp_sec3
146
            // 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).
155
            // 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).
147
156
148
            ASSERT(numImportFunctions == import.kindIndex);
157
            ASSERT(numImportFunctions == import.kindIndex);
149
            instance->setImportFunction(vm, cell, numImportFunctions++);
158
            instance->setImportFunction(vm, function, numImportFunctions++);
150
            // v. Append closure to imports.
159
            // v. Append closure to imports.
151
            break;
160
            break;
152
        }
161
        }
- Source/JavaScriptCore/wasm/js/WebAssemblyModuleRecord.cpp -17 / +39 lines
Lines 32-37 Source/JavaScriptCore/wasm/js/WebAssemblyModuleRecord.cpp_sec1
32
#include "JSCInlines.h"
32
#include "JSCInlines.h"
33
#include "JSLexicalEnvironment.h"
33
#include "JSLexicalEnvironment.h"
34
#include "JSModuleEnvironment.h"
34
#include "JSModuleEnvironment.h"
35
#include "JSWebAssemblyHelpers.h"
35
#include "JSWebAssemblyInstance.h"
36
#include "JSWebAssemblyInstance.h"
36
#include "JSWebAssemblyLinkError.h"
37
#include "JSWebAssemblyLinkError.h"
37
#include "JSWebAssemblyModule.h"
38
#include "JSWebAssemblyModule.h"
Lines 110-128 void WebAssemblyModuleRecord::link(ExecS Source/JavaScriptCore/wasm/js/WebAssemblyModuleRecord.cpp_sec2
110
            //   i. If there is an Exported Function Exotic Object func in funcs whose func.[[Closure]] equals c, then return func.
111
            //   i. If there is an Exported Function Exotic Object func in funcs whose func.[[Closure]] equals c, then return func.
111
            //   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.)
112
            //   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.)
112
            if (exp.kindIndex < functionImportCount) {
113
            if (exp.kindIndex < functionImportCount) {
113
                // FIXME Implement re-exporting an import. https://bugs.webkit.org/show_bug.cgi?id=165510
114
                unsigned functionIndex = exp.kindIndex;
114
                RELEASE_ASSERT_NOT_REACHED();
115
                JSObject* functionImport = instance->importFunction(functionIndex)->get();
116
                if (isWebAssemblyHostFunction(vm, functionImport))
117
                    exportedValue = functionImport;
118
                else {
119
                    Wasm::SignatureIndex signatureIndex = module->signatureIndexFromFunctionIndexSpace(functionIndex);
120
                    exportedValue = WebAssemblyWrapperFunction::create(vm, globalObject, functionImport, functionIndex, codeBlock, signatureIndex);
121
                }
122
            } else {
123
                //   iii. Otherwise:
124
                //     a. Let func be an Exported Function Exotic Object created from c.
125
                //     b. Append func to funcs.
126
                //     c. Return func.
127
                JSWebAssemblyCallee* jsEntrypointCallee = codeBlock->jsEntrypointCalleeFromFunctionIndexSpace(exp.kindIndex);
128
                JSWebAssemblyCallee* wasmEntrypointCallee = codeBlock->wasmEntrypointCalleeFromFunctionIndexSpace(exp.kindIndex);
129
                Wasm::SignatureIndex signatureIndex = module->signatureIndexFromFunctionIndexSpace(exp.kindIndex);
130
                const Wasm::Signature* signature = Wasm::SignatureInformation::get(&vm, signatureIndex);
131
                WebAssemblyFunction* function = WebAssemblyFunction::create(vm, globalObject, signature->argumentCount(), exp.field.string(), instance, jsEntrypointCallee, wasmEntrypointCallee, signatureIndex);
132
                exportedValue = function;
115
            }
133
            }
116
            //   iii. Otherwise:
117
            //     a. Let func be an Exported Function Exotic Object created from c.
118
            //     b. Append func to funcs.
119
            //     c. Return func.
120
            JSWebAssemblyCallee* jsEntrypointCallee = codeBlock->jsEntrypointCalleeFromFunctionIndexSpace(exp.kindIndex);
121
            JSWebAssemblyCallee* wasmEntrypointCallee = codeBlock->wasmEntrypointCalleeFromFunctionIndexSpace(exp.kindIndex);
122
            Wasm::SignatureIndex signatureIndex = module->signatureIndexFromFunctionIndexSpace(exp.kindIndex);
123
            const Wasm::Signature* signature = Wasm::SignatureInformation::get(&vm, signatureIndex);
124
            WebAssemblyFunction* function = WebAssemblyFunction::create(vm, globalObject, signature->argumentCount(), exp.field.string(), instance, jsEntrypointCallee, wasmEntrypointCallee, signatureIndex);
125
            exportedValue = function;
126
            break;
134
            break;
127
        }
135
        }
128
        case Wasm::ExternalKind::Table: {
136
        case Wasm::ExternalKind::Table: {
Lines 184-190 void WebAssemblyModuleRecord::link(ExecS Source/JavaScriptCore/wasm/js/WebAssemblyModuleRecord.cpp_sec3
184
        ASSERT(!signature->argumentCount());
192
        ASSERT(!signature->argumentCount());
185
        ASSERT(signature->returnType() == Wasm::Void);
193
        ASSERT(signature->returnType() == Wasm::Void);
186
        if (startFunctionIndexSpace < codeBlock->functionImportCount()) {
194
        if (startFunctionIndexSpace < codeBlock->functionImportCount()) {
187
            JSCell* startFunction = instance->importFunction(startFunctionIndexSpace)->get();
195
            JSObject* startFunction = instance->importFunction(startFunctionIndexSpace)->get();
188
            m_startFunction.set(vm, this, startFunction);
196
            m_startFunction.set(vm, this, startFunction);
189
        } else {
197
        } else {
190
            JSWebAssemblyCallee* jsEntrypointCallee = codeBlock->jsEntrypointCalleeFromFunctionIndexSpace(startFunctionIndexSpace);
198
            JSWebAssemblyCallee* jsEntrypointCallee = codeBlock->jsEntrypointCalleeFromFunctionIndexSpace(startFunctionIndexSpace);
Lines 241-254 JSValue WebAssemblyModuleRecord::evaluat Source/JavaScriptCore/wasm/js/WebAssemblyModuleRecord.cpp_sec4
241
                // for the import.
249
                // for the import.
242
                // https://bugs.webkit.org/show_bug.cgi?id=165510
250
                // https://bugs.webkit.org/show_bug.cgi?id=165510
243
                uint32_t functionIndex = element.functionIndices[i];
251
                uint32_t functionIndex = element.functionIndices[i];
252
                Wasm::SignatureIndex signatureIndex = module->signatureIndexFromFunctionIndexSpace(functionIndex);
244
                if (functionIndex < codeBlock->functionImportCount()) {
253
                if (functionIndex < codeBlock->functionImportCount()) {
245
                    return JSValue::decode(
254
                    JSObject* functionImport = jsCast<JSObject*>(m_instance->importFunction(functionIndex)->get());
246
                        throwVMRangeError(state, scope, ASCIILiteral("Element is setting the table value with an import. This is not yet implemented. FIXME.")));
255
                    if (isWebAssemblyHostFunction(vm, functionImport)) {
256
                        WebAssemblyFunction* wasmFunction = jsDynamicCast<WebAssemblyFunction*>(vm, functionImport);
257
                        // If we ever import a WebAssemblyWrapperFunction, we set the import as the unwrapped value.
258
                        // Because a WebAssemblyWrapperFunction can never wrap another WebAssemblyWrapperFunction,
259
                        // the only type this could be is WebAssemblyFunction.
260
                        RELEASE_ASSERT(wasmFunction);
261
                        table->setFunction(vm, tableIndex, wasmFunction);
262
                        ++tableIndex;
263
                        continue;
264
                    }
265
266
                    table->setFunction(vm, tableIndex,
267
                        WebAssemblyWrapperFunction::create(vm, m_instance->globalObject(), functionImport, functionIndex, codeBlock, signatureIndex));
268
                    ++tableIndex;
269
                    continue;
247
                }
270
                }
248
271
249
                JSWebAssemblyCallee* jsEntrypointCallee = codeBlock->jsEntrypointCalleeFromFunctionIndexSpace(functionIndex);
272
                JSWebAssemblyCallee* jsEntrypointCallee = codeBlock->jsEntrypointCalleeFromFunctionIndexSpace(functionIndex);
250
                JSWebAssemblyCallee* wasmEntrypointCallee = codeBlock->wasmEntrypointCalleeFromFunctionIndexSpace(functionIndex);
273
                JSWebAssemblyCallee* wasmEntrypointCallee = codeBlock->wasmEntrypointCalleeFromFunctionIndexSpace(functionIndex);
251
                Wasm::SignatureIndex signatureIndex = module->signatureIndexFromFunctionIndexSpace(functionIndex);
252
                const Wasm::Signature* signature = Wasm::SignatureInformation::get(&vm, signatureIndex);
274
                const Wasm::Signature* signature = Wasm::SignatureInformation::get(&vm, signatureIndex);
253
                // FIXME: Say we export local function "foo" at function index 0.
275
                // FIXME: Say we export local function "foo" at function index 0.
254
                // What if we also set it to the table an Element w/ index 0.
276
                // What if we also set it to the table an Element w/ index 0.
Lines 288-294 JSValue WebAssemblyModuleRecord::evaluat Source/JavaScriptCore/wasm/js/WebAssemblyModuleRecord.cpp_sec5
288
        }
310
        }
289
    }
311
    }
290
312
291
    if (JSCell* startFunction = m_startFunction.get()) {
313
    if (JSObject* startFunction = m_startFunction.get()) {
292
        CallData callData;
314
        CallData callData;
293
        CallType callType = JSC::getCallData(startFunction, callData);
315
        CallType callType = JSC::getCallData(startFunction, callData);
294
        call(state, startFunction, callType, callData, jsUndefined(), state->emptyList());
316
        call(state, startFunction, callType, callData, jsUndefined(), state->emptyList());
- Source/JavaScriptCore/wasm/js/WebAssemblyModuleRecord.h -1 / +1 lines
Lines 59-65 private: Source/JavaScriptCore/wasm/js/WebAssemblyModuleRecord.h_sec1
59
    static void visitChildren(JSCell*, SlotVisitor&);
59
    static void visitChildren(JSCell*, SlotVisitor&);
60
60
61
    WriteBarrier<JSWebAssemblyInstance> m_instance;
61
    WriteBarrier<JSWebAssemblyInstance> m_instance;
62
    WriteBarrier<JSCell> m_startFunction;
62
    WriteBarrier<JSObject> m_startFunction;
63
};
63
};
64
64
65
} // namespace JSC
65
} // namespace JSC
- Source/JavaScriptCore/wasm/js/WebAssemblyTablePrototype.cpp -5 / +10 lines
Lines 106-112 EncodedJSValue JSC_HOST_CALL webAssembly Source/JavaScriptCore/wasm/js/WebAssemblyTablePrototype.cpp_sec1
106
        return { };
106
        return { };
107
    }
107
    }
108
108
109
    if (WebAssemblyFunction* result = table->getFunction(index))
109
    if (JSObject* result = table->getFunction(index))
110
        return JSValue::encode(result);
110
        return JSValue::encode(result);
111
    return JSValue::encode(jsNull());
111
    return JSValue::encode(jsNull());
112
}
112
}
Lines 120-127 EncodedJSValue JSC_HOST_CALL webAssembly Source/JavaScriptCore/wasm/js/WebAssemblyTablePrototype.cpp_sec2
120
    RETURN_IF_EXCEPTION(throwScope, encodedJSValue());
120
    RETURN_IF_EXCEPTION(throwScope, encodedJSValue());
121
121
122
    JSValue value = exec->argument(1);
122
    JSValue value = exec->argument(1);
123
    WebAssemblyFunction* function = jsDynamicCast<WebAssemblyFunction*>(vm, value);
123
    WebAssemblyFunction* wasmFunction;
124
    if (!value.isNull() && !function) {
124
    WebAssemblyWrapperFunction* wasmWrapperFunction;
125
    if (!value.isNull() && !isWebAssemblyHostFunction(vm, value, wasmFunction, wasmWrapperFunction)) {
125
        throwException(exec, throwScope,
126
        throwException(exec, throwScope,
126
            createTypeError(exec, ASCIILiteral("WebAssembly.Table.prototype.set expects the second argument to be null or an instance of WebAssembly.Function")));
127
            createTypeError(exec, ASCIILiteral("WebAssembly.Table.prototype.set expects the second argument to be null or an instance of WebAssembly.Function")));
127
        return { };
128
        return { };
Lines 139-146 EncodedJSValue JSC_HOST_CALL webAssembly Source/JavaScriptCore/wasm/js/WebAssemblyTablePrototype.cpp_sec3
139
    if (value.isNull())
140
    if (value.isNull())
140
        table->clearFunction(index);
141
        table->clearFunction(index);
141
    else {
142
    else {
142
        ASSERT(!!function);
143
        ASSERT(value.isObject() && isWebAssemblyHostFunction(vm, jsCast<JSObject*>(value), wasmFunction, wasmWrapperFunction));
143
        table->setFunction(vm, index, function);
144
        ASSERT(!!wasmFunction || !!wasmWrapperFunction);
145
        if (wasmFunction)
146
            table->setFunction(vm, index, wasmFunction);
147
        else
148
            table->setFunction(vm, index, wasmWrapperFunction);
144
    }
149
    }
145
    
150
    
146
    return JSValue::encode(jsUndefined());
151
    return JSValue::encode(jsUndefined());
- Source/JavaScriptCore/wasm/js/WebAssemblyWrapperFunction.cpp +98 lines
Line 0 Source/JavaScriptCore/wasm/js/WebAssemblyWrapperFunction.cpp_sec1
1
/*
2
 * Copyright (C) 2017 Apple Inc. All rights reserved.
3
 *
4
 * Redistribution and use in source and binary forms, with or without
5
 * modification, are permitted provided that the following conditions
6
 * are met:
7
 * 1. Redistributions of source code must retain the above copyright
8
 *    notice, this list of conditions and the following disclaimer.
9
 * 2. Redistributions in binary form must reproduce the above copyright
10
 *    notice, this list of conditions and the following disclaimer in the
11
 *    documentation and/or other materials provided with the distribution.
12
 *
13
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24
 */
25
26
#include "config.h"
27
#include "WebAssemblyWrapperFunction.h"
28
29
#if ENABLE(WEBASSEMBLY)
30
31
#include "Error.h"
32
#include "FunctionPrototype.h"
33
#include "JSCInlines.h"
34
35
namespace JSC {
36
37
const ClassInfo WebAssemblyWrapperFunction::s_info = { "WebAssemblyWrapperFunction", &Base::s_info, nullptr, CREATE_METHOD_TABLE(WebAssemblyWrapperFunction) };
38
39
static EncodedJSValue JSC_HOST_CALL callWebAssemblyWrapperFunction(ExecState* exec)
40
{
41
    VM& vm = exec->vm();
42
    auto scope = DECLARE_THROW_SCOPE(vm);
43
    WebAssemblyWrapperFunction* wasmFunction = jsDynamicCast<WebAssemblyWrapperFunction*>(vm, exec->jsCallee());
44
    if (!wasmFunction)
45
        return JSValue::encode(throwException(exec, scope, createTypeError(exec, "expected a WebAssembly function")));
46
47
    CallData callData;
48
    JSObject* function = wasmFunction->function();
49
    CallType callType = function->methodTable(vm)->getCallData(function, callData);
50
    RELEASE_ASSERT(callType != CallType::None);
51
    scope.release();
52
    return JSValue::encode(call(exec, function, callType, callData, jsUndefined(), ArgList(exec)));
53
}
54
55
WebAssemblyWrapperFunction::WebAssemblyWrapperFunction(VM& vm, JSGlobalObject* globalObject, Structure* structure, Wasm::SignatureIndex signatureIndex, void* wasmEntrypointCode)
56
    : Base(vm, globalObject, structure)
57
    , m_wasmEntrypointCode(wasmEntrypointCode)
58
    , m_signatureIndex(signatureIndex)
59
{ }
60
61
WebAssemblyWrapperFunction* WebAssemblyWrapperFunction::create(VM& vm, JSGlobalObject* globalObject, JSObject* function, unsigned importIndex, JSWebAssemblyCodeBlock* codeBlock, Wasm::SignatureIndex signatureIndex)
62
{
63
    ASSERT_WITH_MESSAGE(!function->inherits(vm, WebAssemblyWrapperFunction::info()), "We should never double wrap a wrapper function.");
64
    String name = "";
65
    NativeExecutable* executable = vm.getHostFunction(callWebAssemblyWrapperFunction, NoIntrinsic, callHostFunctionAsConstructor, nullptr, name);
66
    WebAssemblyWrapperFunction* result = new (NotNull, allocateCell<WebAssemblyWrapperFunction>(vm.heap)) WebAssemblyWrapperFunction(vm, globalObject, globalObject->webAssemblyWrapperFunctionStructure(), signatureIndex, codeBlock->wasmToJsCallStubForImport(importIndex));
67
    const Wasm::Signature* signature = Wasm::SignatureInformation::get(&vm, signatureIndex);
68
    result->finishCreation(vm, executable, signature->argumentCount(), name, function, codeBlock);
69
    return result;
70
}
71
72
void WebAssemblyWrapperFunction::finishCreation(VM& vm, NativeExecutable* executable, unsigned length, const String& name, JSObject* function, JSWebAssemblyCodeBlock* codeBlock)
73
{
74
    Base::finishCreation(vm, executable, length, name);
75
    RELEASE_ASSERT(JSValue(function).isFunction());
76
    m_function.set(vm, this, function);
77
    m_codeBlock.set(vm, this, codeBlock);
78
}
79
80
Structure* WebAssemblyWrapperFunction::createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
81
{
82
    ASSERT(globalObject);
83
    return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
84
}
85
86
void WebAssemblyWrapperFunction::visitChildren(JSCell* cell, SlotVisitor& visitor)
87
{
88
    WebAssemblyWrapperFunction* thisObject = jsCast<WebAssemblyWrapperFunction*>(cell);
89
    ASSERT_GC_OBJECT_INHERITS(thisObject, info());
90
    Base::visitChildren(thisObject, visitor);
91
92
    visitor.append(thisObject->m_codeBlock);
93
    visitor.append(thisObject->m_function);
94
}
95
96
} // namespace JSC
97
98
#endif // ENABLE(WEBASSEMBLY)
- Source/JavaScriptCore/wasm/js/WebAssemblyWrapperFunction.h +68 lines
Line 0 Source/JavaScriptCore/wasm/js/WebAssemblyWrapperFunction.h_sec1
1
/*
2
 * Copyright (C) 2017 Apple Inc. All rights reserved.
3
 *
4
 * Redistribution and use in source and binary forms, with or without
5
 * modification, are permitted provided that the following conditions
6
 * are met:
7
 * 1. Redistributions of source code must retain the above copyright
8
 *    notice, this list of conditions and the following disclaimer.
9
 * 2. Redistributions in binary form must reproduce the above copyright
10
 *    notice, this list of conditions and the following disclaimer in the
11
 *    documentation and/or other materials provided with the distribution.
12
 *
13
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24
 */
25
26
#pragma once
27
28
#if ENABLE(WEBASSEMBLY)
29
30
#include "JSFunction.h"
31
#include "JSWebAssemblyCodeBlock.h"
32
33
namespace JSC {
34
35
class WebAssemblyWrapperFunction : public JSFunction {
36
public:
37
    typedef JSFunction Base;
38
39
    const static unsigned StructureFlags = Base::StructureFlags;
40
41
    DECLARE_INFO;
42
43
    static WebAssemblyWrapperFunction* create(VM&, JSGlobalObject*, JSObject*, unsigned importIndex, JSWebAssemblyCodeBlock*, Wasm::SignatureIndex);
44
    static Structure* createStructure(VM&, JSGlobalObject*, JSValue);
45
46
    Wasm::SignatureIndex signatureIndex() const { return m_signatureIndex; }
47
    void* wasmEntrypoint() { return m_wasmEntrypointCode; }
48
    JSObject* function() { return m_function.get(); }
49
50
protected:
51
    static void visitChildren(JSCell*, SlotVisitor&);
52
53
    void finishCreation(VM&, NativeExecutable*, unsigned length, const String& name, JSObject*, JSWebAssemblyCodeBlock*);
54
55
private:
56
    WebAssemblyWrapperFunction(VM&, JSGlobalObject*, Structure*, Wasm::SignatureIndex, void* wasmEntrypointCode);
57
58
    // We keep a reference to our CodeBlock because we have a raw
59
    // pointer to asm code that it owns.
60
    WriteBarrier<JSWebAssemblyCodeBlock> m_codeBlock;
61
    WriteBarrier<JSObject> m_function;
62
    void* m_wasmEntrypointCode;
63
    Wasm::SignatureIndex m_signatureIndex;
64
};
65
66
} // namespace JSC
67
68
#endif // ENABLE(WEBASSEMBLY)

Return to Bug 165510