JSTests/ChangeLog

 12017-03-09 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 NOBODY (OOPS!).
 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
1182017-03-09 Caio Lima <ticaiolima@gmail.com>
219
320 [ESnext] Implement Object Rest - Implementing Object Rest Destructuring
213698

JSTests/wasm/Builder.js

@@export default class Builder {
579579 break;
580580
581581 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
583586 const s = this._addSection(section);
584587 const elementBuilder = {
585588 End: () => this,
213654

JSTests/wasm/js-api/wrapper-function.js

 1import Builder from '../Builder.js';
 2import * as assert from '../assert.js';
 3
 4
 5function 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}
nonexistent

Source/JavaScriptCore/ChangeLog

 12017-03-09 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 NOBODY (OOPS!).
 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 * JavaScriptCore.xcodeproj/project.pbxproj:
 30 * runtime/JSGlobalObject.cpp:
 31 (JSC::JSGlobalObject::init):
 32 (JSC::JSGlobalObject::visitChildren):
 33 * runtime/JSGlobalObject.h:
 34 (JSC::JSGlobalObject::webAssemblyWrapperFunctionStructure):
 35 * runtime/JSType.h:
 36 * wasm/JSWebAssemblyCodeBlock.h:
 37 (JSC::JSWebAssemblyCodeBlock::wasmToJsCallStubForImport):
 38 * wasm/WasmB3IRGenerator.cpp:
 39 (JSC::Wasm::createJSToWasmWrapper):
 40 * wasm/WasmCallingConvention.h:
 41 (JSC::Wasm::CallingConvention::headerSizeInBytes):
 42 * wasm/js/JSWebAssemblyHelpers.h:
 43 (JSC::isWebAssemblyHostFunction):
 44 * wasm/js/JSWebAssemblyInstance.cpp:
 45 (JSC::JSWebAssemblyInstance::JSWebAssemblyInstance):
 46 * wasm/js/JSWebAssemblyInstance.h:
 47 (JSC::JSWebAssemblyInstance::importFunction):
 48 (JSC::JSWebAssemblyInstance::importFunctions):
 49 (JSC::JSWebAssemblyInstance::setImportFunction):
 50 * wasm/js/JSWebAssemblyTable.cpp:
 51 (JSC::JSWebAssemblyTable::JSWebAssemblyTable):
 52 (JSC::JSWebAssemblyTable::grow):
 53 (JSC::JSWebAssemblyTable::clearFunction):
 54 (JSC::JSWebAssemblyTable::setFunction):
 55 * wasm/js/JSWebAssemblyTable.h:
 56 (JSC::JSWebAssemblyTable::getFunction):
 57 * wasm/js/WebAssemblyInstanceConstructor.cpp:
 58 (JSC::WebAssemblyInstanceConstructor::createInstance):
 59 * wasm/js/WebAssemblyModuleRecord.cpp:
 60 (JSC::WebAssemblyModuleRecord::link):
 61 (JSC::WebAssemblyModuleRecord::evaluate):
 62 * wasm/js/WebAssemblyModuleRecord.h:
 63 * wasm/js/WebAssemblyTablePrototype.cpp:
 64 (JSC::webAssemblyTableProtoFuncGet):
 65 (JSC::webAssemblyTableProtoFuncSet):
 66 * wasm/js/WebAssemblyWrapperFunction.cpp: Added.
 67 (JSC::callWebAssemblyWrapperFunction):
 68 (JSC::WebAssemblyWrapperFunction::WebAssemblyWrapperFunction):
 69 (JSC::WebAssemblyWrapperFunction::create):
 70 (JSC::WebAssemblyWrapperFunction::finishCreation):
 71 (JSC::WebAssemblyWrapperFunction::createStructure):
 72 (JSC::WebAssemblyWrapperFunction::visitChildren):
 73 * wasm/js/WebAssemblyWrapperFunction.h: Added.
 74 (JSC::WebAssemblyWrapperFunction::signatureIndex):
 75 (JSC::WebAssemblyWrapperFunction::wasmEntrypoint):
 76 (JSC::WebAssemblyWrapperFunction::function):
 77
1782017-03-09 Saam Barati <sbarati@apple.com>
279
380 WebAssembly: Make the Unity AngryBots demo run
213654

Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj

13041304 52C0611F1AA51E1C00B4ADBA /* RuntimeType.h in Headers */ = {isa = PBXBuildFile; fileRef = 52C0611D1AA51E1B00B4ADBA /* RuntimeType.h */; settings = {ATTRIBUTES = (Private, ); }; };
13051305 52C952B719A289850069B386 /* TypeProfiler.h in Headers */ = {isa = PBXBuildFile; fileRef = 52C952B619A289850069B386 /* TypeProfiler.h */; settings = {ATTRIBUTES = (Private, ); }; };
13061306 52C952B919A28A1C0069B386 /* TypeProfiler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 52C952B819A28A1C0069B386 /* TypeProfiler.cpp */; };
 1307 52F6C35D1E71EB080081F4CC /* WebAssemblyWrapperFunction.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 52F6C35B1E71EB080081F4CC /* WebAssemblyWrapperFunction.cpp */; };
 1308 52F6C35E1E71EB080081F4CC /* WebAssemblyWrapperFunction.h in Headers */ = {isa = PBXBuildFile; fileRef = 52F6C35C1E71EB080081F4CC /* WebAssemblyWrapperFunction.h */; settings = {ATTRIBUTES = (Private, ); }; };
