| // Copyright 2016 the V8 project authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| // Flags: --expose-wasm --expose-gc |
| |
| load("test/mjsunit/wasm/wasm-module-builder.js"); |
| |
| function AddFunctions(builder) { |
| let sig_index = builder.addType(kSig_i_ii); |
| let mul = builder.addFunction("mul", sig_index) |
| .addBody([ |
| kExprGetLocal, 0, // -- |
| kExprGetLocal, 1, // -- |
| kExprI32Mul // -- |
| ]); |
| let add = builder.addFunction("add", sig_index) |
| .addBody([ |
| kExprGetLocal, 0, // -- |
| kExprGetLocal, 1, // -- |
| kExprI32Add // -- |
| ]); |
| let sub = builder.addFunction("sub", sig_index) |
| .addBody([ |
| kExprGetLocal, 0, // -- |
| kExprGetLocal, 1, // -- |
| kExprI32Sub // -- |
| ]); |
| return {mul: mul, add: add, sub: sub}; |
| } |
| |
| function js_div(a, b) { return (a / b) | 0; } |
| |
| (function ExportedTableTest() { |
| print(arguments.callee.name); |
| |
| let builder = new WasmModuleBuilder(); |
| |
| let d = builder.addImport("q", "js_div", kSig_i_ii); |
| let f = AddFunctions(builder); |
| builder.addFunction("main", kSig_i_ii) |
| .addBody([ |
| kExprI32Const, 33, // -- |
| kExprGetLocal, 0, // -- |
| kExprGetLocal, 1, // -- |
| kExprCallIndirect, 0, kTableZero]) // -- |
| .exportAs("main"); |
| |
| f.add.exportAs("blarg"); |
| |
| builder.setTableBounds(10, 10); |
| let g = builder.addImportedGlobal("q", "base", kWasmI32); |
| builder.addElementSegment( |
| 0, g, true, [f.mul.index, f.add.index, f.sub.index, d]); |
| builder.addExportOfKind("table", kExternalTable, 0); |
| |
| let module = new WebAssembly.Module(builder.toBuffer()); |
| |
| for (let i = 0; i < 5; i++) { |
| print(" base = " + i); |
| let instance = new WebAssembly.Instance(module, {q: {base: i, js_div: js_div}}); |
| main = instance.exports.main; |
| let table = instance.exports.table; |
| assertTrue(table instanceof WebAssembly.Table); |
| assertEquals(10, table.length); |
| for (let j = 0; j < i; j++) { |
| assertSame(null, table.get(j)); |
| } |
| let mul = table.get(i+0); |
| let add = table.get(i+1); |
| let sub = table.get(i+2); |
| |
| print(" mul=" + mul); |
| print(" add=" + add); |
| print(" sub=" + sub); |
| assertEquals("function", typeof mul); |
| assertEquals("function", typeof add); |
| assertEquals("function", typeof sub); |
| assertEquals(2, mul.length); |
| assertEquals(2, add.length); |
| assertEquals(2, sub.length); |
| assertEquals(String(f.add.index), add.name); |
| |
| let exp_div = table.get(i+3); |
| assertEquals("function", typeof exp_div); |
| print(" js_div=" + exp_div); |
| // Should have a new, wrapped version of the import. |
| assertFalse(js_div == exp_div); |
| |
| |
| for (let j = i + 4; j < 10; j++) { |
| assertSame(null, table.get(j)); |
| } |
| |
| assertEquals(-33, mul(-11, 3)); |
| assertEquals(4444444, add(3333333, 1111111)); |
| assertEquals(-9999, sub(1, 10000)); |
| assertEquals(-44, exp_div(-88.1, 2)); |
| } |
| })(); |
| |
| |
| (function ImportedTableTest1() { |
| let kTableSize = 10; |
| print(arguments.callee.name); |
| var builder = new WasmModuleBuilder(); |
| |
| let d = builder.addImport("q", "js_div", kSig_i_ii); |
| let f = AddFunctions(builder); |
| builder.setTableBounds(kTableSize, kTableSize); |
| let g = builder.addImportedGlobal("q", "base", kWasmI32); |
| builder.addElementSegment( |
| 0, g, true, [f.mul.index, f.add.index, f.sub.index, d]); |
| builder.addExportOfKind("table", kExternalTable, 0); |
| |
| let m1 = new WebAssembly.Module(builder.toBuffer()); |
| |
| var builder = new WasmModuleBuilder(); |
| |
| builder.addImportedTable("r", "table", kTableSize, kTableSize); |
| builder.addFunction("main", kSig_i_ii) |
| .addBody([ |
| kExprI32Const, 33, // -- |
| kExprGetLocal, 0, // -- |
| kExprGetLocal, 1, // -- |
| kExprCallIndirect, 0, kTableZero]) // -- |
| .exportAs("main"); |
| |
| let m2 = new WebAssembly.Module(builder.toBuffer()); |
| |
| // Run 5 trials at different table bases. |
| for (let i = 0; i < 5; i++) { |
| print(" base = " + i); |
| let i1 = new WebAssembly.Instance(m1, {q: {base: i, js_div: js_div}}); |
| let table = i1.exports.table; |
| assertEquals(10, table.length); |
| let i2 = new WebAssembly.Instance(m2, {r: {table: table}}); |
| let main = i2.exports.main; |
| |
| for (var j = 0; j < i; j++) { |
| assertTraps(kTrapFuncSigMismatch, () => main(0, j)); |
| assertSame(null, table.get(j)); |
| } |
| |
| // mul |
| assertEquals("function", typeof table.get(i+0)); |
| assertEquals(0, main(0, i+0)); |
| assertEquals(66, main(2, i+0)); |
| |
| // add |
| assertEquals("function", typeof table.get(i+1)); |
| assertEquals(33, main(0, i+1)); |
| assertEquals(38, main(5, i+1)); |
| |
| // sub |
| assertEquals("function", typeof table.get(i+2)); |
| assertEquals(32, main(1, i+2)); |
| assertEquals(28, main(5, i+2)); |
| |
| // div |
| assertEquals("function", typeof table.get(i+3)); |
| assertEquals(8, main(4, i+3)); |
| assertEquals(3, main(11, i+3)); |
| |
| for (var j = i + 4; j < (kTableSize + 5); j++) { |
| assertThrows(x => main(0, j)); |
| if (j < kTableSize) assertSame(null, table.get(j)); |
| } |
| } |
| })(); |
| |
| (function ImportedTableTest2() { |
| let kTableSize = 10; |
| print(arguments.callee.name); |
| |
| var builder = new WasmModuleBuilder(); |
| |
| let d = builder.addImport("q", "js_div", kSig_i_ii); |
| builder.addImportedTable("q", "table", kTableSize, kTableSize); |
| let g = builder.addImportedGlobal("q", "base", kWasmI32); |
| let f = AddFunctions(builder); |
| builder.addElementSegment( |
| 0, g, true, [f.mul.index, f.add.index, f.sub.index, d]); |
| builder.addFunction("main", kSig_i_ii) |
| .addBody([ |
| kExprI32Const, 55, // -- |
| kExprGetLocal, 0, // -- |
| kExprGetLocal, 1, // -- |
| kExprCallIndirect, 0, kTableZero]) // -- |
| .exportAs("main"); |
| |
| let m2 = new WebAssembly.Module(builder.toBuffer()); |
| |
| // Run 5 trials at different table bases. |
| for (let i = 0; i < 5; i++) { |
| print(" base = " + i); |
| let table = new WebAssembly.Table({element: "anyfunc", |
| initial: kTableSize, |
| maximum: kTableSize}); |
| assertEquals(10, table.length); |
| let i2 = new WebAssembly.Instance(m2, {q: {base: i, table: table, |
| js_div: js_div}}); |
| let main = i2.exports.main; |
| |
| for (var j = 0; j < i; j++) { |
| assertTraps(kTrapFuncSigMismatch, () => main(0, j)); |
| assertSame(null, table.get(j)); |
| } |
| |
| // mul |
| assertEquals("function", typeof table.get(i+0)); |
| assertEquals(0, main(0, i+0)); |
| assertEquals(110, main(2, i+0)); |
| |
| // add |
| assertEquals("function", typeof table.get(i+1)); |
| assertEquals(55, main(0, i+1)); |
| assertEquals(60, main(5, i+1)); |
| |
| // sub |
| assertEquals("function", typeof table.get(i+2)); |
| assertEquals(54, main(1, i+2)); |
| assertEquals(50, main(5, i+2)); |
| |
| // div |
| assertEquals("function", typeof table.get(i+3)); |
| assertEquals(13, main(4, i+3)); |
| assertEquals(5, main(11, i+3)); |
| |
| for (var j = i + 4; j < (kTableSize + 5); j++) { |
| assertThrows(x => main(0, j)); |
| if (j < kTableSize) assertSame(null, table.get(j)); |
| } |
| } |
| })(); |
| |
| |
| (function CumulativeTest() { |
| print(arguments.callee.name); |
| |
| let kTableSize = 10; |
| let table = new WebAssembly.Table( |
| {element: "anyfunc", initial: kTableSize, maximum: kTableSize}); |
| |
| var builder = new WasmModuleBuilder(); |
| |
| builder.addImportedTable("x", "table", kTableSize, kTableSize); |
| let g = builder.addImportedGlobal("x", "base", kWasmI32); |
| let sig_index = builder.addType(kSig_i_v); |
| let f = builder.addFunction("f", sig_index) |
| .addBody([ |
| kExprGetGlobal, g |
| ]); |
| builder.addFunction("main", kSig_i_ii) |
| .addBody([ |
| kExprGetLocal, 0, |
| kExprCallIndirect, sig_index, kTableZero]) // -- |
| .exportAs("main"); |
| builder.addElementSegment(0, g, true, [f.index]); |
| |
| let module = new WebAssembly.Module(builder.toBuffer()); |
| |
| for (var i = 0; i < kTableSize; i++) { |
| print(" base = " + i); |
| let instance = new WebAssembly.Instance(module, {x: {base: i, table: table}}); |
| |
| for (var j = 0; j < kTableSize; j++) { |
| let func = table.get(j); |
| if (j > i) { |
| assertSame(null, func); |
| assertTraps(kTrapFuncSigMismatch, () => instance.exports.main(j)); |
| } else { |
| assertEquals("function", typeof func); |
| assertEquals(j, func()); |
| assertEquals(j, instance.exports.main(j)); |
| } |
| } |
| } |
| })(); |
| |
| (function TwoWayTest() { |
| print(arguments.callee.name); |
| let kTableSize = 3; |
| |
| // Module {m1} defines the table and exports it. |
| var builder = new WasmModuleBuilder(); |
| builder.addType(kSig_i_i); |
| builder.addType(kSig_i_ii); |
| var sig_index1 = builder.addType(kSig_i_v); |
| var f1 = builder.addFunction("f1", sig_index1) |
| .addBody([kExprI32Const, 11]); |
| |
| builder.addFunction("main", kSig_i_ii) |
| .addBody([ |
| kExprGetLocal, 0, // -- |
| kExprCallIndirect, sig_index1, kTableZero]) // -- |
| .exportAs("main"); |
| |
| builder.setTableBounds(kTableSize, kTableSize); |
| builder.addElementSegment(0, 0, false, [f1.index]); |
| builder.addExportOfKind("table", kExternalTable, 0); |
| |
| var m1 = new WebAssembly.Module(builder.toBuffer()); |
| |
| // Module {m2} imports the table and adds {f2}. |
| var builder = new WasmModuleBuilder(); |
| builder.addType(kSig_i_ii); |
| var sig_index2 = builder.addType(kSig_i_v); |
| var f2 = builder.addFunction("f2", sig_index2) |
| .addBody([kExprI32Const, 22]); |
| |
| builder.addFunction("main", kSig_i_ii) |
| .addBody([ |
| kExprGetLocal, 0, // -- |
| kExprCallIndirect, sig_index2, kTableZero]) // -- |
| .exportAs("main"); |
| |
| builder.addImportedTable("z", "table", kTableSize, kTableSize); |
| builder.addElementSegment(0, 1, false, [f2.index]); |
| |
| var m2 = new WebAssembly.Module(builder.toBuffer()); |
| |
| assertFalse(sig_index1 == sig_index2); |
| |
| var i1 = new WebAssembly.Instance(m1); |
| var i2 = new WebAssembly.Instance(m2, {z: {table: i1.exports.table}}); |
| |
| assertEquals(11, i1.exports.main(0)); |
| assertEquals(11, i2.exports.main(0)); |
| |
| assertEquals(22, i1.exports.main(1)); |
| assertEquals(22, i2.exports.main(1)); |
| |
| assertTraps(kTrapFuncSigMismatch, () => i1.exports.main(2)); |
| assertTraps(kTrapFuncSigMismatch, () => i2.exports.main(2)); |
| assertTraps(kTrapFuncInvalid, () => i1.exports.main(3)); |
| assertTraps(kTrapFuncInvalid, () => i2.exports.main(3)); |
| })(); |
| |
| (function MismatchedTableSize() { |
| print(arguments.callee.name); |
| let kTableSize = 5; |
| |
| for (var expsize = 1; expsize < 4; expsize++) { |
| for (var impsize = 1; impsize < 4; impsize++) { |
| print(" expsize = " + expsize + ", impsize = " + impsize); |
| var builder = new WasmModuleBuilder(); |
| builder.setTableBounds(expsize, expsize); |
| builder.addExportOfKind("expfoo", kExternalTable, 0); |
| |
| let m1 = new WebAssembly.Module(builder.toBuffer()); |
| |
| var builder = new WasmModuleBuilder(); |
| builder.addImportedTable("y", "impfoo", impsize, impsize); |
| |
| let m2 = new WebAssembly.Module(builder.toBuffer()); |
| |
| var i1 = new WebAssembly.Instance(m1); |
| |
| // TODO(titzer): v8 currently requires import table size to match |
| // export table size. |
| var ffi = {y: {impfoo: i1.exports.expfoo}}; |
| if (expsize == impsize) { |
| var i2 = new WebAssembly.Instance(m2, ffi); |
| } else { |
| assertThrows(() => new WebAssembly.Instance(m2, ffi)); |
| } |
| } |
| } |
| })(); |
| |
| (function TableGrowBoundsCheck() { |
| print(arguments.callee.name); |
| var kMaxSize = 30, kInitSize = 5; |
| let table = new WebAssembly.Table({element: "anyfunc", |
| initial: kInitSize, maximum: kMaxSize}); |
| var builder = new WasmModuleBuilder(); |
| builder.addImportedTable("x", "table", kInitSize, kMaxSize); |
| let module = new WebAssembly.Module(builder.toBuffer()); |
| let instance = new WebAssembly.Instance(module, {x: {base: 1, table: table}}); |
| |
| for(var i = kInitSize; i < kMaxSize; i+=5) { |
| assertEquals(i, table.length); |
| for (var j = 0; j < i; j++) table.set(j, null); |
| for (var j = 0; j < i; j++) assertEquals(null, table.get(j)); |
| assertThrows(() => table.set(i, null), RangeError); |
| assertThrows(() => table.get(i), RangeError); |
| assertEquals(i, table.grow(5)); |
| } |
| assertEquals(30, table.length); |
| assertThrows(() => table.grow(1), RangeError); |
| assertThrows(() => table.set(kMaxSize, null), RangeError); |
| assertThrows(() => table.get(kMaxSize), RangeError); |
| })(); |
| |
| (function CumulativeGrowTest() { |
| print(arguments.callee.name); |
| let table = new WebAssembly.Table({ |
| element: "anyfunc", initial: 10, maximum: 30}); |
| var builder = new WasmModuleBuilder(); |
| builder.addImportedTable("x", "table", 10, 30); |
| |
| let g = builder.addImportedGlobal("x", "base", kWasmI32); |
| let sig_index = builder.addType(kSig_i_v); |
| builder.addFunction("g", sig_index) |
| .addBody([ |
| kExprGetGlobal, g |
| ]); |
| builder.addFunction("main", kSig_i_ii) |
| .addBody([ |
| kExprGetLocal, 0, |
| kExprCallIndirect, sig_index, kTableZero]) // -- |
| .exportAs("main"); |
| builder.addElementSegment(0, g, true, [g]); |
| let module = new WebAssembly.Module(builder.toBuffer()); |
| |
| var instances = []; |
| for (var i = 0; i < 10; i++) { |
| print(" base = " + i); |
| instances.push(new WebAssembly.Instance( |
| module, {x: {base: i, table: table}})); |
| } |
| |
| for (var j = 0; j < 10; j++) { |
| let func = table.get(j); |
| assertEquals("function", typeof func); |
| assertEquals(j, func()); |
| assertEquals(j, instances[j].exports.main(j)); |
| } |
| |
| assertEquals(10, table.grow(10)); |
| |
| // Verify that grow does not alter function behaviors |
| for (var j = 0; j < 10; j++) { |
| let func = table.get(j); |
| assertEquals("function", typeof func); |
| assertEquals(j, func()); |
| assertEquals(j, instances[j].exports.main(j)); |
| } |
| |
| let new_builder = new WasmModuleBuilder(); |
| new_builder.addExport("wasm", new_builder.addFunction("", kSig_v_v).addBody([])); |
| new_builder.addImportedTable("x", "table", 20, 30); |
| let new_module = new WebAssembly.Module(new_builder.toBuffer()); |
| let instance = new WebAssembly.Instance(new_module, {x: {table: table}}); |
| let new_func = instance.exports.wasm; |
| |
| for (var j = 10; j < 20; j++) { |
| table.set(j, new_func); |
| let func = table.get(j); |
| assertEquals("function", typeof func); |
| assertSame(new_func, table.get(j)); |
| } |
| assertThrows(() => table.grow(11), RangeError); |
| })(); |
| |
| |
| (function TestImportTooLarge() { |
| print(arguments.callee.name); |
| let builder = new WasmModuleBuilder(); |
| builder.addImportedTable("t", "t", 1, 2); |
| |
| // initial size is too large |
| assertThrows(() => builder.instantiate({t: {t: new WebAssembly.Table( |
| {element: "anyfunc", initial: 3, maximum: 3})}}), WebAssembly.LinkError); |
| |
| // maximum size is too large |
| assertThrows(() => builder.instantiate({t: {t: new WebAssembly.Table( |
| {element: "anyfunc", initial: 1, maximum: 4})}}), WebAssembly.LinkError); |
| |
| // no maximum |
| assertThrows(() => builder.instantiate({t: {t: new WebAssembly.Table( |
| {element: "anyfunc", initial: 1})}}), WebAssembly.LinkError); |
| })(); |
| |
| (function TableImportLargerThanCompiled() { |
| print(arguments.callee.name); |
| var kMaxSize = 30, kInitSize = 5; |
| var builder = new WasmModuleBuilder(); |
| builder.addImportedTable("x", "table", 1, 35); |
| let table = new WebAssembly.Table({element: "anyfunc", |
| initial: kInitSize, maximum: kMaxSize}); |
| let module = new WebAssembly.Module(builder.toBuffer()); |
| let instance = new WebAssembly.Instance(module, {x: {base: 1, table: table}}); |
| for (var i = 0; i < kInitSize; ++i) table.set(i, null); |
| for (var i = 0; i < kInitSize; ++i) assertEquals(null, table.get(i)); |
| assertThrows(() => table.set(kInitSize, null), RangeError); |
| })(); |
| |
| (function ModulesShareTableAndGrow() { |
| print(arguments.callee.name); |
| let module1 = (() => { |
| let builder = new WasmModuleBuilder(); |
| builder.addImportedTable("x", "table", 1, 35); |
| return new WebAssembly.Module(builder.toBuffer()); |
| })(); |
| let module2 = (() => { |
| let builder = new WasmModuleBuilder(); |
| builder.addImportedTable("x", "table", 2, 40); |
| return new WebAssembly.Module(builder.toBuffer()); |
| })(); |
| |
| var kMaxSize = 30, kInitSize = 5; |
| let table = new WebAssembly.Table({element: "anyfunc", |
| initial: kInitSize, maximum: kMaxSize}); |
| let instance1 = new WebAssembly.Instance( |
| module1, {x: {base: 1, table: table}}); |
| let instance2 = new WebAssembly.Instance( |
| module2, {x: {base: 1, table: table}}); |
| |
| for (var i = 0; i < kInitSize; ++i) table.set(i, null); |
| for (var i = 0; i < kInitSize; ++i) assertEquals(null, table.get(i)); |
| assertThrows(() => table.set(kInitSize, null), RangeError); |
| assertEquals(kInitSize, table.grow(5)); |
| for (var i = 0; i < 2*kInitSize; ++i) table.set(i, null); |
| for (var i = 0; i < 2*kInitSize; ++i) assertEquals(null, table.get(i)); |
| assertThrows(() => table.set(2*kInitSize, null), RangeError); |
| // Try to grow past imported maximum |
| assertThrows(() => table.grow(21), RangeError); |
| })(); |
| |
| (function MultipleElementSegments() { |
| let kTableSize = 10; |
| print(arguments.callee.name); |
| |
| let mul = (a, b) => a * b; |
| let add = (a, b) => a + b; |
| let sub = (a, b) => a - b; |
| |
| // Test 1 to 3 segments in the elements section. |
| // segment 1 sets [1, 2] to mul, |
| // segment 2 sets [2, 3, 4] to add, |
| // segment 3 sets [3, 4, 5, 6] to sub. |
| for (let num_segments = 1; num_segments < 4; ++num_segments) { |
| var builder = new WasmModuleBuilder(); |
| |
| builder.setTableBounds(kTableSize, kTableSize); |
| builder.addExportOfKind("table", kExternalTable, 0); |
| let f = AddFunctions(builder); |
| let indexes = [f.mul.index, f.add.index, f.sub.index]; |
| for (let i = 0; i < num_segments; ++i) { |
| let offset = i + 1; |
| let len = i + 2; |
| let index = indexes[i]; |
| builder.addElementSegment(0, offset, false, new Array(len).fill(index)); |
| } |
| |
| let instance = builder.instantiate(); |
| |
| let table = instance.exports.table; |
| assertEquals(kTableSize, table.length); |
| |
| for (let i = 0; i < num_segments; ++i) { |
| let exp = i < 1 || i > 2 ? null : mul; |
| if (num_segments > 1 && i >= 2 && i <= 4) exp = add; |
| if (num_segments > 2 && i >= 3 && i <= 6) exp = sub; |
| if (!exp) { |
| assertSame(null, table.get(i)); |
| } else { |
| assertEquals("function", typeof table.get(i)); |
| assertEquals(exp(6, 3), table.get(i)(6, 3)); |
| } |
| } |
| } |
| })(); |
| |
| (function InitImportedTableSignatureMismatch() { |
| // instance0 exports a function table and a main function which indirectly |
| // calls a function from the table. |
| let builder0 = new WasmModuleBuilder(); |
| builder0.setName('module_0'); |
| let sig_index = builder0.addType(kSig_i_v); |
| builder0.addFunction('main', kSig_i_i) |
| .addBody([ |
| kExprGetLocal, 0, // - |
| kExprCallIndirect, sig_index, kTableZero |
| ]) |
| .exportAs('main'); |
| builder0.setTableBounds(3, 3); |
| builder0.addExportOfKind('table', kExternalTable); |
| let module0 = new WebAssembly.Module(builder0.toBuffer()); |
| let instance0 = new WebAssembly.Instance(module0); |
| |
| // instance1 imports the table and adds a function to it. |
| let builder1 = new WasmModuleBuilder(); |
| builder1.setName('module_1'); |
| builder1.addFunction('f', kSig_i_i).addBody([kExprGetLocal, 0]); |
| builder1.addImportedTable('z', 'table'); |
| builder1.addElementSegment(0, 0, false, [0]); |
| let module1 = new WebAssembly.Module(builder1.toBuffer()); |
| let instance1 = |
| new WebAssembly.Instance(module1, {z: {table: instance0.exports.table}}); |
| |
| // Calling the main method on instance0 should fail, because the signature of |
| // the added function does not match. |
| assertThrows( |
| () => instance0.exports.main(0), WebAssembly.RuntimeError, |
| /signature mismatch/); |
| })(); |
| |
| (function IndirectCallIntoOtherInstance() { |
| print(arguments.callee.name); |
| |
| var mem_1 = new WebAssembly.Memory({initial: 1}); |
| var mem_2 = new WebAssembly.Memory({initial: 1}); |
| var view_1 = new Int32Array(mem_1.buffer); |
| var view_2 = new Int32Array(mem_2.buffer); |
| view_1[0] = 1; |
| view_2[0] = 1000; |
| |
| let builder = new WasmModuleBuilder(); |
| let sig = builder.addType(kSig_i_v); |
| builder.addFunction('main', kSig_i_i) |
| .addBody([kExprGetLocal, 0, kExprCallIndirect, sig, kTableZero]) |
| .exportAs('main'); |
| builder.addImportedMemory('', 'memory', 1); |
| |
| builder.setTableBounds(1, 1); |
| builder.addExportOfKind('table', kExternalTable); |
| |
| let module1 = new WebAssembly.Module(builder.toBuffer()); |
| let instance1 = new WebAssembly.Instance(module1, {'':{memory:mem_1}}); |
| |
| builder = new WasmModuleBuilder(); |
| builder.addFunction('main', kSig_i_v).addBody([kExprI32Const, 0, kExprI32LoadMem, 0, 0]); |
| builder.addImportedTable('', 'table'); |
| builder.addElementSegment(0, 0, false, [0]); |
| builder.addImportedMemory('', 'memory', 1); |
| |
| |
| let module2 = new WebAssembly.Module(builder.toBuffer()); |
| let instance2 = new WebAssembly.Instance(module2, { |
| '': { |
| table: instance1.exports.table, |
| memory: mem_2 |
| } |
| }); |
| |
| assertEquals(instance1.exports.main(0), 1000); |
| })(); |
| |
| |
| (function ImportedFreestandingTable() { |
| print(arguments.callee.name); |
| |
| function forceGc() { |
| gc(); |
| gc(); |
| gc(); |
| } |
| |
| function setup() { |
| let builder = new WasmModuleBuilder(); |
| let sig = builder.addType(kSig_i_v); |
| builder.addFunction('main', kSig_i_i) |
| .addBody([kExprGetLocal, 0, kExprCallIndirect, sig, kTableZero]) |
| .exportAs('main'); |
| |
| builder.addImportedTable('', 'table'); |
| |
| let module1 = new WebAssembly.Module(builder.toBuffer()); |
| let table = new WebAssembly.Table({initial:2, element:'anyfunc'}); |
| let instance1 = new WebAssembly.Instance(module1, {'':{table: table}}); |
| |
| builder = new WasmModuleBuilder(); |
| builder.addExport('theImport', builder.addImport('', 'callout', kSig_i_v)); |
| builder.addImportedMemory('', 'memory', 1); |
| builder.addFunction('main', kSig_i_v) |
| .addBody([ |
| kExprCallFunction, 0, |
| kExprI32Const, 0, kExprI32LoadMem, 0, 0, |
| kExprI32Add |
| ]).exportAs('main'); |
| |
| let mem = new WebAssembly.Memory({initial:1}); |
| let view = new Int32Array(mem.buffer); |
| view[0] = 4; |
| |
| let module2 = new WebAssembly.Module(builder.toBuffer()); |
| let instance2 = new WebAssembly.Instance(module2, { |
| '': { |
| callout: () => { |
| forceGc(); |
| return 3; |
| }, |
| 'memory': mem |
| } |
| }); |
| table.set(0, instance2.exports.main); |
| table.set(1, instance2.exports.theImport); |
| return instance1; |
| } |
| |
| function test(variant, expectation) { |
| var instance = setup(); |
| forceGc(); |
| assertEquals(expectation, instance.exports.main(variant)); |
| } |
| |
| // 0 indirectly calls the wasm function that calls the import, |
| // 1 does the same but for the exported import. |
| test(0, 7); |
| test(1, 3); |
| })(); |
| |
| |
| (function ImportedWasmFunctionPutIntoTable() { |
| print(arguments.callee.name); |
| |
| let wasm_mul = (() => { |
| let builder = new WasmModuleBuilder(); |
| builder.addFunction("mul", kSig_i_ii) |
| .addBody( |
| [kExprGetLocal, 0, |
| kExprGetLocal, 1, |
| kExprI32Mul]) |
| .exportFunc(); |
| return builder.instantiate().exports.mul; |
| })(); |
| |
| let builder = new WasmModuleBuilder(); |
| |
| let j = builder.addImport("q", "js_div", kSig_i_ii); |
| let w = builder.addImport("q", "wasm_mul", kSig_i_ii); |
| builder.addFunction("main", kSig_i_ii) |
| .addBody([ |
| kExprI32Const, 33, // -- |
| kExprGetLocal, 0, // -- |
| kExprGetLocal, 1, // -- |
| kExprCallIndirect, 0, kTableZero]) // -- |
| .exportAs("main"); |
| |
| builder.setTableBounds(10, 10); |
| let g = builder.addImportedGlobal("q", "base", kWasmI32); |
| builder.addElementSegment(0, g, true, [j, w]); |
| |
| let module = new WebAssembly.Module(builder.toBuffer()); |
| for (var i = 0; i < 5; i++) { |
| let instance = new WebAssembly.Instance(module, {q: {base: i, js_div: js_div, wasm_mul: wasm_mul}}); |
| let j = i + 1; |
| |
| assertThrows(() => {instance.exports.main(j, i-1)}); |
| assertEquals((33/j)|0, instance.exports.main(j, i+0)); |
| assertEquals((33*j)|0, instance.exports.main(j, i+1)); |
| assertThrows(() => {instance.exports.main(j, i+2)}); |
| } |
| |
| })(); |
| |
| (function ImportedWasmFunctionPutIntoImportedTable() { |
| print(arguments.callee.name); |
| |
| let kTableSize = 10; |
| |
| let wasm_mul = (() => { |
| let builder = new WasmModuleBuilder(); |
| builder.addFunction("mul", kSig_i_ii) |
| .addBody( |
| [kExprGetLocal, 0, |
| kExprGetLocal, 1, |
| kExprI32Mul]) |
| .exportFunc(); |
| return builder.instantiate().exports.mul; |
| })(); |
| |
| let table = new WebAssembly.Table({element: "anyfunc", |
| initial: kTableSize, |
| maximum: kTableSize}); |
| |
| let builder = new WasmModuleBuilder(); |
| |
| let j = builder.addImport("q", "js_div", kSig_i_ii); |
| let w = builder.addImport("q", "wasm_mul", kSig_i_ii); |
| builder.addImportedTable("q", "table", kTableSize, kTableSize); |
| builder.addFunction("main", kSig_i_ii) |
| .addBody([ |
| kExprI32Const, 44, // -- |
| kExprGetLocal, 0, // -- |
| kExprGetLocal, 1, // -- |
| kExprCallIndirect, 0, kTableZero]) // -- |
| .exportAs("main"); |
| |
| let g = builder.addImportedGlobal("q", "base", kWasmI32); |
| builder.addElementSegment(0, g, true, [j, w]); |
| |
| let module = new WebAssembly.Module(builder.toBuffer()); |
| for (var i = 0; i < 5; i++) { |
| let instance = new WebAssembly.Instance(module, {q: {base: i, js_div: js_div, wasm_mul: wasm_mul, table: table}}); |
| let j = i + 1; |
| |
| assertEquals((44/j)|0, instance.exports.main(j, i+0)); |
| assertEquals((44*j)|0, instance.exports.main(j, i+1)); |
| assertThrows(() => {instance.exports.main(j, i+2)}); |
| } |
| })(); |
| |
| (function ExportedFunctionsImportedOrder() { |
| print(arguments.callee.name); |
| |
| let i1 = (() => { |
| let builder = new WasmModuleBuilder(); |
| builder.addFunction("f1", kSig_i_v) |
| .addBody( |
| [kExprI32Const, 1]) |
| .exportFunc(); |
| builder.addFunction("f2", kSig_i_v) |
| .addBody( |
| [kExprI32Const, 2]) |
| .exportFunc(); |
| return builder.instantiate(); |
| })(); |
| |
| let i2 = (() => { |
| let builder = new WasmModuleBuilder(); |
| builder.addTable(kWasmAnyFunc, 4); |
| builder.addImport("q", "f2", kSig_i_v); |
| builder.addImport("q", "f1", kSig_i_v); |
| builder.addFunction("main", kSig_i_i) |
| .addBody([ |
| kExprGetLocal, 0, |
| kExprCallIndirect, 0, kTableZero |
| ]) |
| .exportFunc(); |
| builder.addElementSegment(0, 0, false, [0, 1, 1, 0]); |
| |
| return builder.instantiate({q: {f2: i1.exports.f2, f1: i1.exports.f1}}); |
| })(); |
| |
| assertEquals(2, i2.exports.main(0)); |
| assertEquals(1, i2.exports.main(1)); |
| assertEquals(1, i2.exports.main(2)); |
| assertEquals(2, i2.exports.main(3)); |
| })(); |
| |
| (function IndirectCallsToImportedFunctions() { |
| print(arguments.callee.name); |
| |
| let module = (() => { |
| let builder = new WasmModuleBuilder(); |
| builder.addMemory(1, 1, false); |
| builder.addFunction("f", kSig_i_v) |
| .addBody([ |
| kExprI32Const, 0, |
| kExprI32LoadMem, 0, 4, |
| ]) |
| .exportFunc(); |
| builder.exportMemoryAs("memory"); |
| return new WebAssembly.Module(builder.toBuffer()); |
| })(); |
| |
| function setMemI32(instance, offset, val) { |
| var array = new Int32Array(instance.exports.memory.buffer); |
| array[offset/4] = val; |
| } |
| |
| function makeFun(val) { |
| let instance = new WebAssembly.Instance(module); |
| setMemI32(instance, 0, 2000000); |
| setMemI32(instance, 4, val); |
| setMemI32(instance, 8, 3000000); |
| return instance.exports.f; |
| } |
| |
| let f300 = makeFun(300); |
| let f100 = makeFun(100); |
| let f200 = makeFun(200); |
| |
| let main = (() => { |
| let builder = new WasmModuleBuilder(); |
| builder.addMemory(1, 1, false); |
| builder.addTable(kWasmAnyFunc, 4); |
| builder.addImport("q", "f1", kSig_i_v); |
| builder.addImport("q", "f2", kSig_i_v); |
| builder.addImport("q", "f3", kSig_i_v); |
| builder.addFunction("f", kSig_i_v) |
| .addBody([ |
| kExprI32Const, 8, |
| kExprI32LoadMem, 0, 0, |
| ]); |
| builder.addFunction("main", kSig_i_i) |
| .addBody([ |
| kExprGetLocal, 0, |
| kExprCallIndirect, 0, kTableZero |
| ]) |
| .exportFunc(); |
| builder.exportMemoryAs("memory"); |
| builder.addElementSegment(0, 0, false, [0, 1, 2, 3]); |
| var instance = builder.instantiate({q: {f1: f100, f2: f200, f3: f300}}); |
| setMemI32(instance, 0, 5000000); |
| setMemI32(instance, 4, 6000000); |
| setMemI32(instance, 8, 400); |
| return instance.exports.main; |
| })(); |
| |
| assertEquals(100, main(0)); |
| assertEquals(200, main(1)); |
| assertEquals(300, main(2)); |
| assertEquals(400, main(3)); |
| })(); |