Changeset 209642 in webkit
- Timestamp:
- Dec 9, 2016 6:34:02 PM (7 years ago)
- Location:
- trunk
- Files:
-
- 1 added
- 12 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/JSTests/ChangeLog
r209630 r209642 1 2016-12-09 JF Bastien <jfbastien@apple.com> 2 3 WebAssembly JS API: implement start function 4 https://bugs.webkit.org/show_bug.cgi?id=165150 5 6 Reviewed by Saam Barati. 7 8 * wasm/Builder.js: allow building a .Start() 9 * wasm/Builder_WebAssemblyBinary.js: 10 * wasm/js-api/test_Start.js: Added. 11 (const.emitters.Start): serialize a start section 12 * wasm/self-test/test_BuilderJSON.js: validate the start section's content 13 1 14 2016-12-09 Saam Barati <sbarati@apple.com> 2 15 -
trunk/JSTests/wasm/Builder.js
r209630 r209642 438 438 439 439 case "Start": 440 // FIXME implement start https://bugs.webkit.org/show_bug.cgi?id=161709 441 this[section] = () => { throw new Error(`Unimplemented: section type "${section}"`); }; 440 this[section] = function(functionIndexOrName) { 441 const s = this._addSection(section); 442 const startBuilder = { 443 End: () => this, 444 }; 445 if (typeof(functionIndexOrName) !== "number" && typeof(functionIndexOrName) !== "string") 446 throw new Error(`Start section's function index must either be a number or a string`); 447 s.data.push(functionIndexOrName); 448 return startBuilder; 449 }; 442 450 break; 443 451 … … 457 465 const importSection = builder._getSection("Import"); 458 466 const exportSection = builder._getSection("Export"); 467 const startSection = builder._getSection("Start"); 459 468 const codeSection = s; 460 469 if (exportSection) { … … 489 498 } 490 499 } 500 if (startSection) { 501 const start = startSection.data[0]; 502 let mapped = builder._getFunctionFromIndexSpace(start); 503 if (!builder._checked) { 504 if (typeof(mapped) === "undefined") 505 mapped = start; // In unchecked mode, simply use what was provided if it's nonsensical. 506 assert.isA(start, "number"); // It can't be too nonsensical, otherwise we can't create a binary. 507 startSection.data[0] = start; 508 } else { 509 if (typeof(mapped) === "undefined") 510 throw new Error(`Start section refers to non-existant function '${start}'`); 511 if (typeof(start) === "string" || typeof(start) === "object") 512 startSection.data[0] = mapped; 513 // FIXME in checked mode, test that the type is acceptable for start function. We probably want _registerFunctionToIndexSpace to also register types per index. https://bugs.webkit.org/show_bug.cgi?id=165658 514 } 515 } 491 516 return builder; 492 517 }, -
trunk/JSTests/wasm/Builder_WebAssemblyBinary.js
r209630 r209642 116 116 } 117 117 }, 118 Start: (section, bin) => { throw new Error(`Not yet implemented`); }, 118 Start: (section, bin) => { 119 put(bin, "varuint32", section.data[0]); 120 }, 119 121 Element: (section, bin) => { throw new Error(`Not yet implemented`); }, 120 122 -
trunk/JSTests/wasm/self-test/test_BuilderJSON.js
r209630 r209642 241 241 assert.throws(() => e.Function("foo", 0, { params: ["i32"] }), Error, `Not the same: "1" and "0": Re-exporting import "bar" as "foo" has mismatching type`); 242 242 })(); 243 244 (function StartInvalidNumberedFunction() { 245 const b = (new Builder()) 246 .Type().End() 247 .Function().End() 248 .Start(0).End() 249 assert.throws(() => b.Code().End(), Error, `Start section refers to non-existant function '0'`); 250 })(); 251 252 (function StartInvalidNamedFunction() { 253 const b = (new Builder()) 254 .Type().End() 255 .Function().End() 256 .Start("foo").End(); 257 assert.throws(() => b.Code().End(), Error, `Start section refers to non-existant function 'foo'`); 258 })(); 259 260 (function StartNamedFunction() { 261 const b = (new Builder()) 262 .Type().End() 263 .Function().End() 264 .Start("foo").End() 265 .Code() 266 .Function("foo", { params: [] }).End() 267 .End(); 268 const j = JSON.parse(b.json()); 269 assert.eq(j.section.length, 4); 270 assert.eq(j.section[2].name, "Start"); 271 assert.eq(j.section[2].data.length, 1); 272 assert.eq(j.section[2].data[0], 0); 273 })(); 274 275 /* FIXME implement checking of signature https://bugs.webkit.org/show_bug.cgi?id=165658 276 (function StartInvalidTypeArg() { 277 const b = (new Builder()) 278 .Type().End() 279 .Function().End() 280 .Start("foo").End() 281 assert.throws(() => b.Code().Function("foo", { params: ["i32"] }).End(), Error, `???`); 282 })(); 283 284 (function StartInvalidTypeReturn() { 285 const b = (new Builder()) 286 .Type().End() 287 .Function().End() 288 .Start("foo").End() 289 assert.throws(() => b.Code().Function("foo", { params: [], ret: "i32" }).I32Const(42).Ret().End(), Error, `???`); 290 })(); 291 */ 292 293 // FIXME test start of import or table. https://bugs.webkit.org/show_bug.cgi?id=165658 243 294 244 295 (function EmptyCodeSection() { -
trunk/Source/JavaScriptCore/ChangeLog
r209638 r209642 1 2016-12-09 JF Bastien <jfbastien@apple.com> 2 3 WebAssembly JS API: implement start function 4 https://bugs.webkit.org/show_bug.cgi?id=165150 5 6 Reviewed by Saam Barati. 7 8 * wasm/WasmFormat.h: pass the start function around 9 * wasm/WasmModuleParser.cpp: 10 (JSC::Wasm::ModuleParser::parseTable): mark unreachable code 11 (JSC::Wasm::ModuleParser::parseGlobal): mark unreachable code 12 (JSC::Wasm::ModuleParser::parseStart): mark unreachable code 13 (JSC::Wasm::ModuleParser::parseElement): mark unreachable code 14 (JSC::Wasm::ModuleParser::parseData): mark unreachable code 15 * wasm/js/WebAssemblyFunction.cpp: 16 (JSC::callWebAssemblyFunction): NFC: call the new function below 17 (JSC::WebAssemblyFunction::call): separate this out so that the start function can use it 18 * wasm/js/WebAssemblyFunction.h: 19 * wasm/js/WebAssemblyModuleRecord.cpp: 20 (JSC::WebAssemblyModuleRecord::visitChildren): visit the start function 21 (JSC::WebAssemblyModuleRecord::link): handle start function 22 (JSC::WebAssemblyModuleRecord::evaluate): call the start function, if present 23 * wasm/js/WebAssemblyModuleRecord.h: 24 1 25 2016-12-09 Filip Pizlo <fpizlo@apple.com> 2 26 -
trunk/Source/JavaScriptCore/wasm/WasmFormat.cpp
r209630 r209642 34 34 namespace JSC { namespace Wasm { 35 35 36 JS_EXPORT_PRIVATE ModuleInformation::~ModuleInformation() { } 37 36 38 } } // namespace JSC::Wasm 37 39 -
trunk/Source/JavaScriptCore/wasm/WasmFormat.h
r209630 r209642 36 36 #include "WasmOps.h" 37 37 #include "WasmPageCount.h" 38 #include <wtf/Optional.h> 38 39 #include <wtf/Vector.h> 39 40 … … 124 125 MemoryInformation memory; 125 126 Vector<Export> exports; 127 std::optional<uint32_t> startFunctionIndexSpace; 128 129 ~ModuleInformation(); 126 130 }; 127 131 -
trunk/Source/JavaScriptCore/wasm/WasmModuleParser.cpp
r209630 r209642 304 304 bool ModuleParser::parseTable() 305 305 { 306 // FIXME 306 // FIXME implement table https://bugs.webkit.org/show_bug.cgi?id=164135 307 RELEASE_ASSERT_NOT_REACHED(); 307 308 return true; 308 309 } … … 366 367 { 367 368 // FIXME https://bugs.webkit.org/show_bug.cgi?id=164133 369 RELEASE_ASSERT_NOT_REACHED(); 368 370 return true; 369 371 } … … 416 418 bool ModuleParser::parseStart() 417 419 { 420 uint32_t startFunctionIndex; 421 if (!parseVarUInt32(startFunctionIndex) 422 || startFunctionIndex >= m_functionIndexSpace.size()) 423 return false; 424 Signature* signature = m_functionIndexSpace[startFunctionIndex].signature; 425 if (signature->arguments.size() != 0 426 || signature->returnType != Void) 427 return false; 428 m_module->startFunctionIndexSpace = startFunctionIndex; 429 return true; 430 } 431 432 bool ModuleParser::parseElement() 433 { 418 434 // FIXME https://bugs.webkit.org/show_bug.cgi?id=161709 419 return true; 420 } 421 422 bool ModuleParser::parseElement() 423 { 424 // FIXME https://bugs.webkit.org/show_bug.cgi?id=161709 435 RELEASE_ASSERT_NOT_REACHED(); 425 436 return true; 426 437 } … … 451 462 { 452 463 // FIXME https://bugs.webkit.org/show_bug.cgi?id=161709 464 RELEASE_ASSERT_NOT_REACHED(); 453 465 return true; 454 466 } -
trunk/Source/JavaScriptCore/wasm/js/WebAssemblyFunction.cpp
r209630 r209642 93 93 } 94 94 95 // Note: we specifically use the WebAssemblyFunction as the callee to begin with in the ProtoCallFrame. 96 // The reason for this is that calling into the llint may stack overflow, and the stack overflow 97 // handler might read the global object from the callee. The JSWebAssemblyCallee doesn't have a 98 // global object, but the WebAssemblyFunction does. 99 ProtoCallFrame protoCallFrame; 100 protoCallFrame.init(nullptr, wasmFunction, firstArgument, argCount, remainingArgs); 101 102 return wasmFunction->call(vm, &protoCallFrame); 103 } 104 105 EncodedJSValue WebAssemblyFunction::call(VM& vm, ProtoCallFrame* protoCallFrame) 106 { 95 107 // Setup the memory that the entrance loads. 96 if (JSWebAssemblyMemory* memory = wasmFunction->instance()->memory()) {108 if (JSWebAssemblyMemory* memory = instance()->memory()) { 97 109 Wasm::Memory* wasmMemory = memory->memory(); 98 110 vm.topWasmMemoryPointer = wasmMemory->memory(); … … 103 115 } 104 116 105 // Note: we specifically use the WebAsseblyFunction as the callee to begin with in the ProtoCallFrame.106 // The reason for this is that calling into the llint may stack overflow, and the stack overflow107 // handler might read the global object from the callee. The JSWebAssemblyCallee doesn't have a108 // global object, but the WebAssemblyFunction does.109 ProtoCallFrame protoCallFrame;110 protoCallFrame.init(nullptr, wasmFunction, firstArgument, argCount, remainingArgs);111 112 117 JSWebAssemblyInstance* prevJSWebAssemblyInstance = vm.topJSWebAssemblyInstance; 113 vm.topJSWebAssemblyInstance = wasmFunction->instance();114 EncodedJSValue rawResult = vmEntryToWasm(w asmFunction->webAssemblyCallee()->jsToWasmEntryPoint(), &vm, &protoCallFrame);118 vm.topJSWebAssemblyInstance = instance(); 119 EncodedJSValue rawResult = vmEntryToWasm(webAssemblyCallee()->jsToWasmEntryPoint(), &vm, protoCallFrame); 115 120 vm.topJSWebAssemblyInstance = prevJSWebAssemblyInstance; 116 121 117 122 // FIXME is this correct? https://bugs.webkit.org/show_bug.cgi?id=164876 118 switch (signature ->returnType) {123 switch (signature()->returnType) { 119 124 case Wasm::Void: 120 125 return JSValue::encode(jsUndefined()); -
trunk/Source/JavaScriptCore/wasm/js/WebAssemblyFunction.h
r209560 r209642 35 35 class JSGlobalObject; 36 36 class JSWebAssemblyCallee; 37 struct ProtoCallFrame; 37 38 class WebAssemblyInstance; 38 39 … … 63 64 return m_signature; 64 65 } 66 EncodedJSValue call(VM&, ProtoCallFrame*); 65 67 66 68 protected: -
trunk/Source/JavaScriptCore/wasm/js/WebAssemblyModuleRecord.cpp
r209630 r209642 35 35 #include "JSWebAssemblyInstance.h" 36 36 #include "JSWebAssemblyModule.h" 37 #include "ProtoCallFrame.h" 37 38 #include "WasmFormat.h" 38 39 #include "WebAssemblyFunction.h" 40 #include <limits> 39 41 40 42 namespace JSC { … … 97 99 Base::visitChildren(thisObject, visitor); 98 100 visitor.append(&thisObject->m_instance); 101 visitor.append(&thisObject->m_startFunction); 99 102 } 100 103 … … 108 111 JSWebAssemblyModule* module = instance->module(); 109 112 const Wasm::ModuleInformation& moduleInformation = module->moduleInformation(); 113 114 bool hasStart = !!moduleInformation.startFunctionIndexSpace; 115 auto startFunctionIndexSpace = moduleInformation.startFunctionIndexSpace.value_or(0); 116 110 117 SymbolTable* exportSymbolTable = module->exportSymbolTable(); 111 118 unsigned importCount = module->importCount(); … … 134 141 WebAssemblyFunction* function = WebAssemblyFunction::create(vm, globalObject, signature->arguments.size(), exp.field.string(), instance, wasmCallee, signature); 135 142 exportedValue = function; 143 if (hasStart && startFunctionIndexSpace == exp.functionIndex) 144 m_startFunction.set(vm, this, function); 136 145 break; 137 146 } … … 158 167 } 159 168 169 if (hasStart) { 170 Wasm::Signature* signature = module->signatureForFunctionIndexSpace(startFunctionIndexSpace); 171 // The start function must not take any arguments or return anything. This is enforced by the parser. 172 ASSERT(!signature->arguments.size()); 173 ASSERT(signature->returnType == Wasm::Void); 174 // FIXME can start call imports / tables? This assumes not. https://github.com/WebAssembly/design/issues/896 175 if (!m_startFunction.get()) { 176 // The start function wasn't added above. It must be a purely internal function. 177 JSWebAssemblyCallee* wasmCallee = module->calleeFromFunctionIndexSpace(startFunctionIndexSpace); 178 WebAssemblyFunction* function = WebAssemblyFunction::create(vm, globalObject, signature->arguments.size(), "start", instance, wasmCallee, signature); 179 m_startFunction.set(vm, this, function); 180 } 181 } 182 160 183 RELEASE_ASSERT(!m_instance); 161 184 m_instance.set(vm, this, instance); … … 165 188 JSValue WebAssemblyModuleRecord::evaluate(ExecState* state) 166 189 { 167 // FIXME this should call the module's `start` function, if any. https://bugs.webkit.org/show_bug.cgi?id=165150 168 // https://github.com/WebAssembly/design/blob/master/Modules.md#module-start-function 169 // The start function must not take any arguments or return anything 170 UNUSED_PARAM(state); 190 if (WebAssemblyFunction* startFunction = m_startFunction.get()) { 191 VM& vm = state->vm(); 192 auto scope = DECLARE_THROW_SCOPE(vm); 193 ProtoCallFrame protoCallFrame; 194 protoCallFrame.init(nullptr, startFunction, JSValue(), 1, nullptr); 195 startFunction->call(vm, &protoCallFrame); 196 RETURN_IF_EXCEPTION(scope, { }); 197 } 171 198 return jsUndefined(); 172 199 } -
trunk/Source/JavaScriptCore/wasm/js/WebAssemblyModuleRecord.h
r209171 r209642 34 34 35 35 class JSWebAssemblyInstance; 36 class WebAssemblyFunction; 36 37 37 38 // Based on the WebAssembly.Instance specification … … 59 60 60 61 WriteBarrier<JSWebAssemblyInstance> m_instance; 62 WriteBarrier<WebAssemblyFunction> m_startFunction; 61 63 }; 62 64
Note: See TracChangeset
for help on using the changeset viewer.