13071309 531374BD1D5CE67600AF7A0B /* WasmPlan.h in Headers */ = {isa = PBXBuildFile; fileRef = 531374BC1D5CE67600AF7A0B /* WasmPlan.h */; };
13081310 531374BF1D5CE95000AF7A0B /* WasmPlan.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 531374BE1D5CE95000AF7A0B /* WasmPlan.cpp */; };
13091311 533B15DF1DC7F463004D500A /* WasmOps.h in Headers */ = {isa = PBXBuildFile; fileRef = 533B15DE1DC7F463004D500A /* WasmOps.h */; settings = {ATTRIBUTES = (Private, ); }; };

37733775 52C0611D1AA51E1B00B4ADBA /* RuntimeType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RuntimeType.h; sourceTree = "<group>"; };
37743776 52C952B619A289850069B386 /* TypeProfiler.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TypeProfiler.h; sourceTree = "<group>"; };
37753777 52C952B819A28A1C0069B386 /* TypeProfiler.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = TypeProfiler.cpp; sourceTree = "<group>"; };
 3778 52F6C35B1E71EB080081F4CC /* WebAssemblyWrapperFunction.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = WebAssemblyWrapperFunction.cpp; path = js/WebAssemblyWrapperFunction.cpp; sourceTree = "<group>"; };
 3779 52F6C35C1E71EB080081F4CC /* WebAssemblyWrapperFunction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = WebAssemblyWrapperFunction.h; path = js/WebAssemblyWrapperFunction.h; sourceTree = "<group>"; };
37763780 531374BC1D5CE67600AF7A0B /* WasmPlan.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WasmPlan.h; sourceTree = "<group>"; };
37773781 531374BE1D5CE95000AF7A0B /* WasmPlan.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WasmPlan.cpp; sourceTree = "<group>"; };
37783782 533B15DE1DC7F463004D500A /* WasmOps.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WasmOps.h; sourceTree = "<group>"; };

78847888 AD2FCBC31DB58DA400B3E736 /* WebAssemblyTablePrototype.h */,
78857889 ADBC54D21DF8EA00005BF738 /* WebAssemblyToJSCallee.cpp */,
78867890 ADBC54D31DF8EA00005BF738 /* WebAssemblyToJSCallee.h */,
 7891 52F6C35B1E71EB080081F4CC /* WebAssemblyWrapperFunction.cpp */,
 7892 52F6C35C1E71EB080081F4CC /* WebAssemblyWrapperFunction.h */,
78877893 );
78887894 name = js;
78897895 sourceTree = "<group>";

82198225 0F21C27D14BE727A00ADC64B /* CodeSpecializationKind.h in Headers */,
82208226 0F0B83A714BCF50700885B4F /* CodeType.h in Headers */,
82218227 0FA762051DB9242900B7A2FD /* CollectionScope.h in Headers */,
 8228 52F6C35E1E71EB080081F4CC /* WebAssemblyWrapperFunction.h in Headers */,
82228229 A53243981856A489002ED692 /* CombinedDomains.json in Headers */,
82238230 BC18C3F30E16F5CD00B34460 /* CommonIdentifiers.h in Headers */,
82248231 0F15F15F14B7A73E005DE37D /* CommonSlowPaths.h in Headers */,

1032710334 A503FA19188E0FB000110F14 /* JavaScriptCallFrame.cpp in Sources */,
1032810335 1429D92F0ED22D7000B89619 /* JIT.cpp in Sources */,
1032910336 FE1220281BE7F5910039E6F2 /* JITAddGenerator.cpp in Sources */,
 10337 52F6C35D1E71EB080081F4CC /* WebAssemblyWrapperFunction.cpp in Sources */,
1033010338 86A90ED00EE7D51F00AB350D /* JITArithmetic.cpp in Sources */,
1033110339 A75706DE118A2BCF0057F88F /* JITArithmetic32_64.cpp in Sources */,
1033210340 FE3A06B11C10CB8400390FDD /* JITBitAndGenerator.cpp in Sources */,
213654

Source/JavaScriptCore/runtime/JSGlobalObject.cpp

