v8/test/mjsunit/wasm/indirect-tables.js
Sven Sauleau 5bdb13297f [wasm] merge js constants file in module-builder
We noticed that almost every call site were loading both files,
the split isn't necessary anymore.

In some message tests, removed the absolute line number to allow future
changes.

Bug: v8:8726
Change-Id: I8527f0a1ecfa685aa01a5e2f5f47ddf1cb13a545
Reviewed-on: https://chromium-review.googlesource.com/c/1446452
Commit-Queue: Sven Sauleau <ssauleau@igalia.com>
Reviewed-by: Ben Titzer <titzer@chromium.org>
Reviewed-by: Andreas Haas <ahaas@chromium.org>
Cr-Commit-Position: refs/heads/master@{#59220}
2019-01-30 22:10:34 +00:00

898 lines
28 KiB
JavaScript

// 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(
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(
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(
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(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, 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(1, false, [f2.index], true);
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(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(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, false, [0], true);
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, false, [0], true);
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(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(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.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, 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.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, 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));
})();