Changeset 246571 in webkit
- Timestamp:
- Jun 18, 2019 3:01:02 PM (5 years ago)
- Location:
- trunk
- Files:
-
- 1 added
- 26 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/JSTests/ChangeLog
r246567 r246571 1 2019-06-18 Justin Michaud <justin_michaud@apple.com> 2 3 [WASM-References] Add support for multiple tables 4 https://bugs.webkit.org/show_bug.cgi?id=198760 5 6 Reviewed by Saam Barati. 7 8 * wasm/Builder.js: 9 * wasm/js-api/call-indirect.js: 10 (const.oneTable): 11 (const.multiTable): 12 (multiTable): 13 (multiTable.Polyphic2Import): 14 (multiTable.VirtualImport): 15 (const.wasmModuleWhichImportJS): Deleted. 16 (const.makeTable): Deleted. 17 (): Deleted. 18 (Polyphic2Import): Deleted. 19 (VirtualImport): Deleted. 20 * wasm/js-api/table.js: 21 (new.WebAssembly.Module): 22 (assert.throws): 23 (assertBadTableImport): 24 (assert.truthy): 25 (assert.throws.new.WebAssembly.Module.builder.WebAssembly): Deleted. 26 * wasm/references/anyref_table.js: 27 * wasm/references/anyref_table_import.js: 28 (makeImport): 29 (string_appeared_here.fullGC.assert.eq.1.exports.get_tbl.makeImport): 30 (string_appeared_here.fullGC.assert.eq.1.exports.get_tbl): 31 * wasm/references/multitable.js: Added. 32 (assert.throws.1.exports.set_tbl0): 33 (assert.throws): 34 (assert.eq): 35 * wasm/references/validation.js: 36 (assert.throws.new.WebAssembly.Module.bin): 37 (assert.throws): 38 * wasm/spec-tests/imports.wast.js: 39 * wasm/wasm.json: 40 41 * wasm/Builder.js: 42 * wasm/js-api/call-indirect.js: 43 (const.oneTable): 44 (const.multiTable): 45 (multiTable): 46 (multiTable.Polyphic2Import): 47 (multiTable.VirtualImport): 48 (const.wasmModuleWhichImportJS): Deleted. 49 (const.makeTable): Deleted. 50 (): Deleted. 51 (Polyphic2Import): Deleted. 52 (VirtualImport): Deleted. 53 * wasm/js-api/table.js: 54 (new.WebAssembly.Module): 55 (assert.throws): 56 (assertBadTableImport): 57 (assert.truthy): 58 (assert.throws.new.WebAssembly.Module.builder.WebAssembly): Deleted. 59 * wasm/references/anyref_table.js: 60 * wasm/references/anyref_table_import.js: 61 (makeImport): 62 (string_appeared_here.fullGC.assert.eq.1.exports.get_tbl.makeImport): 63 (string_appeared_here.fullGC.assert.eq.1.exports.get_tbl): 64 * wasm/references/func_ref.js: 65 (GetLocal.0.I32Const.0.TableSet.End.End.WebAssembly.fun): Deleted. 66 (GetLocal.0.I32Const.0.TableSet.End.End.WebAssembly.assert.throws): Deleted. 67 (GetLocal.0.I32Const.0.TableSet.End.End.WebAssembly): Deleted. 68 * wasm/references/multitable.js: Added. 69 (assert.throws.1.exports.set_tbl0): 70 (assert.throws): 71 (assert.eq): 72 (string_appeared_here.tableInsanity): 73 (I32Const.0.GetLocal.0.TableSet.1.End.End.WebAssembly.): 74 (I32Const.0.GetLocal.0.TableSet.1.End.End.WebAssembly): 75 * wasm/references/validation.js: 76 (assert.throws.new.WebAssembly.Module.bin): 77 (assert.throws): 78 * wasm/spec-tests/imports.wast.js: 79 * wasm/wasm.json: 80 1 81 2019-06-18 Alexey Shvayka <shvaikalesh@gmail.com> 2 82 -
trunk/JSTests/wasm/Builder.js
r246504 r246571 307 307 case "target_table": break; // improve checking https://bugs.webkit.org/show_bug.cgi?id=163421 308 308 case "reserved": break; // improve checking https://bugs.webkit.org/show_bug.cgi?id=163421 309 case "table_index": break; // improve checking https://bugs.webkit.org/show_bug.cgi?id=163421 309 310 default: throw new Error(`Implementation problem: unhandled immediate "${expect.name}" on "${op}"`); 310 311 } -
trunk/JSTests/wasm/js-api/call-indirect.js
r209771 r246571 2 2 import Builder from '../Builder.js'; 3 3 4 const wasmModuleWhichImportJS= () => {4 const oneTable = () => { 5 5 const builder = (new Builder()) 6 6 .Type().End() … … 32 32 }; 33 33 34 const multiTable = () => { 35 const builder = (new Builder()) 36 .Type().End() 37 .Import() 38 .Function("imp", "func", { params: ["i32"] }) 39 .Table("imp", "table0", { initial: 0, maximum: 0, element: "anyfunc"}) 40 .Table("imp", "table", { initial: 1, maximum: 1, element: "anyfunc"}) 41 .End() 42 .Function().End() 43 .Export() 44 .Function("changeCounter") 45 .Function("callFunc") 46 .End() 47 .Code() 48 .Function("changeCounter", { params: ["i32", "i32"] }) 49 .I32Const(42) 50 .GetLocal(0) 51 .I32Add() 52 .GetLocal(1) 53 .CallIndirect(0, 1) // Calls table[0](param[0] + 42). 54 .End() 55 .Function("callFunc", { params: ["i32"] }) 56 .GetLocal(0) 57 .Call(0) // Calls func(param[0] + 42) 58 .End() 59 .End(); 60 const bin = builder.WebAssembly().get(); 61 const module = new WebAssembly.Module(bin); 62 return module; 63 }; 64 65 for (const wasmModuleWhichImportJS of [oneTable, multiTable]) { 66 34 67 const makeTable = () => { 35 68 return new WebAssembly.Table({initial: 1, maximum: 1, element: "anyfunc"}); … … 41 74 const table = makeTable(); 42 75 const module = wasmModuleWhichImportJS(); 43 const instance = new WebAssembly.Instance(module, { imp: { func: counterSetter, table } });76 const instance = new WebAssembly.Instance(module, { imp: { func: counterSetter, table, table0: new WebAssembly.Table({initial: 0, maximum: 0, element: "anyfunc"}) } }); 44 77 table.set(0, instance.exports.callFunc); 45 78 for (let i = 0; i < 4096; ++i) { … … 58 91 59 92 const tableA = makeTable(); 60 const instanceA = new WebAssembly.Instance(module, { imp: { func: counterASetter, table: tableA } });93 const instanceA = new WebAssembly.Instance(module, { imp: { func: counterASetter, table: tableA, table0: new WebAssembly.Table({initial: 0, maximum: 0, element: "anyfunc"}) } }); 61 94 tableA.set(0, instanceA.exports.callFunc); 62 95 63 96 const tableB = makeTable(); 64 const instanceB = new WebAssembly.Instance(module, { imp: { func: counterBSetter, table: tableB } });97 const instanceB = new WebAssembly.Instance(module, { imp: { func: counterBSetter, table: tableB, table0: new WebAssembly.Table({initial: 0, maximum: 0, element: "anyfunc"}) } }); 65 98 tableB.set(0, instanceB.exports.callFunc); 66 99 for (let i = 0; i < 2048; ++i) { … … 94 127 for (let i = 0; i < num; ++i) { 95 128 let table = makeTable(); 96 instances[i] = new WebAssembly.Instance(module, { imp: { func: counterSetters[i], table } });129 instances[i] = new WebAssembly.Instance(module, { imp: { func: counterSetters[i], table, table0: new WebAssembly.Table({initial: 0, maximum: 0, element: "anyfunc"}) } }); 97 130 table.set(0, instances[i].exports.callFunc); 98 131 } … … 105 138 } 106 139 })(); 140 141 } -
trunk/JSTests/wasm/js-api/table.js
r246139 r246571 14 14 .Code() 15 15 .End(); 16 assert.throws(() => new WebAssembly.Module(builder.WebAssembly().get()), WebAssembly.CompileError, "WebAssembly.Module doesn't parse at byte 34: Cannot have more than one Table for now");16 new WebAssembly.Module(builder.WebAssembly().get()) 17 17 } 18 18 … … 39 39 .Code() 40 40 .End(); 41 assert.throws(() => new WebAssembly.Module(builder.WebAssembly().get()), WebAssembly.CompileError, "WebAssembly.Module doesn't parse at byte 17: Table count of 2 is invalid, at most 1 is allowed for now (evaluating 'new WebAssembly.Module(builder.WebAssembly().get())')");41 new WebAssembly.Module(builder.WebAssembly().get()) 42 42 } 43 43 … … 74 74 .End() 75 75 .End(); 76 assert.throws(() => new WebAssembly.Module(builder.WebAssembly().get()), WebAssembly.CompileError, "WebAssembly.Module doesn't parse at byte 6: call_indirect's 'reserved' varuint1 must be 0x0, in function at index 0 (evaluating 'new WebAssembly.Module(builder.WebAssembly().get())')"); 76 assert.throws(() => new WebAssembly.Module(builder.WebAssembly().get()), WebAssembly.CompileError, "WebAssembly.Module doesn't parse at byte 6: call_indirect's table index 1 invalid, limit is 1, in function at index 0 (evaluating 'new WebAssembly.Module(builder.WebAssembly().get())')"); 77 } 78 79 { 80 const builder = new Builder() 81 .Type().End() 82 .Function().End() 83 .Table() 84 .Table({initial:20, element:"anyfunc"}) 85 .Table({initial:20, element:"anyfunc"}) 86 .End() 87 .Export() 88 .Function("foo") 89 .End() 90 .Code() 91 .Function("foo", {params: ["i32"]}) 92 .GetLocal(0) 93 .GetLocal(0) 94 .CallIndirect(0, 1) 95 .End() 96 .End(); 97 new WebAssembly.Module(builder.WebAssembly().get()) 77 98 } 78 99 … … 187 208 .Code() 188 209 .End(); 189 assert.throws(() => new WebAssembly.Module(builder.WebAssembly().get()), WebAssembly.CompileError, "WebAssembly.Module doesn't parse at byte 39: Cannot have more than one Table for now");210 new WebAssembly.Module(builder.WebAssembly().get()) 190 211 } 191 212 … … 321 342 assert.truthy(instance.exports.table instanceof WebAssembly.Table); 322 343 } 344 345 { 346 const builder = new Builder() 347 .Type().End() 348 .Function().End() 349 .Table() 350 .Table({initial: 0, maximum: 1, element: "anyfunc"}) 351 .Table({initial: 20, maximum: 30, element: "anyfunc"}) 352 .End() 353 .Export() 354 .Table("table0", 0) 355 .Table("table", 1) 356 .Table("table2", 1) 357 .End() 358 .Code().End(); 359 360 const module = new WebAssembly.Module(builder.WebAssembly().get()); 361 const instance = new WebAssembly.Instance(module); 362 assert.eq(instance.exports.table, instance.exports.table2); 363 assert.eq(instance.exports.table.length, 20); 364 assert.eq(instance.exports.table0.length, 0); 365 assert.truthy(instance.exports.table instanceof WebAssembly.Table); 366 } -
trunk/JSTests/wasm/references/anyref_table.js
r246516 r246571 19 19 .I32Const(0) 20 20 .GetLocal(0) 21 .TableSet( )21 .TableSet(0) 22 22 .End() 23 23 24 24 .Function("get_tbl", { params: [], ret: "anyref" }) 25 25 .I32Const(0) 26 .TableGet( )26 .TableGet(0) 27 27 .End() 28 28 -
trunk/JSTests/wasm/references/anyref_table_import.js
r246139 r246571 23 23 .I32Const(0) 24 24 .GetLocal(0) 25 .TableSet( )25 .TableSet(0) 26 26 .End() 27 27 28 28 .Function("get_tbl", { params: [], ret: "anyref" }) 29 29 .I32Const(0) 30 .TableGet( )30 .TableGet(0) 31 31 .End() 32 32 … … 89 89 .I32Const(0) 90 90 .GetLocal(0) 91 .TableSet( )91 .TableSet(0) 92 92 .End() 93 93 94 94 .Function("get_tbl", { params: [], ret: "anyref" }) 95 95 .I32Const(0) 96 .TableGet( )96 .TableGet(0) 97 97 .End() 98 98 … … 128 128 .I32Const(0) 129 129 .GetLocal(0) 130 .TableSet( )130 .TableSet(0) 131 131 .End() 132 132 133 133 .Function("get_tbl", { params: [], ret: "anyref" }) 134 134 .I32Const(0) 135 .TableGet( )135 .TableGet(0) 136 136 .End() 137 137 -
trunk/JSTests/wasm/references/func_ref.js
r246504 r246571 258 258 .GetLocal(0) 259 259 .I32Const(0) 260 .TableSet( )260 .TableSet(0) 261 261 .End() 262 262 .End().WebAssembly().get()), Error, "WebAssembly.Module doesn't validate: table.set value to type I32 expected Anyfunc, in function at index 0 (evaluating 'new WebAssembly.Module')"); … … 268 268 .Function().End() 269 269 .Table() 270 .Table({initial: 0, element: "anyref"}) 270 271 .Table({initial: 1, element: "anyfunc"}) 271 272 .End() … … 292 293 .I32Const(0) 293 294 .GetGlobal(0) 294 .TableSet( )295 .TableSet(1) 295 296 296 297 .GetLocal(0) 297 298 .I32Const(0) 298 .CallIndirect(2, 0)299 .CallIndirect(2,1) 299 300 .End() 300 301 … … 329 330 .Function().End() 330 331 .Table() 332 .Table({initial: 0, element: "anyref"}) 331 333 .Table({initial: 1, element: "anyfunc"}) 332 334 .End() … … 339 341 .I32Const(0) 340 342 .GetLocal(0) 341 .TableSet( )343 .TableSet(1) 342 344 .End() 343 345 344 346 .Function("get", { params: [], ret: "anyfunc" }) 345 347 .I32Const(0) 346 .TableGet( )348 .TableGet(1) 347 349 .End() 348 350 .End().WebAssembly().get())); … … 406 408 .I32Const(0) 407 409 .RefFunc(0) 408 .TableSet( )410 .TableSet(0) 409 411 .I32Const(0) 410 412 .CallIndirect(0, 0) … … 415 417 .I32Const(0) 416 418 .RefFunc(0) 417 .TableSet( )419 .TableSet(0) 418 420 .I32Const(0) 419 421 .CallIndirect(0, 0) -
trunk/JSTests/wasm/references/validation.js
r246504 r246571 25 25 const builder = (new Builder()) 26 26 .Type().End() 27 .Import() 28 .Table("imp", "tbl", {initial: 2, element: "anyfunc"}) 29 .End() 27 30 .Function().End() 28 31 .Export() … … 33 36 .I32Const(0) 34 37 .I32Const(0) 35 .TableSet( )38 .TableSet(0) 36 39 .End() 37 40 .End(); … … 40 43 bin.trim(); 41 44 42 assert.throws(() => new WebAssembly.Module(bin.get()), WebAssembly.CompileError, "WebAssembly.Module doesn't validate: table.set value to type I32 expected Any ref, in function at index 0 (evaluating 'new WebAssembly.Module(bin.get())')");45 assert.throws(() => new WebAssembly.Module(bin.get()), WebAssembly.CompileError, "WebAssembly.Module doesn't validate: table.set value to type I32 expected Anyfunc, in function at index 0 (evaluating 'new WebAssembly.Module(bin.get())')"); 43 46 } 44 47 … … 57 60 .I32Const(0) 58 61 .GetLocal(0) 59 .TableSet( )62 .TableSet(0) 60 63 .End() 61 64 .End(); … … 80 83 .Function("j", { params: [], ret: "anyref" }) 81 84 .I32Const(0) 82 .TableGet( )85 .TableGet(0) 83 86 .End() 84 87 .End(); -
trunk/JSTests/wasm/spec-tests/imports.wast.js
r218216 r246571 189 189 assert_trap(() => call($14, "call", [100])); 190 190 191 // imports.wast:293192 assert_invalid("\x00\x61\x73\x6d\x01\x00\x00\x00\x02\x8d\x80\x80\x80\x00\x02\x00\x00\x01\x70\x00\x0a\x00\x00\x01\x70\x00\x0a");193 194 // imports.wast:297195 assert_invalid("\x00\x61\x73\x6d\x01\x00\x00\x00\x02\x87\x80\x80\x80\x00\x01\x00\x00\x01\x70\x00\x0a\x04\x84\x80\x80\x80\x00\x01\x70\x00\x0a");196 197 // imports.wast:301198 assert_invalid("\x00\x61\x73\x6d\x01\x00\x00\x00\x04\x87\x80\x80\x80\x00\x02\x70\x00\x0a\x70\x00\x0a");199 200 191 // imports.wast:306 201 192 let $15 = instance("\x00\x61\x73\x6d\x01\x00\x00\x00\x02\x97\x80\x80\x80\x00\x01\x04\x74\x65\x73\x74\x0c\x74\x61\x62\x6c\x65\x2d\x31\x30\x2d\x69\x6e\x66\x01\x70\x00\x0a"); -
trunk/JSTests/wasm/wasm.json
r246504 r246571 68 68 "get_global": { "category": "special", "value": 35, "return": ["any"], "parameter": [], "immediate": [{"name": "global_index", "type": "varuint32"}], "description": "read a global variable" }, 69 69 "set_global": { "category": "special", "value": 36, "return": [], "parameter": ["any"], "immediate": [{"name": "global_index", "type": "varuint32"}], "description": "write a global variable" }, 70 "table.get": { "category": "special", "value": 37, "return": ["anyref"], "parameter": ["i32"], "immediate": [ ],"description": "get a table value" },71 "table.set": { "category": "special", "value": 38, "return": [], "parameter": ["i32", "anyref"], "immediate": [ ],"description": "set a table value" },70 "table.get": { "category": "special", "value": 37, "return": ["anyref"], "parameter": ["i32"], "immediate": [{"name": "table_index", "type": "varuint32"}], "description": "get a table value" }, 71 "table.set": { "category": "special", "value": 38, "return": [], "parameter": ["i32", "anyref"], "immediate": [{"name": "table_index", "type": "varuint32"}], "description": "set a table value" }, 72 72 "call": { "category": "call", "value": 16, "return": ["call"], "parameter": ["call"], "immediate": [{"name": "function_index", "type": "varuint32"}], "description": "call a function by its index" }, 73 "call_indirect": { "category": "call", "value": 17, "return": ["call"], "parameter": ["call"], "immediate": [{"name": "type_index", "type": "varuint32"}, {"name": " reserved", "type": "varuint1"}],"description": "call a function indirect with an expected signature" },73 "call_indirect": { "category": "call", "value": 17, "return": ["call"], "parameter": ["call"], "immediate": [{"name": "type_index", "type": "varuint32"}, {"name": "table_index","type": "varuint32"}],"description": "call a function indirect with an expected signature" }, 74 74 "i32.load8_s": { "category": "memory", "value": 44, "return": ["i32"], "parameter": ["addr"], "immediate": [{"name": "flags", "type": "varuint32"}, {"name": "offset", "type": "varuint32"}], "description": "load from memory" }, 75 75 "i32.load8_u": { "category": "memory", "value": 45, "return": ["i32"], "parameter": ["addr"], "immediate": [{"name": "flags", "type": "varuint32"}, {"name": "offset", "type": "varuint32"}], "description": "load from memory" }, -
trunk/Source/JavaScriptCore/ChangeLog
r246567 r246571 1 2019-06-18 Justin Michaud <justin_michaud@apple.com> 2 3 [WASM-References] Add support for multiple tables 4 https://bugs.webkit.org/show_bug.cgi?id=198760 5 6 Reviewed by Saam Barati. 7 8 Support multiple wasm tables. We turn tableInformation into a tables array, and update all of the 9 existing users to give a table index. The array of Tables in Wasm::Instance is hung off the tail 10 to make it easier to use from jit code. 11 12 * wasm/WasmAirIRGenerator.cpp: 13 (JSC::Wasm::AirIRGenerator::AirIRGenerator): 14 (JSC::Wasm::AirIRGenerator::addTableGet): 15 (JSC::Wasm::AirIRGenerator::addTableSet): 16 (JSC::Wasm::AirIRGenerator::addCallIndirect): 17 * wasm/WasmB3IRGenerator.cpp: 18 (JSC::Wasm::B3IRGenerator::B3IRGenerator): 19 (JSC::Wasm::B3IRGenerator::addTableGet): 20 (JSC::Wasm::B3IRGenerator::addTableSet): 21 (JSC::Wasm::B3IRGenerator::addCallIndirect): 22 * wasm/WasmExceptionType.h: 23 * wasm/WasmFormat.h: 24 (JSC::Wasm::Element::Element): 25 * wasm/WasmFunctionParser.h: 26 (JSC::Wasm::FunctionParser<Context>::parseExpression): 27 (JSC::Wasm::FunctionParser<Context>::parseUnreachableExpression): 28 * wasm/WasmInstance.cpp: 29 (JSC::Wasm::Instance::Instance): 30 (JSC::Wasm::Instance::create): 31 (JSC::Wasm::Instance::extraMemoryAllocated const): 32 (JSC::Wasm::Instance::table): 33 (JSC::Wasm::Instance::setTable): 34 * wasm/WasmInstance.h: 35 (JSC::Wasm::Instance::updateCachedMemory): 36 (JSC::Wasm::Instance::offsetOfGlobals): 37 (JSC::Wasm::Instance::offsetOfTablePtr): 38 (JSC::Wasm::Instance::allocationSize): 39 (JSC::Wasm::Instance::table): Deleted. 40 (JSC::Wasm::Instance::setTable): Deleted. 41 (JSC::Wasm::Instance::offsetOfTable): Deleted. 42 * wasm/WasmModuleInformation.h: 43 (JSC::Wasm::ModuleInformation::tableCount const): 44 * wasm/WasmSectionParser.cpp: 45 (JSC::Wasm::SectionParser::parseImport): 46 (JSC::Wasm::SectionParser::parseTableHelper): 47 (JSC::Wasm::SectionParser::parseTable): 48 (JSC::Wasm::SectionParser::parseElement): 49 * wasm/WasmTable.h: 50 (JSC::Wasm::Table::owner const): 51 * wasm/WasmValidate.cpp: 52 (JSC::Wasm::Validate::addTableGet): 53 (JSC::Wasm::Validate::addTableSet): 54 (JSC::Wasm::Validate::addCallIndirect): 55 * wasm/js/JSWebAssemblyInstance.cpp: 56 (JSC::JSWebAssemblyInstance::JSWebAssemblyInstance): 57 (JSC::JSWebAssemblyInstance::visitChildren): 58 * wasm/js/JSWebAssemblyInstance.h: 59 * wasm/js/WebAssemblyModuleRecord.cpp: 60 (JSC::WebAssemblyModuleRecord::link): 61 (JSC::WebAssemblyModuleRecord::evaluate): 62 * wasm/wasm.json: 63 1 64 2019-06-18 Alexey Shvayka <shvaikalesh@gmail.com> 2 65 -
trunk/Source/JavaScriptCore/wasm/WasmAirIRGenerator.cpp
r246504 r246571 238 238 239 239 // Tables 240 PartialResult WARN_UNUSED_RETURN addTableGet( ExpressionType& index, ExpressionType& result);241 PartialResult WARN_UNUSED_RETURN addTableSet( ExpressionType& index, ExpressionType& value);240 PartialResult WARN_UNUSED_RETURN addTableGet(unsigned, ExpressionType& index, ExpressionType& result); 241 PartialResult WARN_UNUSED_RETURN addTableSet(unsigned, ExpressionType& index, ExpressionType& value); 242 242 243 243 // Locals … … 278 278 // Calls 279 279 PartialResult WARN_UNUSED_RETURN addCall(uint32_t calleeIndex, const Signature&, Vector<ExpressionType>& args, ExpressionType& result); 280 PartialResult WARN_UNUSED_RETURN addCallIndirect( const Signature&, Vector<ExpressionType>& args, ExpressionType& result);280 PartialResult WARN_UNUSED_RETURN addCallIndirect(unsigned tableIndex, const Signature&, Vector<ExpressionType>& args, ExpressionType& result); 281 281 PartialResult WARN_UNUSED_RETURN addUnreachable(); 282 282 … … 627 627 628 628 uint32_t m_maxNumJSCallArguments { 0 }; 629 unsigned m_numImportFunctions; 629 630 630 631 B3::PatchpointSpecial* m_patchpointSpecial { nullptr }; … … 682 683 , m_code(m_proc.code()) 683 684 , m_unlinkedWasmToWasmCalls(unlinkedWasmToWasmCalls) 685 , m_numImportFunctions(info.importFunctionCount()) 684 686 { 685 687 m_currentBlock = m_code.addBlock(); … … 969 971 } 970 972 971 auto AirIRGenerator::addTableGet( ExpressionType& index, ExpressionType& result) -> PartialResult973 auto AirIRGenerator::addTableGet(unsigned tableIndex, ExpressionType& index, ExpressionType& result) -> PartialResult 972 974 { 973 975 // FIXME: Emit this inline <https://bugs.webkit.org/show_bug.cgi?id=198506>. … … 976 978 result = tmpForType(Type::Anyref); 977 979 978 emitCCall(&getWasmTableElement, result, instanceValue(), index);980 emitCCall(&getWasmTableElement, result, instanceValue(), addConstant(Type::I32, tableIndex), index); 979 981 emitCheck([&] { 980 982 return Inst(BranchTest32, nullptr, Arg::resCond(MacroAssembler::Zero), result, result); … … 986 988 } 987 989 988 auto AirIRGenerator::addTableSet( ExpressionType& index, ExpressionType& value) -> PartialResult990 auto AirIRGenerator::addTableSet(unsigned tableIndex, ExpressionType& index, ExpressionType& value) -> PartialResult 989 991 { 990 992 // FIXME: Emit this inline <https://bugs.webkit.org/show_bug.cgi?id=198506>. … … 994 996 995 997 auto shouldThrow = g32(); 996 emitCCall(&setWasmTableElement, shouldThrow, instanceValue(), index, value);998 emitCCall(&setWasmTableElement, shouldThrow, instanceValue(), addConstant(Type::I32, tableIndex), index, value); 997 999 998 1000 emitCheck([&] { … … 1894 1896 } 1895 1897 1896 auto AirIRGenerator::addCallIndirect( const Signature& signature, Vector<ExpressionType>& args, ExpressionType& result) -> PartialResult1898 auto AirIRGenerator::addCallIndirect(unsigned tableIndex, const Signature& signature, Vector<ExpressionType>& args, ExpressionType& result) -> PartialResult 1897 1899 { 1898 1900 ExpressionType calleeIndex = args.takeLast(); 1899 1901 ASSERT(signature.argumentCount() == args.size()); 1900 ASSERT(m_info.tableInformation.type() == TableElementType::Funcref); 1902 ASSERT(m_info.tableCount() > tableIndex); 1903 ASSERT(m_info.tables[tableIndex].type() == TableElementType::Funcref); 1901 1904 1902 1905 m_makesCalls = true; … … 1913 1916 ExpressionType callableFunctionBufferLength = g64(); 1914 1917 { 1915 RELEASE_ASSERT(Arg::isValidAddrForm(Instance::offsetOfTable(), B3::Width64));1916 1918 RELEASE_ASSERT(Arg::isValidAddrForm(FuncRefTable::offsetOfFunctions(), B3::Width64)); 1917 1919 RELEASE_ASSERT(Arg::isValidAddrForm(FuncRefTable::offsetOfInstances(), B3::Width64)); 1918 1920 RELEASE_ASSERT(Arg::isValidAddrForm(FuncRefTable::offsetOfLength(), B3::Width64)); 1919 1921 1920 append(Move, Arg::addr(instanceValue(), Instance::offsetOfTable()), callableFunctionBufferLength); 1922 if (UNLIKELY(!Arg::isValidAddrForm(Instance::offsetOfTablePtr(m_numImportFunctions, tableIndex), B3::Width64))) { 1923 append(Move, Arg::bigImm(Instance::offsetOfTablePtr(m_numImportFunctions, tableIndex)), callableFunctionBufferLength); 1924 append(Add64, instanceValue(), callableFunctionBufferLength); 1925 append(Move, Arg::addr(callableFunctionBufferLength), callableFunctionBufferLength); 1926 } else 1927 append(Move, Arg::addr(instanceValue(), Instance::offsetOfTablePtr(m_numImportFunctions, tableIndex)), callableFunctionBufferLength); 1921 1928 append(Move, Arg::addr(callableFunctionBufferLength, FuncRefTable::offsetOfFunctions()), callableFunctionBuffer); 1922 1929 append(Move, Arg::addr(callableFunctionBufferLength, FuncRefTable::offsetOfInstances()), instancesBuffer); -
trunk/Source/JavaScriptCore/wasm/WasmB3IRGenerator.cpp
r246504 r246571 191 191 192 192 // Tables 193 PartialResult WARN_UNUSED_RETURN addTableGet( ExpressionType& index, ExpressionType& result);194 PartialResult WARN_UNUSED_RETURN addTableSet( ExpressionType& index, ExpressionType& value);193 PartialResult WARN_UNUSED_RETURN addTableGet(unsigned, ExpressionType& index, ExpressionType& result); 194 PartialResult WARN_UNUSED_RETURN addTableSet(unsigned, ExpressionType& index, ExpressionType& value); 195 195 196 196 // Locals … … 231 231 // Calls 232 232 PartialResult WARN_UNUSED_RETURN addCall(uint32_t calleeIndex, const Signature&, Vector<ExpressionType>& args, ExpressionType& result); 233 PartialResult WARN_UNUSED_RETURN addCallIndirect( const Signature&, Vector<ExpressionType>& args, ExpressionType& result);233 PartialResult WARN_UNUSED_RETURN addCallIndirect(unsigned tableIndex, const Signature&, Vector<ExpressionType>& args, ExpressionType& result); 234 234 PartialResult WARN_UNUSED_RETURN addUnreachable(); 235 235 … … 293 293 294 294 uint32_t m_maxNumJSCallArguments { 0 }; 295 unsigned m_numImportFunctions; 295 296 }; 296 297 … … 344 345 , m_unlinkedWasmToWasmCalls(unlinkedWasmToWasmCalls) 345 346 , m_constantInsertionValues(m_proc) 347 , m_numImportFunctions(info.importFunctionCount()) 346 348 { 347 349 m_currentBlock = m_proc.addBlock(); … … 567 569 } 568 570 569 auto B3IRGenerator::addTableGet( ExpressionType& index, ExpressionType& result) -> PartialResult571 auto B3IRGenerator::addTableGet(unsigned tableIndex, ExpressionType& index, ExpressionType& result) -> PartialResult 570 572 { 571 573 // FIXME: Emit this inline <https://bugs.webkit.org/show_bug.cgi?id=198506>. 572 574 result = m_currentBlock->appendNew<CCallValue>(m_proc, toB3Type(Anyref), origin(), 573 575 m_currentBlock->appendNew<ConstPtrValue>(m_proc, origin(), tagCFunctionPtr<void*>(&getWasmTableElement, B3CCallPtrTag)), 574 instanceValue(), index);576 instanceValue(), m_currentBlock->appendNew<Const32Value>(m_proc, origin(), tableIndex), index); 575 577 576 578 { … … 586 588 } 587 589 588 auto B3IRGenerator::addTableSet( ExpressionType& index, ExpressionType& value) -> PartialResult590 auto B3IRGenerator::addTableSet(unsigned tableIndex, ExpressionType& index, ExpressionType& value) -> PartialResult 589 591 { 590 592 // FIXME: Emit this inline <https://bugs.webkit.org/show_bug.cgi?id=198506>. 591 593 auto shouldThrow = m_currentBlock->appendNew<CCallValue>(m_proc, B3::Int32, origin(), 592 594 m_currentBlock->appendNew<ConstPtrValue>(m_proc, origin(), tagCFunctionPtr<void*>(&setWasmTableElement, B3CCallPtrTag)), 593 instanceValue(), index, value);595 instanceValue(), m_currentBlock->appendNew<Const32Value>(m_proc, origin(), tableIndex), index, value); 594 596 595 597 { … … 1299 1301 } 1300 1302 1301 auto B3IRGenerator::addCallIndirect( const Signature& signature, Vector<ExpressionType>& args, ExpressionType& result) -> PartialResult1303 auto B3IRGenerator::addCallIndirect(unsigned tableIndex, const Signature& signature, Vector<ExpressionType>& args, ExpressionType& result) -> PartialResult 1302 1304 { 1303 1305 ExpressionType calleeIndex = args.takeLast(); … … 1316 1318 { 1317 1319 ExpressionType table = m_currentBlock->appendNew<MemoryValue>(m_proc, Load, pointerType(), origin(), 1318 instanceValue(), safeCast<int32_t>(Instance::offsetOfTable ()));1320 instanceValue(), safeCast<int32_t>(Instance::offsetOfTablePtr(m_numImportFunctions, tableIndex))); 1319 1321 callableFunctionBuffer = m_currentBlock->appendNew<MemoryValue>(m_proc, Load, pointerType(), origin(), 1320 1322 table, safeCast<int32_t>(FuncRefTable::offsetOfFunctions())); -
trunk/Source/JavaScriptCore/wasm/WasmFormat.h
r246504 r246571 214 214 215 215 struct Element { 216 Element(I32InitExpr offset) 217 : offset(offset) 216 Element(uint32_t tableIndex, I32InitExpr offset) 217 : tableIndex(tableIndex) 218 , offset(offset) 218 219 { } 219 220 221 uint32_t tableIndex; 220 222 I32InitExpr offset; 221 223 Vector<uint32_t> functionIndices; -
trunk/Source/JavaScriptCore/wasm/WasmFunctionParser.h
r246504 r246571 284 284 case TableGet: { 285 285 WASM_PARSER_FAIL_IF(!Options::useWebAssemblyReferences(), "references are not enabled"); 286 unsigned tableIndex; 287 WASM_PARSER_FAIL_IF(!parseVarUInt32(tableIndex), "can't parse table index"); 286 288 ExpressionType result, index; 287 289 WASM_TRY_POP_EXPRESSION_STACK_INTO(index, "table.get"); 288 WASM_TRY_ADD_TO_CONTEXT(addTableGet( index, result));290 WASM_TRY_ADD_TO_CONTEXT(addTableGet(tableIndex, index, result)); 289 291 m_expressionStack.append(result); 290 292 return { }; … … 293 295 case TableSet: { 294 296 WASM_PARSER_FAIL_IF(!Options::useWebAssemblyReferences(), "references are not enabled"); 297 unsigned tableIndex; 298 WASM_PARSER_FAIL_IF(!parseVarUInt32(tableIndex), "can't parse table index"); 295 299 ExpressionType val, index; 296 300 WASM_TRY_POP_EXPRESSION_STACK_INTO(val, "table.set"); 297 301 WASM_TRY_POP_EXPRESSION_STACK_INTO(index, "table.set"); 298 WASM_TRY_ADD_TO_CONTEXT(addTableSet( index, val));302 WASM_TRY_ADD_TO_CONTEXT(addTableSet(tableIndex, index, val)); 299 303 return { }; 300 304 } … … 397 401 case CallIndirect: { 398 402 uint32_t signatureIndex; 399 uint 8_t reserved;400 WASM_PARSER_FAIL_IF(!m_info.table Information, "call_indirect is only valid when a table is defined or imported");403 uint32_t tableIndex; 404 WASM_PARSER_FAIL_IF(!m_info.tableCount(), "call_indirect is only valid when a table is defined or imported"); 401 405 WASM_PARSER_FAIL_IF(!parseVarUInt32(signatureIndex), "can't get call_indirect's signature index"); 402 WASM_PARSER_FAIL_IF(!parseVarUInt 1(reserved), "can't get call_indirect's reserved byte");403 WASM_PARSER_FAIL_IF( reserved, "call_indirect's 'reserved' varuint1 must be 0x0");406 WASM_PARSER_FAIL_IF(!parseVarUInt32(tableIndex), "can't get call_indirect's table index"); 407 WASM_PARSER_FAIL_IF(tableIndex >= m_info.tableCount(), "call_indirect's table index ", tableIndex, " invalid, limit is ", m_info.tableCount()); 404 408 WASM_PARSER_FAIL_IF(m_info.usedSignatures.size() <= signatureIndex, "call_indirect's signature index ", signatureIndex, " exceeds known signatures ", m_info.usedSignatures.size()); 405 WASM_PARSER_FAIL_IF(m_info.table Information.type() != TableElementType::Funcref, "call_indirect is only valid when a table has type anyfunc");409 WASM_PARSER_FAIL_IF(m_info.tables[tableIndex].type() != TableElementType::Funcref, "call_indirect is only valid when a table has type anyfunc"); 406 410 407 411 const Signature& calleeSignature = m_info.usedSignatures[signatureIndex].get(); … … 417 421 418 422 ExpressionType result = Context::emptyExpression(); 419 WASM_TRY_ADD_TO_CONTEXT(addCallIndirect( calleeSignature, args, result));423 WASM_TRY_ADD_TO_CONTEXT(addCallIndirect(tableIndex, calleeSignature, args, result)); 420 424 421 425 if (result != Context::emptyExpression()) … … 632 636 case CallIndirect: { 633 637 uint32_t unused; 634 uint 8_t unused2;638 uint32_t unused2; 635 639 WASM_PARSER_FAIL_IF(!parseVarUInt32(unused), "can't get call_indirect's signature index in unreachable context"); 636 WASM_PARSER_FAIL_IF(!parseVarUInt 1(unused2), "can't get call_indirect's reserved byte in unreachable context");640 WASM_PARSER_FAIL_IF(!parseVarUInt32(unused2), "can't get call_indirect's reserved byte in unreachable context"); 637 641 return { }; 638 642 } … … 686 690 687 691 case TableGet: 688 case TableSet: 692 case TableSet: { 693 unsigned tableIndex; 694 WASM_PARSER_FAIL_IF(!parseVarUInt32(tableIndex), "can't parse table index"); 695 FALLTHROUGH; 696 } 689 697 case RefIsNull: 690 698 case RefNull: { -
trunk/Source/JavaScriptCore/wasm/WasmInstance.cpp
r246504 r246571 62 62 m_globalsToMark.set(i); 63 63 } 64 memset(bitwise_cast<char*>(this) + offsetOfTablePtr(m_numImportFunctions, 0), 0, m_module->moduleInformation().tableCount() * sizeof(Table*)); 64 65 } 65 66 66 67 Ref<Instance> Instance::create(Context* context, Ref<Module>&& module, EntryFrame** pointerToTopEntryFrame, void** pointerToActualStackLimit, StoreTopCallFrameCallback&& storeTopCallFrame) 67 68 { 68 return adoptRef(*new (NotNull, fastMalloc(allocationSize(module->moduleInformation().importFunctionCount() ))) Instance(context, WTFMove(module), pointerToTopEntryFrame, pointerToActualStackLimit, WTFMove(storeTopCallFrame)));69 return adoptRef(*new (NotNull, fastMalloc(allocationSize(module->moduleInformation().importFunctionCount(), module->moduleInformation().tableCount()))) Instance(context, WTFMove(module), pointerToTopEntryFrame, pointerToActualStackLimit, WTFMove(storeTopCallFrame))); 69 70 } 70 71 … … 73 74 size_t Instance::extraMemoryAllocated() const 74 75 { 75 return globalMemoryByteSize(m_module.get()) + allocationSize(m_numImportFunctions );76 return globalMemoryByteSize(m_module.get()) + allocationSize(m_numImportFunctions, m_module->moduleInformation().tableCount()); 76 77 } 77 78 … … 100 101 } 101 102 102 EncodedJSValue getWasmTableElement(Instance* instance, int32_t signedIndex)103 Table* Instance::table(unsigned i) 103 104 { 105 RELEASE_ASSERT(i < m_module->moduleInformation().tableCount()); 106 return *bitwise_cast<Table**>(bitwise_cast<char*>(this) + offsetOfTablePtr(m_numImportFunctions, i)); 107 } 108 109 void Instance::setTable(unsigned i, Ref<Table>&& table) 110 { 111 RELEASE_ASSERT(i < m_module->moduleInformation().tableCount()); 112 ASSERT(!this->table(i)); 113 *bitwise_cast<Table**>(bitwise_cast<char*>(this) + offsetOfTablePtr(m_numImportFunctions, i)) = &table.leakRef(); 114 } 115 116 EncodedJSValue getWasmTableElement(Instance* instance, unsigned tableIndex, int32_t signedIndex) 117 { 118 ASSERT(tableIndex < instance->module().moduleInformation().tableCount()); 104 119 if (signedIndex < 0) 105 120 return 0; 106 121 107 122 uint32_t index = signedIndex; 108 if (index >= instance->table( )->length())123 if (index >= instance->table(tableIndex)->length()) 109 124 return 0; 110 125 111 return JSValue::encode(instance->table( )->get(index));126 return JSValue::encode(instance->table(tableIndex)->get(index)); 112 127 } 113 128 114 bool setWasmTableElement(Instance* instance, int32_t signedIndex, EncodedJSValue encValue)129 bool setWasmTableElement(Instance* instance, unsigned tableIndex, int32_t signedIndex, EncodedJSValue encValue) 115 130 { 131 ASSERT(tableIndex < instance->module().moduleInformation().tableCount()); 116 132 if (signedIndex < 0) 117 133 return false; 118 134 119 135 uint32_t index = signedIndex; 120 if (index >= instance->table( )->length())136 if (index >= instance->table(tableIndex)->length()) 121 137 return false; 122 138 123 139 JSValue value = JSValue::decode(encValue); 124 if (instance->table( )->type() == Wasm::TableElementType::Anyref)125 instance->table( )->set(index, value);126 else if (instance->table( )->type() == Wasm::TableElementType::Funcref) {140 if (instance->table(tableIndex)->type() == Wasm::TableElementType::Anyref) 141 instance->table(tableIndex)->set(index, value); 142 else if (instance->table(tableIndex)->type() == Wasm::TableElementType::Funcref) { 127 143 WebAssemblyFunction* wasmFunction; 128 144 WebAssemblyWrapperFunction* wasmWrapperFunction; … … 131 147 ASSERT(!!wasmFunction || !!wasmWrapperFunction); 132 148 if (wasmFunction) 133 instance->table( )->asFuncrefTable()->setFunction(index, jsCast<JSObject*>(value), wasmFunction->importableFunction(), &wasmFunction->instance()->instance());149 instance->table(tableIndex)->asFuncrefTable()->setFunction(index, jsCast<JSObject*>(value), wasmFunction->importableFunction(), &wasmFunction->instance()->instance()); 134 150 else 135 instance->table( )->asFuncrefTable()->setFunction(index, jsCast<JSObject*>(value), wasmWrapperFunction->importableFunction(), &wasmWrapperFunction->instance()->instance());151 instance->table(tableIndex)->asFuncrefTable()->setFunction(index, jsCast<JSObject*>(value), wasmWrapperFunction->importableFunction(), &wasmWrapperFunction->instance()->instance()); 136 152 } else if (value.isNull()) 137 instance->table( )->clear(index);153 instance->table(tableIndex)->clear(index); 138 154 else 139 155 ASSERT_NOT_REACHED(); -
trunk/Source/JavaScriptCore/wasm/WasmInstance.h
r246504 r246571 42 42 class Instance; 43 43 44 EncodedJSValue getWasmTableElement(Instance*, int32_t);45 bool setWasmTableElement(Instance*, int32_t, EncodedJSValue encValue);44 EncodedJSValue getWasmTableElement(Instance*, unsigned, int32_t); 45 bool setWasmTableElement(Instance*, unsigned, int32_t, EncodedJSValue encValue); 46 46 EncodedJSValue doWasmRefFunc(Instance*, uint32_t); 47 47 … … 71 71 CodeBlock* codeBlock() { return m_codeBlock.get(); } 72 72 Memory* memory() { return m_memory.get(); } 73 Table* table() { return m_table.get(); } 73 Table* table(unsigned); 74 void setTable(unsigned, Ref<Table>&&); 74 75 75 76 void* cachedMemory() const { return m_cachedMemory.getMayBeNull(cachedMemorySize()); } … … 89 90 } 90 91 } 91 void setTable(Ref<Table>&& table) { m_table = WTFMove(table); }92 92 93 93 int32_t loadI32Global(unsigned i) const { return m_globals.get()[i].primitive; } … … 104 104 static ptrdiff_t offsetOfMemory() { return OBJECT_OFFSETOF(Instance, m_memory); } 105 105 static ptrdiff_t offsetOfGlobals() { return OBJECT_OFFSETOF(Instance, m_globals); } 106 static ptrdiff_t offsetOfTable() { return OBJECT_OFFSETOF(Instance, m_table); }107 106 static ptrdiff_t offsetOfCachedMemory() { return OBJECT_OFFSETOF(Instance, m_cachedMemory); } 108 107 static ptrdiff_t offsetOfCachedMemorySize() { return OBJECT_OFFSETOF(Instance, m_cachedMemorySize); } … … 123 122 124 123 // Tail accessors. 125 static size_t offsetOfTail() { return WTF::roundUpToMultipleOf<sizeof(uint64_t)>(sizeof(Instance)); }124 static constexpr size_t offsetOfTail() { return WTF::roundUpToMultipleOf<sizeof(uint64_t)>(sizeof(Instance)); } 126 125 struct ImportFunctionInfo { 127 126 // Target instance and entrypoint are only set for wasm->wasm calls, and are otherwise nullptr. The embedder-specific logic occurs through import function. … … 143 142 template<typename T> T* importFunction(unsigned importFunctionNum) { return reinterpret_cast<T*>(&importFunctionInfo(importFunctionNum)->importFunction); } 144 143 144 static_assert(sizeof(ImportFunctionInfo) == WTF::roundUpToMultipleOf<sizeof(uint64_t)>(sizeof(ImportFunctionInfo)), "We rely on this for the alignment to be correct"); 145 static constexpr size_t offsetOfTablePtr(unsigned numImportFunctions, unsigned i) { return offsetOfTail() + sizeof(ImportFunctionInfo) * numImportFunctions + sizeof(Table*) * i; } 146 145 147 void storeTopCallFrame(void* callFrame) 146 148 { … … 151 153 Instance(Context*, Ref<Module>&&, EntryFrame**, void**, StoreTopCallFrameCallback&&); 152 154 153 static size_t allocationSize(Checked<size_t> numImportFunctions )155 static size_t allocationSize(Checked<size_t> numImportFunctions, Checked<size_t> numTables) 154 156 { 155 return (offsetOfTail() + sizeof(ImportFunctionInfo) * numImportFunctions ).unsafeGet();157 return (offsetOfTail() + sizeof(ImportFunctionInfo) * numImportFunctions + sizeof(Table*) * numTables).unsafeGet(); 156 158 } 157 159 void* m_owner { nullptr }; // In a JS embedding, this is a JSWebAssemblyInstance*. … … 162 164 RefPtr<CodeBlock> m_codeBlock; 163 165 RefPtr<Memory> m_memory; 164 RefPtr<Table> m_table;165 166 166 167 union GlobalValue { -
trunk/Source/JavaScriptCore/wasm/WasmLimits.h
r224122 r246571 52 52 53 53 constexpr size_t maxTableEntries = 10000000; 54 constexpr unsigned maxTables = 1000000; 54 55 55 56 } } // namespace JSC::Wasm -
trunk/Source/JavaScriptCore/wasm/WasmModuleInformation.h
r246504 r246571 66 66 // If we need to remove this limitation, we would have MemoryInformation and TableInformation in the Vectors. 67 67 uint32_t memoryCount() const { return memory ? 1 : 0; } 68 uint32_t tableCount() const { return table Information ? 1 : 0; }68 uint32_t tableCount() const { return tables.size(); } 69 69 70 70 const BitVector& referencedFunctions() const { return m_referencedFunctions; } … … 84 84 Vector<Segment::Ptr> data; 85 85 Vector<Element> elements; 86 TableInformation tableInformation;86 Vector<TableInformation> tables; 87 87 Vector<Global> globals; 88 88 unsigned firstInternalGlobal { 0 }; -
trunk/Source/JavaScriptCore/wasm/WasmSectionParser.cpp
r246516 r246571 120 120 case ExternalKind::Table: { 121 121 bool isImport = true; 122 kindIndex = m_info->tables.size(); 122 123 PartialResult result = parseTableHelper(isImport); 123 124 if (UNLIKELY(!result)) … … 194 195 auto SectionParser::parseTableHelper(bool isImport) -> PartialResult 195 196 { 196 WASM_PARSER_FAIL_IF(m_info->tableCount() > 0, "Cannot have more than one Table for now");197 WASM_PARSER_FAIL_IF(m_info->tableCount() >= maxTables, "Table count of ", m_info->tableCount(), " is too big, maximum ", maxTables); 197 198 198 199 int8_t type; … … 210 211 211 212 TableElementType tableType = type == Wasm::Anyfunc ? TableElementType::Funcref : TableElementType::Anyref; 212 m_info->table Information = TableInformation(initial, maximum, isImport, tableType);213 m_info->tables.append(TableInformation(initial, maximum, isImport, tableType)); 213 214 214 215 return { }; … … 219 220 uint32_t count; 220 221 WASM_PARSER_FAIL_IF(!parseVarUInt32(count), "can't get Table's count"); 221 WASM_PARSER_FAIL_IF(count > 1, "Table count of ", count, " is invalid, at most 1 is allowed for now"); 222 223 if (!count) 224 return { }; 225 226 bool isImport = false; 227 PartialResult result = parseTableHelper(isImport); 228 if (UNLIKELY(!result)) 229 return makeUnexpected(WTFMove(result.error())); 222 223 for (unsigned i = 0; i < count; ++i) { 224 bool isImport = false; 225 PartialResult result = parseTableHelper(isImport); 226 if (UNLIKELY(!result)) 227 return makeUnexpected(WTFMove(result.error())); 228 } 230 229 231 230 return { }; … … 380 379 WASM_PARSER_FAIL_IF(!parseVarUInt32(tableIndex), "can't get ", elementNum, "th Element table index"); 381 380 WASM_PARSER_FAIL_IF(tableIndex >= m_info->tableCount(), "Element section for Table ", tableIndex, " exceeds available Table ", m_info->tableCount()); 382 WASM_PARSER_FAIL_IF(m_info->table Information.type() != TableElementType::Funcref, "Table ", tableIndex, " must have type 'anyfunc' to have an element section");381 WASM_PARSER_FAIL_IF(m_info->tables[tableIndex].type() != TableElementType::Funcref, "Table ", tableIndex, " must have type 'anyfunc' to have an element section"); 383 382 Type initExprType; 384 383 WASM_FAIL_IF_HELPER_FAILS(parseInitExpr(initOpcode, initExprBits, initExprType)); … … 387 386 WASM_PARSER_FAIL_IF(indexCount == std::numeric_limits<uint32_t>::max(), "Element section's ", elementNum, "th index count is too big ", indexCount); 388 387 389 ASSERT(!!m_info->table Information);390 391 Element element( makeI32InitExpr(initOpcode, initExprBits));388 ASSERT(!!m_info->tables[tableIndex]); 389 390 Element element(tableIndex, makeI32InitExpr(initOpcode, initExprBits)); 392 391 WASM_PARSER_FAIL_IF(!element.functionIndices.tryReserveCapacity(indexCount), "can't allocate memory for ", indexCount, " Element indices"); 393 392 -
trunk/Source/JavaScriptCore/wasm/WasmTable.h
r246487 r246571 58 58 uint32_t mask() const { return m_mask; } 59 59 60 template<typename T> T* owner() const { return reinterpret_cast<T*>(m_owner); } 60 61 void setOwner(JSObject* owner) 61 62 { -
trunk/Source/JavaScriptCore/wasm/WasmValidate.cpp
r246504 r246571 107 107 108 108 // Tables 109 Result WARN_UNUSED_RETURN addTableGet( ExpressionType& index, ExpressionType& result);110 Result WARN_UNUSED_RETURN addTableSet( ExpressionType& index, ExpressionType& value);109 Result WARN_UNUSED_RETURN addTableGet(unsigned, ExpressionType& index, ExpressionType& result); 110 Result WARN_UNUSED_RETURN addTableSet(unsigned, ExpressionType& index, ExpressionType& value); 111 111 112 112 // Locals … … 149 149 // Calls 150 150 Result WARN_UNUSED_RETURN addCall(unsigned calleeIndex, const Signature&, const Vector<ExpressionType>& args, ExpressionType& result); 151 Result WARN_UNUSED_RETURN addCallIndirect( const Signature&, const Vector<ExpressionType>& args, ExpressionType& result);151 Result WARN_UNUSED_RETURN addCallIndirect(unsigned tableIndex, const Signature&, const Vector<ExpressionType>& args, ExpressionType& result); 152 152 153 153 ALWAYS_INLINE void didKill(ExpressionType) { } … … 179 179 } 180 180 181 auto Validate::addTableGet(ExpressionType& index, ExpressionType& result) -> Result 182 { 183 result = m_module.tableInformation.wasmType(); 181 auto Validate::addTableGet(unsigned tableIndex, ExpressionType& index, ExpressionType& result) -> Result 182 { 183 WASM_VALIDATOR_FAIL_IF(tableIndex >= m_module.tableCount(), "table index ", tableIndex, " is invalid, limit is ", m_module.tableCount()); 184 result = m_module.tables[tableIndex].wasmType(); 184 185 WASM_VALIDATOR_FAIL_IF(Type::I32 != index, "table.get index to type ", index, " expected ", Type::I32); 185 186 … … 187 188 } 188 189 189 auto Validate::addTableSet(ExpressionType& index, ExpressionType& value) -> Result 190 { 191 auto type = m_module.tableInformation.wasmType(); 190 auto Validate::addTableSet(unsigned tableIndex, ExpressionType& index, ExpressionType& value) -> Result 191 { 192 WASM_VALIDATOR_FAIL_IF(tableIndex >= m_module.tableCount(), "table index ", tableIndex, " is invalid, limit is ", m_module.tableCount()); 193 auto type = m_module.tables[tableIndex].wasmType(); 192 194 WASM_VALIDATOR_FAIL_IF(Type::I32 != index, "table.set index to type ", index, " expected ", Type::I32); 193 195 WASM_VALIDATOR_FAIL_IF(!isSubtype(value, type), "table.set value to type ", value, " expected ", type); 194 WASM_VALIDATOR_FAIL_IF(m_module.tableInformation.type() != TableElementType::Anyref 195 && m_module.tableInformation.type() != TableElementType::Funcref, "table.set expects the table to have type anyref or anyfunc"); 196 RELEASE_ASSERT(m_module.tables[tableIndex].type() == TableElementType::Anyref || m_module.tables[tableIndex].type() == TableElementType::Funcref); 196 197 197 198 return { }; … … 380 381 } 381 382 382 auto Validate::addCallIndirect(const Signature& signature, const Vector<ExpressionType>& args, ExpressionType& result) -> Result 383 { 384 WASM_VALIDATOR_FAIL_IF(m_module.tableInformation.type() != TableElementType::Funcref, "Table must have type Anyfunc to call"); 383 auto Validate::addCallIndirect(unsigned tableIndex, const Signature& signature, const Vector<ExpressionType>& args, ExpressionType& result) -> Result 384 { 385 RELEASE_ASSERT(tableIndex < m_module.tableCount()); 386 RELEASE_ASSERT(m_module.tables[tableIndex].type() == TableElementType::Funcref); 385 387 const auto argumentCount = signature.argumentCount(); 386 388 WASM_VALIDATOR_FAIL_IF(argumentCount != args.size() - 1, "arity mismatch in call_indirect, got ", args.size() - 1, " arguments, expected ", argumentCount); -
trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyInstance.cpp
r246504 r246571 54 54 , m_instance(WTFMove(instance)) 55 55 , m_vm(&vm) 56 , m_tables(m_instance->module().moduleInformation().tableCount()) 56 57 { 57 58 for (unsigned i = 0; i < this->instance().numImportFunctions(); ++i) … … 86 87 visitor.append(thisObject->m_moduleNamespaceObject); 87 88 visitor.append(thisObject->m_memory); 88 visitor.append(thisObject->m_table); 89 for (unsigned i = 0; i < thisObject->instance().module().moduleInformation().tableCount(); ++i) 90 visitor.append(thisObject->m_tables[i]); 89 91 visitor.append(thisObject->m_callee); 90 92 visitor.reportExtraMemoryVisited(thisObject->m_instance->extraMemoryAllocated()); -
trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyInstance.h
r245765 r246571 72 72 Wasm::MemoryMode memoryMode() { return memory()->memory().mode(); } 73 73 74 JSWebAssemblyTable* table() { return m_table.get(); } 75 void setTable(VM& vm, JSWebAssemblyTable* value) { 76 ASSERT(!table()); 77 m_table.set(vm, this, value); 78 instance().setTable(makeRef(*table()->table())); 74 JSWebAssemblyTable* table(unsigned i) { return m_tables[i].get(); } 75 void setTable(VM& vm, uint32_t index, JSWebAssemblyTable* value) 76 { 77 ASSERT(index < m_tables.size()); 78 ASSERT(!table(index)); 79 m_tables[index].set(vm, this, value); 80 instance().setTable(index, makeRef(*table(index)->table())); 79 81 } 80 82 … … 99 101 WriteBarrier<JSModuleNamespaceObject> m_moduleNamespaceObject; 100 102 WriteBarrier<JSWebAssemblyMemory> m_memory; 101 WriteBarrier<JSWebAssemblyTable> m_table;103 Vector<WriteBarrier<JSWebAssemblyTable>> m_tables; 102 104 WriteBarrier<WebAssemblyToJSCallee> m_callee; 103 105 }; -
trunk/Source/JavaScriptCore/wasm/js/WebAssemblyModuleRecord.cpp
r246504 r246571 114 114 }; 115 115 116 bool hasTableImport = false;117 118 116 for (const auto& import : moduleInformation.imports) { 119 117 // Validation and linking other than Wasm::ExternalKind::Function is already done in JSWebAssemblyInstance. … … 265 263 266 264 case Wasm::ExternalKind::Table: { 267 RELEASE_ASSERT(!hasTableImport); // This should be guaranteed by a validation failure.268 265 // 7. Otherwise (i is a table import): 269 hasTableImport = true;270 266 JSWebAssemblyTable* table = jsDynamicCast<JSWebAssemblyTable*>(vm, value); 271 267 // i. If v is not a WebAssembly.Table object, throw a WebAssembly.LinkError. … … 273 269 return exception(createJSWebAssemblyLinkError(exec, vm, importFailMessage(import, "Table import", "is not an instance of WebAssembly.Table"))); 274 270 275 uint32_t expectedInitial = moduleInformation.table Information.initial();271 uint32_t expectedInitial = moduleInformation.tables[import.kindIndex].initial(); 276 272 uint32_t actualInitial = table->length(); 277 273 if (actualInitial < expectedInitial) 278 274 return exception(createJSWebAssemblyLinkError(exec, vm, importFailMessage(import, "Table import", "provided an 'initial' that is too small"))); 279 275 280 if (Optional<uint32_t> expectedMaximum = moduleInformation.table Information.maximum()) {276 if (Optional<uint32_t> expectedMaximum = moduleInformation.tables[import.kindIndex].maximum()) { 281 277 Optional<uint32_t> actualMaximum = table->maximum(); 282 278 if (!actualMaximum) … … 286 282 } 287 283 288 auto expectedType = moduleInformation.table Information.type();284 auto expectedType = moduleInformation.tables[import.kindIndex].type(); 289 285 auto actualType = table->table()->type(); 290 286 if (expectedType != actualType) … … 293 289 // ii. Append v to tables. 294 290 // iii. Append v.[[Table]] to imports. 295 m_instance->setTable(vm, table);291 m_instance->setTable(vm, import.kindIndex, table); 296 292 RETURN_IF_EXCEPTION(scope, void()); 297 293 break; … … 303 299 } 304 300 305 {306 if ( !!moduleInformation.tableInformation && moduleInformation.tableInformation.isImport()) {301 for (unsigned i = 0; i < moduleInformation.tableCount(); ++i) { 302 if (moduleInformation.tables[i].isImport()) { 307 303 // We should either have a Table import or we should have thrown an exception. 308 RELEASE_ASSERT( hasTableImport);309 } 310 311 if (! !moduleInformation.tableInformation && !hasTableImport) {312 RELEASE_ASSERT(!moduleInformation.table Information.isImport());304 RELEASE_ASSERT(m_instance->table(i)); 305 } 306 307 if (!m_instance->table(i)) { 308 RELEASE_ASSERT(!moduleInformation.tables[i].isImport()); 313 309 // We create a Table when it's a Table definition. 314 RefPtr<Wasm::Table> wasmTable = Wasm::Table::tryCreate(moduleInformation.table Information.initial(), moduleInformation.tableInformation.maximum(), moduleInformation.tableInformation.type());310 RefPtr<Wasm::Table> wasmTable = Wasm::Table::tryCreate(moduleInformation.tables[i].initial(), moduleInformation.tables[i].maximum(), moduleInformation.tables[i].type()); 315 311 if (!wasmTable) 316 312 return exception(createJSWebAssemblyLinkError(exec, vm, "couldn't create Table")); … … 320 316 scope.assertNoException(); 321 317 ASSERT(table); 322 m_instance->setTable(vm, table);318 m_instance->setTable(vm, i, table); 323 319 RETURN_IF_EXCEPTION(scope, void()); 324 320 } … … 398 394 case Wasm::ExternalKind::Table: { 399 395 // This should be guaranteed by module verification. 400 RELEASE_ASSERT(m_instance->table()); 401 ASSERT(exp.kindIndex == 0); 402 403 exportedValue = m_instance->table(); 396 RELEASE_ASSERT(m_instance->table(exp.kindIndex)); 397 exportedValue = m_instance->table(exp.kindIndex); 404 398 break; 405 399 } … … 487 481 Wasm::CodeBlock* codeBlock = m_instance->instance().codeBlock(); 488 482 const Wasm::ModuleInformation& moduleInformation = module.moduleInformation(); 489 JSWebAssemblyTable* table = m_instance->table();490 483 491 484 const Vector<Wasm::Segment::Ptr>& data = moduleInformation.data; … … 499 492 // imported wasn't compatible. However, those should error out before 500 493 // getting here. 501 ASSERT(!! table);494 ASSERT(!!m_instance->table(element.tableIndex)); 502 495 503 496 if (!element.functionIndices.size()) 504 497 continue; 505 498 506 uint32_t tableIndex = element.offset.isGlobalImport()499 uint32_t elementIndex = element.offset.isGlobalImport() 507 500 ? static_cast<uint32_t>(m_instance->instance().loadI32Global(element.offset.globalImportIndex())) 508 501 : element.offset.constValue(); 509 502 510 fn(element, tableIndex);503 fn(element, element.tableIndex, elementIndex); 511 504 512 505 if (exception) … … 532 525 533 526 // Validation of all element ranges comes before all Table and Memory initialization. 534 forEachElement([&] (const Wasm::Element& element, uint32_t tableIndex ) {535 uint64_t lastWrittenIndex = static_cast<uint64_t>( tableIndex) + static_cast<uint64_t>(element.functionIndices.size()) - 1;536 if (UNLIKELY(lastWrittenIndex >= table->length()))527 forEachElement([&] (const Wasm::Element& element, uint32_t tableIndex, uint32_t elementIndex) { 528 uint64_t lastWrittenIndex = static_cast<uint64_t>(elementIndex) + static_cast<uint64_t>(element.functionIndices.size()) - 1; 529 if (UNLIKELY(lastWrittenIndex >= m_instance->table(tableIndex)->length())) 537 530 exception = JSValue(throwException(exec, scope, createJSWebAssemblyLinkError(exec, vm, "Element is trying to set an out of bounds table index"_s))); 538 531 }); … … 553 546 554 547 JSGlobalObject* globalObject = m_instance->globalObject(vm); 555 forEachElement([&] (const Wasm::Element& element, uint32_t tableIndex ) {548 forEachElement([&] (const Wasm::Element& element, uint32_t tableIndex, uint32_t elementIndex) { 556 549 for (uint32_t i = 0; i < element.functionIndices.size(); ++i) { 557 550 // FIXME: This essentially means we're exporting an import. … … 569 562 // the only type this could be is WebAssemblyFunction. 570 563 RELEASE_ASSERT(wasmFunction); 571 table->set(tableIndex, wasmFunction);572 ++ tableIndex;564 m_instance->table(tableIndex)->set(elementIndex, wasmFunction); 565 ++elementIndex; 573 566 continue; 574 567 } 575 568 576 table->set(tableIndex,569 m_instance->table(tableIndex)->set(elementIndex, 577 570 WebAssemblyWrapperFunction::create(vm, globalObject, globalObject->webAssemblyWrapperFunctionStructure(), functionImport, functionIndex, m_instance.get(), signatureIndex)); 578 ++ tableIndex;571 ++elementIndex; 579 572 continue; 580 573 } … … 590 583 vm, globalObject, globalObject->webAssemblyFunctionStructure(), signature.argumentCount(), String(), m_instance.get(), embedderEntrypointCallee, entrypointLoadLocation, signatureIndex); 591 584 592 table->set(tableIndex, function);593 ++ tableIndex;585 m_instance->table(tableIndex)->set(elementIndex, function); 586 ++elementIndex; 594 587 } 595 588 }); -
trunk/Source/JavaScriptCore/wasm/wasm.json
r246504 r246571 68 68 "get_global": { "category": "special", "value": 35, "return": ["any"], "parameter": [], "immediate": [{"name": "global_index", "type": "varuint32"}], "description": "read a global variable" }, 69 69 "set_global": { "category": "special", "value": 36, "return": [], "parameter": ["any"], "immediate": [{"name": "global_index", "type": "varuint32"}], "description": "write a global variable" }, 70 "table.get": { "category": "special", "value": 37, "return": ["anyref"], "parameter": ["i32"], "immediate": [ ],"description": "get a table value" },71 "table.set": { "category": "special", "value": 38, "return": [], "parameter": ["i32", "anyref"], "immediate": [ ],"description": "set a table value" },70 "table.get": { "category": "special", "value": 37, "return": ["anyref"], "parameter": ["i32"], "immediate": [{"name": "table_index", "type": "varuint32"}], "description": "get a table value" }, 71 "table.set": { "category": "special", "value": 38, "return": [], "parameter": ["i32", "anyref"], "immediate": [{"name": "table_index", "type": "varuint32"}], "description": "set a table value" }, 72 72 "call": { "category": "call", "value": 16, "return": ["call"], "parameter": ["call"], "immediate": [{"name": "function_index", "type": "varuint32"}], "description": "call a function by its index" }, 73 "call_indirect": { "category": "call", "value": 17, "return": ["call"], "parameter": ["call"], "immediate": [{"name": "type_index", "type": "varuint32"}, {"name": " reserved", "type": "varuint1"}],"description": "call a function indirect with an expected signature" },73 "call_indirect": { "category": "call", "value": 17, "return": ["call"], "parameter": ["call"], "immediate": [{"name": "type_index", "type": "varuint32"}, {"name": "table_index","type": "varuint32"}],"description": "call a function indirect with an expected signature" }, 74 74 "i32.load8_s": { "category": "memory", "value": 44, "return": ["i32"], "parameter": ["addr"], "immediate": [{"name": "flags", "type": "varuint32"}, {"name": "offset", "type": "varuint32"}], "description": "load from memory" }, 75 75 "i32.load8_u": { "category": "memory", "value": 45, "return": ["i32"], "parameter": ["addr"], "immediate": [{"name": "flags", "type": "varuint32"}, {"name": "offset", "type": "varuint32"}], "description": "load from memory" },
Note: See TracChangeset
for help on using the changeset viewer.