@@putDirectWithoutTransition(vm, vm.proper
890890 m_webAssemblyStructure.set(vm, this, JSWebAssembly::createStructure(vm, this, webAssemblyPrototype));
891891 m_webAssemblyModuleRecordStructure.set(vm, this, WebAssemblyModuleRecord::createStructure(vm, this, m_objectPrototype.get()));
892892 m_webAssemblyFunctionStructure.set(vm, this, WebAssemblyFunction::createStructure(vm, this, m_functionPrototype.get()));
 893 m_webAssemblyWrapperFunctionStructure.set(vm, this, WebAssemblyWrapperFunction::createStructure(vm, this, m_functionPrototype.get()));
893894 auto* webAssembly = JSWebAssembly::create(vm, this, m_webAssemblyStructure.get());
894895 putDirectWithoutTransition(vm, Identifier::fromString(exec, "WebAssembly"), webAssembly, DontEnum);
895896

@@void JSGlobalObject::visitChildren(JSCel
12701271 visitor.append(thisObject->m_webAssemblyStructure);
12711272 visitor.append(thisObject->m_webAssemblyModuleRecordStructure);
12721273 visitor.append(thisObject->m_webAssemblyFunctionStructure);
 1274 visitor.append(thisObject->m_webAssemblyWrapperFunctionStructure);
12731275 FOR_EACH_WEBASSEMBLY_CONSTRUCTOR_TYPE(VISIT_SIMPLE_TYPE)
12741276#endif // ENABLE(WEBASSEMBLY)
12751277
213654

Source/JavaScriptCore/runtime/JSGlobalObject.h

@@public:
345345 WriteBarrier<Structure> m_webAssemblyStructure;
346346 WriteBarrier<Structure> m_webAssemblyModuleRecordStructure;
347347 WriteBarrier<Structure> m_webAssemblyFunctionStructure;
 348 WriteBarrier<Structure> m_webAssemblyWrapperFunctionStructure;
348349 FOR_EACH_WEBASSEMBLY_CONSTRUCTOR_TYPE(DEFINE_STORAGE_FOR_SIMPLE_TYPE)
349350#endif // ENABLE(WEBASSEMBLY)
350351

@@public:
612613#if ENABLE(WEBASSEMBLY)
613614 Structure* webAssemblyModuleRecordStructure() const { return m_webAssemblyModuleRecordStructure.get(); }
614615 Structure* webAssemblyFunctionStructure() const { return m_webAssemblyFunctionStructure.get(); }
 616 Structure* webAssemblyWrapperFunctionStructure() const { return m_webAssemblyWrapperFunctionStructure.get(); }
615617#endif // ENABLE(WEBASSEMBLY)
616618
617619 JS_EXPORT_PRIVATE void setRemoteDebuggingEnabled(bool);
213654

Source/JavaScriptCore/runtime/JSType.h

@@enum JSType : uint8_t {
9797
9898 WebAssemblyFunctionType,
9999
100  LastJSCObjectType = JSSetType,
 100 LastJSCObjectType = WebAssemblyFunctionType,
101101 MaxJSType = 0b11111111,
102102};
103103
213654

Source/JavaScriptCore/wasm/JSWebAssemblyCodeBlock.h

@@public:
9494 return bitwise_cast<WriteBarrier<JSWebAssemblyCallee>*>(bitwise_cast<char*>(this) + offsetOfCallees());
9595 }
9696
 97 void* wasmToJsCallStubForImport(unsigned importIndex)
 98 {
 99 RELEASE_ASSERT(importIndex < m_wasmExitStubs.size());
 100 return m_wasmExitStubs[importIndex].wasmToJs.code().executableAddress();
 101 }
 102
97103private:
98104 JSWebAssemblyCodeBlock(VM&, JSWebAssemblyModule*, Bag<CallLinkInfo>&&, Vector<Wasm::WasmExitStubs>&&, Wasm::Memory::Mode, unsigned calleeCount);
99105 DECLARE_EXPORT_INFO;
213654

Source/JavaScriptCore/wasm/WasmB3IRGenerator.cpp

@@void B3IRGenerator::dump(const Vector<Co
10391039
10401040static void createJSToWasmWrapper(VM& vm, CompilationContext& compilationContext, WasmInternalFunction& function, const Signature* signature, const ModuleInformation& info)
10411041{
1042  Procedure proc;
1043  BasicBlock* block = proc.addBlock();
 1042 CCallHelpers& jit = *compilationContext.jsEntrypointJIT;
10441043
1045  Origin origin;
 1044 jit.emitFunctionPrologue();
10461045
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 unsigned toSaveSize = toSave.numberOfSetGPRs();
 1062 toSave.filter(RegisterSet::calleeSaveRegisters());
 1063 // They should all be callee saves.
 1064 RELEASE_ASSERT(toSave.numberOfSetGPRs() == toSaveSize);
 1065
 1066 RegisterAtOffsetList registersToSpill(toSave, RegisterAtOffsetList::OffsetBaseType::FramePointerBased);
 1067 function.jsToWasmEntrypoint.calleeSaveRegisters = registersToSpill;
 1068
 1069 unsigned totalFrameSize = registersToSpill.size() * sizeof(void*);
 1070 totalFrameSize += WasmCallingConvention::headerSizeInBytes();
 1071 totalFrameSize -= sizeof(CallerFrameAndPC);
 1072 unsigned numGPRs = 0;
 1073 unsigned numFPRs = 0;
 1074 for (unsigned i = 0; i < signature->argumentCount(); i++) {
 1075 switch (signature->argument(i)) {
 1076 case Wasm::I64:
 1077 case Wasm::I32:
 1078 if (numGPRs >= wasmCallingConvention().m_gprArgs.size())
 1079 totalFrameSize += sizeof(void*);
 1080 ++numGPRs;
 1081 break;
 1082 case Wasm::F32:
 1083 case Wasm::F64:
 1084 if (numFPRs >= wasmCallingConvention().m_fprArgs.size())
 1085 totalFrameSize += sizeof(void*);
 1086 ++numFPRs;
 1087 break;
 1088 default:
 1089 RELEASE_ASSERT_NOT_REACHED();
 1090 }
 1091 }
10481092
1049  if (!ASSERT_DISABLED) {
1050  // This should be guaranteed by our JS wrapper that handles calls to us.
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));
 1093 totalFrameSize = WTF::roundUpToMultipleOf(stackAlignmentBytes(), totalFrameSize);
 1094 jit.subPtr(MacroAssembler::TrustedImm32(totalFrameSize), MacroAssembler::stackPointerRegister);
10561095
1057  Value* expectedArgumentCount = block->appendNew<Const32Value>(proc, origin, signature->argumentCount());
 1096 // We save all these registers regardless of having a memory or not.
 1097 // The reason is that we use one of these as a scratch. That said,
 1098 // almost all real wasm programs use memory, so it's not really
 1099 // worth optimizing for the case that they don't.
 1100 for (const RegisterAtOffset& regAtOffset : registersToSpill) {
 1101 GPRReg reg = regAtOffset.reg().gpr();
 1102 ptrdiff_t offset = regAtOffset.offset();
 1103 jit.storePtr(reg, CCallHelpers::Address(GPRInfo::callFrameRegister, offset));
 1104 }
10581105
1059  CheckValue* argumentCountCheck = block->appendNew<CheckValue>(proc, Check, origin,
1060  block->appendNew<Value>(proc, Above, origin, expectedArgumentCount, argumentCount));
 1106 {
 1107 CCallHelpers::Address calleeFrame = CCallHelpers::Address(MacroAssembler::stackPointerRegister, -static_cast<ptrdiff_t>(sizeof(CallerFrameAndPC)));
 1108 numGPRs = 0;
 1109 numFPRs = 0;
 1110 // We're going to set the pinned registers after this. So
 1111 // we can use this as a scratch for now since we saved it above.
 1112 GPRReg scratchReg = pinnedRegs.baseMemoryPointer;
 1113
 1114 ptrdiff_t jsOffset = CallFrameSlot::thisArgument * sizeof(void*);
 1115 ptrdiff_t wasmOffset = CallFrame::headerSizeInRegisters * sizeof(void*);
 1116 for (unsigned i = 0; i < signature->argumentCount(); i++) {
 1117 switch (signature->argument(i)) {
 1118 case Wasm::I32:
 1119 case Wasm::I64:
 1120 if (numGPRs >= wasmCallingConvention().m_gprArgs.size()) {
 1121 if (signature->argument(i) == Wasm::I32) {
 1122 jit.load32(CCallHelpers::Address(GPRInfo::callFrameRegister, jsOffset), scratchReg);
 1123 jit.store32(scratchReg, calleeFrame.withOffset(wasmOffset));
 1124 } else {
 1125 jit.load64(CCallHelpers::Address(GPRInfo::callFrameRegister, jsOffset), scratchReg);
 1126 jit.store64(scratchReg, calleeFrame.withOffset(wasmOffset));
 1127 }
 1128 wasmOffset += sizeof(void*);
 1129 } else {
 1130 if (signature->argument(i) == Wasm::I32)
 1131 jit.load32(CCallHelpers::Address(GPRInfo::callFrameRegister, jsOffset), wasmCallingConvention().m_gprArgs[numGPRs].gpr());
 1132 else
 1133 jit.load64(CCallHelpers::Address(GPRInfo::callFrameRegister, jsOffset), wasmCallingConvention().m_gprArgs[numGPRs].gpr());
 1134 }
 1135 ++numGPRs;
 1136 break;
 1137 case Wasm::F32:
 1138 case Wasm::F64:
 1139 if (numFPRs >= wasmCallingConvention().m_fprArgs.size()) {
 1140 if (signature->argument(i) == Wasm::F32) {
 1141 jit.load32(CCallHelpers::Address(GPRInfo::callFrameRegister, jsOffset), scratchReg);
 1142 jit.store32(scratchReg, calleeFrame.withOffset(wasmOffset));
 1143 } else {
 1144 jit.load64(CCallHelpers::Address(GPRInfo::callFrameRegister, jsOffset), scratchReg);
 1145 jit.store64(scratchReg, calleeFrame.withOffset(wasmOffset));
 1146 }
 1147 wasmOffset += sizeof(void*);
 1148 } else {
 1149 if (signature->argument(i) == Wasm::F32)
 1150 jit.loadFloat(CCallHelpers::Address(GPRInfo::callFrameRegister, jsOffset), wasmCallingConvention().m_fprArgs[numFPRs].fpr());
 1151 else
 1152 jit.loadDouble(CCallHelpers::Address(GPRInfo::callFrameRegister, jsOffset), wasmCallingConvention().m_fprArgs[numFPRs].fpr());
 1153 }
 1154 ++numFPRs;
 1155 break;
 1156 default:
 1157 RELEASE_ASSERT_NOT_REACHED();
 1158 }
10611159
1062  argumentCountCheck->setGenerator([] (CCallHelpers& jit, const StackmapGenerationParams&) {
1063  jit.breakpoint();
1064  });
 1160 jsOffset += sizeof(void*);
 1161 }
10651162 }
10661163
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
1068  Value* instance = block->appendNew<MemoryValue>(proc, Load, pointerType(), Origin(),
1069  block->appendNew<ConstPtrValue>(proc, Origin(), &vm.topJSWebAssemblyInstance));
1070  restoreWebAssemblyGlobalState(vm, info.memory, instance, proc, block);
1071 
1072  // Get our arguments.
1073  Vector<Value*> arguments;
1074  jscCallingConvention().loadArguments(signature, proc, block, origin, [&] (Value* argument, unsigned) {
1075  arguments.append(argument);
1076  });
1077 
1078  // Move the arguments into place.
1079  Value* result = wasmCallingConvention().setupCall(proc, block, origin, arguments, toB3Type(signature->returnType()), [&] (PatchpointValue* patchpoint) {
1080  CompilationContext* context = &compilationContext;
1081 
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.
1083  const PinnedRegisterInfo* pinnedRegs = &PinnedRegisterInfo::get();
1084  RegisterSet clobbers;
1085  clobbers.set(pinnedRegs->baseMemoryPointer);
1086  for (auto info : pinnedRegs->sizeRegisters)
1087  clobbers.set(info.sizeRegister);
1088  patchpoint->effects.writesPinned = true;
1089  patchpoint->clobber(clobbers);
 1164 if (!!info.memory) {
 1165 GPRReg baseMemory = pinnedRegs.baseMemoryPointer;
 1166 jit.loadPtr(&vm.topJSWebAssemblyInstance, baseMemory);
 1167 jit.loadPtr(CCallHelpers::Address(baseMemory, JSWebAssemblyInstance::offsetOfMemory()), baseMemory);
 1168 const auto& sizeRegs = pinnedRegs.sizeRegisters;
 1169 ASSERT(sizeRegs.size() >= 1);
 1170 ASSERT(!sizeRegs[0].sizeOffset); // The following code assumes we start at 0, and calculates subsequent size registers relative to 0.
 1171 jit.loadPtr(CCallHelpers::Address(baseMemory, JSWebAssemblyMemory::offsetOfSize()), sizeRegs[0].sizeRegister);
 1172 jit.loadPtr(CCallHelpers::Address(baseMemory, JSWebAssemblyMemory::offsetOfMemory()), baseMemory);
 1173 for (unsigned i = 1; i < sizeRegs.size(); ++i)
 1174 jit.add64(CCallHelpers::TrustedImm32(-sizeRegs[i].sizeOffset), sizeRegs[0].sizeRegister, sizeRegs[i].sizeRegister);
 1175 }
10901176
1091  patchpoint->setGenerator([context] (CCallHelpers& jit, const B3::StackmapGenerationParams&) {
1092  AllowMacroScratchRegisterUsage allowScratch(jit);
 1177 compilationContext.jsEntrypointToWasmEntrypointCall = jit.call();
10931178
1094  CCallHelpers::Call call = jit.call();
1095  context->jsEntrypointToWasmEntrypointCall = call;
1096  });
1097  });
 1179 for (const RegisterAtOffset& regAtOffset : registersToSpill) {
 1180 GPRReg reg = regAtOffset.reg().gpr();
 1181 ASSERT(reg != GPRInfo::returnValueGPR);
 1182 ptrdiff_t offset = regAtOffset.offset();
 1183 jit.loadPtr(CCallHelpers::Address(GPRInfo::callFrameRegister, offset), reg);
 1184 }
10981185
1099  // Return the result, if needed.
11001186 switch (signature->returnType()) {
1101  case Wasm::Void:
1102  block->appendNewControlValue(proc, B3::Return, origin);
1103  break;
11041187 case Wasm::F32:
 1188 jit.moveFloatTo32(FPRInfo::returnValueFPR, GPRInfo::returnValueGPR);
 1189 break;
11051190 case Wasm::F64:
1106  result = block->appendNew<Value>(proc, BitwiseCast, origin, result);
1107  FALLTHROUGH;
1108  case Wasm::I32:
1109  case Wasm::I64:
1110  block->appendNewControlValue(proc, B3::Return, origin, result);
 1191 jit.moveDoubleTo64(FPRInfo::returnValueFPR, GPRInfo::returnValueGPR);
 1192 break;
 1193 default:
11111194 break;
1112  case Wasm::Func:
1113  case Wasm::Anyfunc:
1114  RELEASE_ASSERT_NOT_REACHED();
11151195 }
11161196
1117  B3::prepareForGeneration(proc);
1118  B3::generate(proc, *compilationContext.jsEntrypointJIT);
1119  compilationContext.jsEntrypointByproducts = proc.releaseByproducts();
1120  function.jsToWasmEntrypoint.calleeSaveRegisters = proc.calleeSaveRegisters();
 1197 jit.emitFunctionEpilogue();
 1198 jit.ret();
11211199}
11221200
11231201Expected<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)
213654

