v8/test/mjsunit/wasm/indirect-tables.js
Ben L. Titzer 0c1b4c257b [wasm] Move indirect function tables into the WasmContext
This CL changes the WASM implementation to access indirect function
tables through the WasmContext, whereas previously indirect function
tables and their sizes were constants that were inlined into compiled
into code, requiring code patching. This is a necessary step for sharing
code between instances and eventually, isolates.

R=clemensh@chromium.org,mstarzinger@chromium.org

Bug: v8:7424
Change-Id: Ida4138ed92729730dfbc0a81a84d8484b233d808
Reviewed-on: https://chromium-review.googlesource.com/895683
Commit-Queue: Ben Titzer <titzer@chromium.org>
Reviewed-by: Clemens Hammacher <clemensh@chromium.org>
Cr-Commit-Position: refs/heads/master@{#51427}
2018-02-21 12:29:21 +00:00

838 lines
26 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-constants.js");
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.setFunctionTableBounds(10, 10);
let g = builder.addImportedGlobal("q", "base", kWasmI32);
builder.addFunctionTableInit(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.setFunctionTableBounds(kTableSize, kTableSize);
let g = builder.addImportedGlobal("q", "base", kWasmI32);
builder.addFunctionTableInit(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.addFunctionTableInit(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.addFunctionTableInit(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.setFunctionTableBounds(kTableSize, kTableSize);
builder.addFunctionTableInit(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.addFunctionTableInit(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.setFunctionTableBounds(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.addFunctionTableInit(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.setFunctionTableBounds(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.addFunctionTableInit(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.setFunctionTableBounds(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.addFunctionTableInit(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.setFunctionTableBounds(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.addFunctionTableInit(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);
})();
// Remove this test when v8:7232 is addressed comprehensively.
(function TablesAreImmutableInWasmCallstacks() {
print(arguments.callee.name);
let table = new WebAssembly.Table({initial:2, element:'anyfunc'});
let builder = new WasmModuleBuilder();
builder.addImport('', 'mutator', kSig_v_v);
builder.addFunction('main', kSig_v_v)
.addBody([
kExprCallFunction, 0
]).exportAs('main');
let module = new WebAssembly.Module(builder.toBuffer());
let instance = new WebAssembly.Instance(module, {
'': {
'mutator': () => {table.set(0, null);}
}
});
table.set(0, instance.exports.main);
try {
instance.exports.main();
assertUnreached();
} catch (e) {
assertTrue(e instanceof RangeError);
}
try {
instance.exports.main();
assertUnreached();
} catch (e) {
assertTrue(e instanceof RangeError);
}
table.set(0, null);
assertEquals(null, table.get(0));
})();
(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.setFunctionTableBounds(10, 10);
let g = builder.addImportedGlobal("q", "base", kWasmI32);
builder.addFunctionTableInit(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.addFunctionTableInit(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)});
}
})();