Source/JavaScriptCore/wasm/WasmCallingConvention.h

@@private:
8484 }
8585
8686public:
 87 static unsigned headerSizeInBytes() { return headerSize; }
8788 void setupFrameInPrologue(CodeLocationDataLabelPtr* calleeMoveLocation, B3::Procedure& proc, B3::Origin origin, B3::BasicBlock* block) const
8889 {
8990 static_assert(CallFrameSlot::callee * sizeof(Register) < headerSize, "We rely on this here for now.");
213654

Source/JavaScriptCore/wasm/js/JSWebAssemblyHelpers.h

2929
3030#include "JSArrayBuffer.h"
3131#include "JSCJSValue.h"
 32#include "WebAssemblyFunction.h"
 33#include "WebAssemblyWrapperFunction.h"
3234
3335namespace JSC {
3436

@@ALWAYS_INLINE uint8_t* getWasmBufferFrom
7173 return arrayBufferView ? static_cast<uint8_t*>(arrayBufferView->vector()) : static_cast<uint8_t*>(arrayBuffer->impl()->data());
7274}
7375
 76ALWAYS_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
 91ALWAYS_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
 99ALWAYS_INLINE bool isWebAssemblyHostFunction(VM& vm, JSObject* object)
 100{
 101 WebAssemblyFunction* unused;
 102 WebAssemblyWrapperFunction* unused2;
 103 return isWebAssemblyHostFunction(vm, object, unused, unused2);
 104}
 105
74106} // namespace JSC
75107
76108#endif // ENABLE(WEBASSEMBLY)
213654

Source/JavaScriptCore/wasm/js/JSWebAssemblyInstance.cpp

@@JSWebAssemblyInstance::JSWebAssemblyInst
6767 : Base(vm, structure)
6868 , m_numImportFunctions(numImportFunctions)
6969{
70  memset(importFunctions(), 0, m_numImportFunctions * sizeof(WriteBarrier<JSCell>));
 70 memset(importFunctions(), 0, m_numImportFunctions * sizeof(WriteBarrier<JSObject>));
7171}
7272
7373void JSWebAssemblyInstance::finishCreation(VM& vm, JSWebAssemblyModule* module, JSModuleNamespaceObject* moduleNamespaceObject)
213654

Source/JavaScriptCore/wasm/js/JSWebAssemblyInstance.h

@@public:
6060 return m_codeBlock.get();
6161 }
6262
63  WriteBarrier<JSCell>* importFunction(unsigned idx)
 63 WriteBarrier<JSObject>* importFunction(unsigned idx)
6464 {
6565 RELEASE_ASSERT(idx < m_numImportFunctions);
6666 return &importFunctions()[idx];
6767 }
6868
69  WriteBarrier<JSCell>* importFunctions()
 69 WriteBarrier<JSObject>* importFunctions()
7070 {
71  return bitwise_cast<WriteBarrier<JSCell>*>(bitwise_cast<char*>(this) + offsetOfImportFunctions());
 71 return bitwise_cast<WriteBarrier<JSObject>*>(bitwise_cast<char*>(this) + offsetOfImportFunctions());
7272 }
7373
74  void setImportFunction(VM& vm, JSCell* value, unsigned idx)
 74 void setImportFunction(VM& vm, JSObject* value, unsigned idx)
7575 {
7676 importFunction(idx)->set(vm, this, value);
7777 }
213654

Source/JavaScriptCore/wasm/js/JSWebAssemblyTable.cpp

@@JSWebAssemblyTable::JSWebAssemblyTable(V
6464 // FIXME: It might be worth trying to pre-allocate maximum here. The spec recommends doing so.
6565 // But for now, we're not doing that.
6666 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));
6868 for (uint32_t i = 0; i < m_size; ++i) {
6969 new (&m_functions.get()[i]) Wasm::CallableFunction();
7070 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>();
7272 }
7373}
7474

@@bool JSWebAssemblyTable::grow(uint32_t n
106106 return false;
107107
108108 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));
110110
111111 for (uint32_t i = m_size; i < newSize; ++i) {
112112 new (&m_functions.get()[i]) Wasm::CallableFunction();
113  new (&m_jsFunctions.get()[i]) WriteBarrier<WebAssemblyFunction>();
 113 new (&m_jsFunctions.get()[i]) WriteBarrier<JSObject>();
114114 }
115115 m_size = newSize;
116116 return true;

@@bool JSWebAssemblyTable::grow(uint32_t n
119119void JSWebAssemblyTable::clearFunction(uint32_t index)
120120{
121121 RELEASE_ASSERT(index < m_size);
122  m_jsFunctions.get()[index] = WriteBarrier<WebAssemblyFunction>();
 122 m_jsFunctions.get()[index] = WriteBarrier<JSObject>();
123123 m_functions.get()[index] = Wasm::CallableFunction();
124124 ASSERT(m_functions.get()[index].signatureIndex == Wasm::Signature::invalidIndex); // We rely on this in compiled code.
125125}

@@void JSWebAssemblyTable::setFunction(VM&
131131 m_functions.get()[index] = Wasm::CallableFunction(function->signatureIndex(), function->wasmEntrypoint());
132132}
133133
 134void 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
134141} // namespace JSC
135142
136143#endif // ENABLE(WEBASSEMBLY)
213654

Source/JavaScriptCore/wasm/js/JSWebAssemblyTable.h

2929
3030#include "JSDestructibleObject.h"
3131#include "JSObject.h"
 32#include "WebAssemblyWrapperFunction.h"
3233#include "WebAssemblyFunction.h"
3334#include <wtf/MallocPtr.h>
3435

@@public:
5051 std::optional<uint32_t> maximum() const { return m_maximum; }
5152 uint32_t size() const { return m_size; }
5253 bool grow(uint32_t newSize) WARN_UNUSED_RETURN;
53  WebAssemblyFunction* getFunction(uint32_t index)
 54 JSObject* getFunction(uint32_t index)
5455 {
5556 RELEASE_ASSERT(index < m_size);
5657 return m_jsFunctions.get()[index].get();
5758 }
5859 void clearFunction(uint32_t index);
5960 void setFunction(VM&, uint32_t index, WebAssemblyFunction*);
 61 void setFunction(VM&, uint32_t index, WebAssemblyWrapperFunction*);
6062
6163 static ptrdiff_t offsetOfSize() { return OBJECT_OFFSETOF(JSWebAssemblyTable, m_size); }
6264 static ptrdiff_t offsetOfFunctions() { return OBJECT_OFFSETOF(JSWebAssemblyTable, m_functions); }

@@private:
7476 static void visitChildren(JSCell*, SlotVisitor&);
7577
7678 MallocPtr<Wasm::CallableFunction> m_functions;
77  MallocPtr<WriteBarrier<WebAssemblyFunction>> m_jsFunctions;
 79 MallocPtr<WriteBarrier<JSObject>> m_jsFunctions;
7880 std::optional<uint32_t> m_maximum;
7981 uint32_t m_size;
8082};
213654

Source/JavaScriptCore/wasm/js/WebAssemblyInstanceConstructor.cpp

3232#include "JSCInlines.h"
3333#include "JSModuleEnvironment.h"
3434#include "JSModuleNamespaceObject.h"
 35#include "JSWebAssemblyHelpers.h"
3536#include "JSWebAssemblyInstance.h"
3637#include "JSWebAssemblyLinkError.h"
3738#include "JSWebAssemblyMemory.h"

@@JSWebAssemblyInstance* WebAssemblyInstan
129130 if (!value.isFunction())
130131 return exception(createJSWebAssemblyLinkError(exec, vm, ASCIILiteral("import function must be callable")));
131132
132  JSCell* cell = value.asCell();
 133 JSObject* function = jsCast<JSObject*>(value);
133134 // 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)) {
135138 // 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 }
137147 Wasm::SignatureIndex expectedSignatureIndex = moduleInformation.importFunctionSignatureIndices[import.kindIndex];
138148 if (importedSignatureIndex != expectedSignatureIndex)
139149 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]].
141150 }
142151 // iii. Otherwise:
143152 // 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.

@@JSWebAssemblyInstance* WebAssemblyInstan
146155 // 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).
147156
148157 ASSERT(numImportFunctions == import.kindIndex);
149  instance->setImportFunction(vm, cell, numImportFunctions++);
 158 instance->setImportFunction(vm, function, numImportFunctions++);
150159 // v. Append closure to imports.
151160 break;
152161 }
213654

Source/JavaScriptCore/wasm/js/WebAssemblyModuleRecord.cpp

3232#include "JSCInlines.h"
3333#include "JSLexicalEnvironment.h"
3434#include "JSModuleEnvironment.h"
 35#include "JSWebAssemblyHelpers.h"
3536#include "JSWebAssemblyInstance.h"
3637#include "JSWebAssemblyLinkError.h"
3738#include "JSWebAssemblyModule.h"

@@void WebAssemblyModuleRecord::link(ExecS
110111 // i. If there is an Exported Function Exotic Object func in funcs whose func.[[Closure]] equals c, then return func.
111112 // 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.)
112113 if (exp.kindIndex < functionImportCount) {
113  // FIXME Implement re-exporting an import. https://bugs.webkit.org/show_bug.cgi?id=165510
114  RELEASE_ASSERT_NOT_REACHED();
 114 unsigned functionIndex = exp.kindIndex;
 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;
115133 }
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;
126134 break;
127135 }
128136 case Wasm::ExternalKind::Table: {

@@void WebAssemblyModuleRecord::link(ExecS
184192 ASSERT(!signature->argumentCount());
185193 ASSERT(signature->returnType() == Wasm::Void);
186194 if (startFunctionIndexSpace < codeBlock->functionImportCount()) {
187  JSCell* startFunction = instance->importFunction(startFunctionIndexSpace)->get();
 195 JSObject* startFunction = instance->importFunction(startFunctionIndexSpace)->get();
188196 m_startFunction.set(vm, this, startFunction);
189197 } else {
190198 JSWebAssemblyCallee* jsEntrypointCallee = codeBlock->jsEntrypointCalleeFromFunctionIndexSpace(startFunctionIndexSpace);

@@JSValue WebAssemblyModuleRecord::evaluat
241249 // for the import.
242250 // https://bugs.webkit.org/show_bug.cgi?id=165510
243251 uint32_t functionIndex = element.functionIndices[i];
 252 Wasm::SignatureIndex signatureIndex = module->signatureIndexFromFunctionIndexSpace(functionIndex);
244253 if (functionIndex < codeBlock->functionImportCount()) {
245  return JSValue::decode(
246  throwVMRangeError(state, scope, ASCIILiteral("Element is setting the table value with an import. This is not yet implemented. FIXME.")));
 254 JSObject* functionImport = jsCast<JSObject*>(m_instance->importFunction(functionIndex)->get());
 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;
247270 }
248271
249272 JSWebAssemblyCallee* jsEntrypointCallee = codeBlock->jsEntrypointCalleeFromFunctionIndexSpace(functionIndex);
250273 JSWebAssemblyCallee* wasmEntrypointCallee = codeBlock->wasmEntrypointCalleeFromFunctionIndexSpace(functionIndex);
251  Wasm::SignatureIndex signatureIndex = module->signatureIndexFromFunctionIndexSpace(functionIndex);
252274 const Wasm::Signature* signature = Wasm::SignatureInformation::get(&vm, signatureIndex);
253275 // FIXME: Say we export local function "foo" at function index 0.
254276 // What if we also set it to the table an Element w/ index 0.

@@JSValue WebAssemblyModuleRecord::evaluat
288310 }
289311 }
290312
291  if (JSCell* startFunction = m_startFunction.get()) {
 313 if (JSObject* startFunction = m_startFunction.get()) {
292314 CallData callData;
293315 CallType callType = JSC::getCallData(startFunction, callData);
294316 call(state, startFunction, callType, callData, jsUndefined(), state->emptyList());
213654

Source/JavaScriptCore/wasm/js/WebAssemblyModuleRecord.h

@@private:
5959 static void visitChildren(JSCell*, SlotVisitor&);
6060
6161 WriteBarrier<JSWebAssemblyInstance> m_instance;
62  WriteBarrier<JSCell> m_startFunction;
 62 WriteBarrier<JSObject> m_startFunction;
6363};
6464
6565} // namespace JSC
213654

Source/JavaScriptCore/wasm/js/WebAssemblyTablePrototype.cpp

@@EncodedJSValue JSC_HOST_CALL webAssembly
106106 return { };
107107 }
108108
109  if (WebAssemblyFunction* result = table->getFunction(index))
 109 if (JSObject* result = table->getFunction(index))
110110 return JSValue::encode(result);
111111 return JSValue::encode(jsNull());
112112}

@@EncodedJSValue JSC_HOST_CALL webAssembly
120120 RETURN_IF_EXCEPTION(throwScope, encodedJSValue());
121121
122122 JSValue value = exec->argument(1);
123  WebAssemblyFunction* function = jsDynamicCast<WebAssemblyFunction*>(vm, value);
124  if (!value.isNull() && !function) {
 123 WebAssemblyFunction* wasmFunction;
 124 WebAssemblyWrapperFunction* wasmWrapperFunction;
 125 if (!value.isNull() && !isWebAssemblyHostFunction(vm, value, wasmFunction, wasmWrapperFunction)) {
125126 throwException(exec, throwScope,
126127 createTypeError(exec, ASCIILiteral("WebAssembly.Table.prototype.set expects the second argument to be null or an instance of WebAssembly.Function")));
127128 return { };

@@EncodedJSValue JSC_HOST_CALL webAssembly
139140 if (value.isNull())
140141 table->clearFunction(index);
141142 else {
142  ASSERT(!!function);
143  table->setFunction(vm, index, function);
 143 ASSERT(value.isObject() && isWebAssemblyHostFunction(vm, jsCast<JSObject*>(value), wasmFunction, wasmWrapperFunction));
 144 ASSERT(!!wasmFunction || !!wasmWrapperFunction);
 145 if (wasmFunction)
 146 table->setFunction(vm, index, wasmFunction);
 147 else
 148 table->setFunction(vm, index, wasmWrapperFunction);
144149 }
145150
146151 return JSValue::encode(jsUndefined());
213654

Source/JavaScriptCore/wasm/js/WebAssemblyWrapperFunction.cpp

 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
 35namespace JSC {
 36
 37const ClassInfo WebAssemblyWrapperFunction::s_info = { "WebAssemblyWrapperFunction", &Base::s_info, nullptr, CREATE_METHOD_TABLE(WebAssemblyWrapperFunction) };
 38
 39static 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
 55WebAssemblyWrapperFunction::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
 61WebAssemblyWrapperFunction* 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
 72void 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
 80Structure* 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
 86void 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)
nonexistent

Source/JavaScriptCore/wasm/js/WebAssemblyWrapperFunction.h

 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
 33namespace JSC {
 34
 35class WebAssemblyWrapperFunction : public JSFunction {
 36public:
 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
 50protected:
 51 static void visitChildren(JSCell*, SlotVisitor&);
 52
 53 void finishCreation(VM&, NativeExecutable*, unsigned length, const String& name, JSObject*, JSWebAssemblyCodeBlock*);
 54
 55private:
 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)
nonexistent