Commit 8d6da6d5 authored by Manos Koukoutos's avatar Manos Koukoutos Committed by V8 LUCI CQ

[wasm][test] Initializer exprs. for element segments

Element segments and tables in tests used an ad-hoc mechanism to
describe the different types of initializer expressions, e.g. an number
which could denote either the value of a constant or the index of a
global. This CL tidies up and generalizes the test infrastructure by
directly using WasmInitExpr in those cases.

Additional changes:
- Introduce WasmElemSegment class.
- Remove obsolete --experimental-wasm-bulk-memory flag from tests.
- Rename WasmInitExpr.type -> kind.
- Remove dependency of wasm-module-builder from mjsunit.js (except in
  assertTraps).

Change-Id: I716254a04ceea9ceb8ac6b848e12e1637f618f0d
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2857638
Commit-Queue: Manos Koukoutos <manoskouk@chromium.org>
Reviewed-by: 's avatarClemens Backes <clemensb@chromium.org>
Cr-Commit-Position: refs/heads/master@{#74368}
parent e0192c6b
......@@ -11,7 +11,7 @@ builder.addMemory(16, 32, false, true);
builder.addType(makeSig([kWasmI32, kWasmI32, kWasmI32], [kWasmI32]));
builder.addType(makeSig([], []));
builder.setTableBounds(1, 1);
builder.addElementSegment(0, 0, false, [0]);
builder.addActiveElementSegment(0, WasmInitExpr.I32Const(0), [0]);
// Generate function 1 (out of 1).
builder.addFunction(undefined, 0 /* sig */)
.addBodyWithEnd([
......
......@@ -24,7 +24,7 @@ let builder1 = new WasmModuleBuilder();
builder1.setName('module_1');
builder1.addFunction('main', kSig_i_v).addBody([kExprUnreachable]);
builder1.addImportedTable('z', 'table');
builder1.addElementSegment(0, 0, false, [0], true);
builder1.addActiveElementSegment(0, WasmInitExpr.I32Const(0), [0]);
let module1 = new WebAssembly.Module(builder1.toBuffer());
let instance1 =
new WebAssembly.Instance(module1, {z: {table: instance0.exports.table}});
......
......@@ -11,7 +11,7 @@ let q_table = builder.addImportedTable("q", "table")
let q_base = builder.addImportedGlobal("q", "base", kWasmI32);
let q_fun = builder.addImport("q", "fun", kSig_v_v);
builder.addType(kSig_i_ii);
builder.addElementSegment(0, q_base, true, [ q_fun ])
builder.addActiveElementSegment(0, WasmInitExpr.GlobalGet(q_base), [q_fun]);
let module = new WebAssembly.Module(builder.toBuffer());
let table = new WebAssembly.Table({
element: "anyfunc",
......
......@@ -19,6 +19,7 @@ const builder2 = new WasmModuleBuilder();
const mul_import = builder2.addImport('q', 'wasm_mul', kSig_i_ii);
builder2.addImportedTable('q', 'table');
const glob_import = builder2.addImportedGlobal('q', 'glob', kWasmI32);
builder2.addElementSegment(0, glob_import, true, [mul_import]);
builder2.addActiveElementSegment(0, WasmInitExpr.GlobalGet(glob_import),
[mul_import]);
builder2.instantiate(
{q: {glob: 0, js_div: i => i, wasm_mul: mul, table: table}});
......@@ -33,7 +33,7 @@ load("test/mjsunit/wasm/wasm-module-builder.js");
kExprCallIndirect, 0, kTableZero
])
.exportFunc();
builder.addElementSegment(0, 0, false, [0, 1, 1, 0]);
builder.addActiveElementSegment(0, WasmInitExpr.I32Const(0), [0, 1, 1, 0]);
return builder.instantiate({q: {f2: i1.exports.f2, f1: i1.exports.f1}});
})();
......
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --experimental-wasm-bulk-memory
// Make sure DCHECK doesn't fire when passive data segment is at the end of the
// module.
let bytes = new Uint8Array([
......
......@@ -2,9 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --experimental-wasm-bulk-memory
load("test/mjsunit/wasm/wasm-module-builder.js");
load('test/mjsunit/wasm/wasm-module-builder.js');
(function TestPassiveDataSegment() {
const builder = new WasmModuleBuilder();
......@@ -29,7 +27,7 @@ load("test/mjsunit/wasm/wasm-module-builder.js");
function getMemoryInit(mem, segment_data) {
const builder = new WasmModuleBuilder();
builder.addImportedMemory("", "mem", 0);
builder.addImportedMemory('', 'mem', 0);
builder.addPassiveDataSegment(segment_data);
builder.addFunction('init', kSig_v_iii)
.addBody([
......@@ -160,7 +158,7 @@ function getMemoryFill(mem) {
(function TestElemDropActive() {
const builder = new WasmModuleBuilder();
builder.setTableBounds(5, 5);
builder.addElementSegment(0, 0, false, [0, 0, 0]);
builder.addActiveElementSegment(0, WasmInitExpr.I32Const(0), [0, 0, 0]);
builder.addFunction('drop', kSig_v_v)
.addBody([
kNumericPrefix, kExprElemDrop,
......@@ -185,7 +183,8 @@ function getMemoryFill(mem) {
assertEquals(0, view[kPageSize - 1]);
// Instantiation fails, memory remains unmodified.
assertThrows(() => builder.instantiate({m: {memory}}), WebAssembly.RuntimeError);
assertThrows(
() => builder.instantiate({m: {memory}}), WebAssembly.RuntimeError);
assertEquals(0, view[kPageSize - 1]);
// The second segment is not initialized.
......@@ -203,14 +202,17 @@ function getMemoryFill(mem) {
const f = builder.addFunction('f', kSig_i_v).addBody([kExprI32Const, 42]);
const tableIndex = 0;
const isGlobal = false;
builder.addElementSegment(tableIndex, 0, isGlobal, [f.index, f.index]);
builder.addActiveElementSegment(
tableIndex,
WasmInitExpr.I32Const(0),
[f.index, f.index]);
builder.addDataSegment(0, [42]);
// Instantiation fails, but still modifies the table. The memory is not
// modified, since data segments are initialized after element segments.
assertThrows(
() => builder.instantiate({m: {memory, table}}), WebAssembly.RuntimeError);
() => builder.instantiate({m: {memory, table}}),
WebAssembly.RuntimeError);
assertEquals(0, view[0]);
})();
......
......@@ -220,7 +220,7 @@ load("test/mjsunit/wasm/wasm-module-builder.js");
.exportAs("main");
builder.setTableBounds(kTableSize, kTableSize);
builder.addElementSegment(0, 0, false, [f1.index]);
builder.addActiveElementSegment(0, WasmInitExpr.I32Const(0), [f1.index]);
builder.addExportOfKind("table", kExternalTable, 0);
return new WebAssembly.Module(builder.toBuffer());
......@@ -241,7 +241,7 @@ load("test/mjsunit/wasm/wasm-module-builder.js");
.exportAs("main");
builder.addImportedTable("z", "table", kTableSize, kTableSize);
builder.addElementSegment(0, 1, false, [f2.index]);
builder.addActiveElementSegment(0, WasmInitExpr.I32Const(1), [f2.index]);
var m2_bytes = builder.toBuffer();
var m2 = new WebAssembly.Module(m2_bytes);
......
......@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --experimental-wasm-reftypes --experimental-wasm-bulk-memory
// Flags: --experimental-wasm-reftypes
load("test/mjsunit/wasm/wasm-module-builder.js");
......@@ -50,7 +50,8 @@ load("test/mjsunit/wasm/wasm-module-builder.js");
print(arguments.callee.name);
const builder = new WasmModuleBuilder();
builder.addDeclarativeElementSegment([null]);
builder.addDeclarativeElementSegment([WasmInitExpr.RefNull(kWasmFuncRef)],
kWasmFuncRef);
builder.addFunction('drop', kSig_v_v)
.addBody([kNumericPrefix, kExprElemDrop, 0])
.exportFunc();
......@@ -66,7 +67,8 @@ load("test/mjsunit/wasm/wasm-module-builder.js");
const builder = new WasmModuleBuilder();
const table = builder.addTable(kWasmAnyFunc, 10);
builder.addDeclarativeElementSegment([null]);
builder.addDeclarativeElementSegment([WasmInitExpr.RefNull(kWasmFuncRef)],
kWasmFuncRef);
builder.addFunction('init', kSig_v_v)
.addBody([
kExprI32Const, 0, kExprI32Const, 0, kExprI32Const, 1, kNumericPrefix,
......
......@@ -41,8 +41,8 @@ let kTableSize = 50;
let f17 = addConstFunc(builder, 17);
builder.addExport("f15", f15);
builder.addExport("f17", f17);
builder.addElementSegment(0, 15, false, [f15]);
builder.addElementSegment(0, 1, false, [call.index]);
builder.addActiveElementSegment(0, WasmInitExpr.I32Const(15), [f15]);
builder.addActiveElementSegment(0, WasmInitExpr.I32Const(1), [call.index]);
var mod1 = builder.toModule();
}
......@@ -62,10 +62,10 @@ let kTableSize = 50;
])
.exportAs("call");
let f26 = addConstFunc(builder, 26);
builder.addElementSegment(0, 17, false, [f17]);
builder.addElementSegment(0, 21, false, [f21]);
builder.addElementSegment(0, 26, false, [f26]);
builder.addElementSegment(0, 5, false, [call.index]);
builder.addActiveElementSegment(0, WasmInitExpr.I32Const(17), [f17]);
builder.addActiveElementSegment(0, WasmInitExpr.I32Const(21), [f21]);
builder.addActiveElementSegment(0, WasmInitExpr.I32Const(26), [f26]);
builder.addActiveElementSegment(0, WasmInitExpr.I32Const(5), [call.index]);
var mod2 = builder.toModule();
}
......@@ -112,8 +112,8 @@ function addConstFuncUsingGlobal(builder, val) {
let f18 = addConstFuncUsingGlobal(builder, 18);
builder.addExport("f14", f14);
builder.addExport("f18", f18);
builder.addElementSegment(0, 14, false, [f14]);
builder.addElementSegment(0, 1, false, [call.index]);
builder.addActiveElementSegment(0, WasmInitExpr.I32Const(14), [f14]);
builder.addActiveElementSegment(0, WasmInitExpr.I32Const(1), [call.index]);
var mod1 = builder.toModule();
}
......@@ -133,10 +133,10 @@ function addConstFuncUsingGlobal(builder, val) {
])
.exportAs("call");
let f28 = addConstFuncUsingGlobal(builder, 28);
builder.addElementSegment(0, 18, false, [f18]);
builder.addElementSegment(0, 22, false, [f22]);
builder.addElementSegment(0, 28, false, [f28]);
builder.addElementSegment(0, 5, false, [call.index]);
builder.addActiveElementSegment(0, WasmInitExpr.I32Const(18), [f18]);
builder.addActiveElementSegment(0, WasmInitExpr.I32Const(22), [f22]);
builder.addActiveElementSegment(0, WasmInitExpr.I32Const(28), [f28]);
builder.addActiveElementSegment(0, WasmInitExpr.I32Const(5), [call.index]);
var mod2 = builder.toModule();
}
......@@ -192,8 +192,8 @@ function addConstFuncUsingMemory(builder, val) {
let f19 = addConstFuncUsingMemory(builder, 19);
builder.addExport("f13", f13);
builder.addExport("f19", f19);
builder.addElementSegment(0, 13, false, [f13]);
builder.addElementSegment(0, 1, false, [call.index]);
builder.addActiveElementSegment(0, WasmInitExpr.I32Const(13), [f13]);
builder.addActiveElementSegment(0, WasmInitExpr.I32Const(1), [call.index]);
var mod1 = builder.toModule();
}
......@@ -215,10 +215,10 @@ function addConstFuncUsingMemory(builder, val) {
])
.exportAs("call");
let f29 = addConstFuncUsingMemory(builder, 29);
builder.addElementSegment(0, 19, false, [f19]);
builder.addElementSegment(0, 23, false, [f23]);
builder.addElementSegment(0, 29, false, [f29]);
builder.addElementSegment(0, 5, false, [call.index]);
builder.addActiveElementSegment(0, WasmInitExpr.I32Const(19), [f19]);
builder.addActiveElementSegment(0, WasmInitExpr.I32Const(23), [f23]);
builder.addActiveElementSegment(0, WasmInitExpr.I32Const(29), [f29]);
builder.addActiveElementSegment(0, WasmInitExpr.I32Const(5), [call.index]);
var mod2 = builder.toModule();
}
......
......@@ -67,11 +67,12 @@ load("test/mjsunit/wasm/wasm-module-builder.js");
.exportAs('return_call_invalid_sig');
// We want to crash if we call through the table with index 0.
builder.addElementSegment(placeholder, 0, false,
builder.addActiveElementSegment(placeholder, WasmInitExpr.I32Const(0),
[f_unreachable, f_unreachable, f_unreachable]);
builder.addElementSegment(table1, 0, false, [f1, f2, f3]);
builder.addActiveElementSegment(table1, WasmInitExpr.I32Const(0),
[f1, f2, f3]);
// Keep one slot in table2 uninitialized. We should trap if we call it.
builder.addElementSegment(table2, 1, false,
builder.addActiveElementSegment(table2, WasmInitExpr.I32Const(1),
[f_unreachable, f_unreachable, f4, f5]);
const instance = builder.instantiate();
......@@ -126,7 +127,7 @@ load("test/mjsunit/wasm/wasm-module-builder.js");
kExprCallIndirect, sig_index, t1])
.exportAs('call');
builder.addElementSegment(t1, g, true, [f1.index]);
builder.addActiveElementSegment(t1, WasmInitExpr.GlobalGet(g), [f1.index]);
const base1 = 3;
const base2 = 5;
......@@ -162,14 +163,16 @@ function js_div(a, b) { return (a / b) | 0; }
let div = builder.addImport("q", "js_div", kSig_i_ii);
builder.addImportedTable("q", "placeholder", kTableSize, kTableSize);
let table_index = builder.addImportedTable("q", "table", kTableSize, kTableSize);
let table_index = builder.addImportedTable("q", "table", kTableSize,
kTableSize);
let g = builder.addImportedGlobal("q", "base", kWasmI32);
let sig_index = builder.addType(kSig_i_ii);
builder.addFunction("placeholder", sig_index)
.addBody([kExprLocalGet, 0]);
builder.addElementSegment(table_index, g, true, [div]);
builder.addActiveElementSegment(table_index, WasmInitExpr.GlobalGet(g),
[div]);
builder.addFunction("main", kSig_i_ii)
.addBody([
kExprI32Const, 55, // --
......
......@@ -169,7 +169,8 @@ function AddFunctions(builder) {
.exportAs("main");
builder.setTableBounds(length, length);
builder.addElementSegment(0, base, false, [f.add.index, f.sub.index, f.mul.index]);
builder.addActiveElementSegment(0, WasmInitExpr.I32Const(base),
[f.add.index, f.sub.index, f.mul.index]);
return builder.instantiate();
}
......@@ -207,7 +208,8 @@ function AddFunctions(builder) {
builder.setTableBounds(10, 10);
var g = builder.addImportedGlobal("fff", "base", kWasmI32);
builder.addElementSegment(0, g, true, [f.mul.index, f.add.index, f.sub.index]);
builder.addActiveElementSegment(0, WasmInitExpr.GlobalGet(g),
[f.mul.index, f.add.index, f.sub.index]);
var module = new WebAssembly.Module(builder.toBuffer());
......
......@@ -50,8 +50,8 @@ function js_div(a, b) { return (a / b) | 0; }
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.addActiveElementSegment(0, WasmInitExpr.GlobalGet(g),
[f.mul.index, f.add.index, f.sub.index, d]);
builder.addExportOfKind("table", kExternalTable, 0);
let module = new WebAssembly.Module(builder.toBuffer());
......@@ -109,8 +109,8 @@ function js_div(a, b) { return (a / b) | 0; }
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.addActiveElementSegment(0, WasmInitExpr.GlobalGet(g),
[f.mul.index, f.add.index, f.sub.index, d]);
builder.addExportOfKind("table", kExternalTable, 0);
let m1 = new WebAssembly.Module(builder.toBuffer());
......@@ -179,8 +179,8 @@ function js_div(a, b) { return (a / b) | 0; }
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.addActiveElementSegment(0, WasmInitExpr.GlobalGet(g),
[f.mul.index, f.add.index, f.sub.index, d]);
builder.addFunction("main", kSig_i_ii)
.addBody([
kExprI32Const, 55, // --
......@@ -256,7 +256,7 @@ function js_div(a, b) { return (a / b) | 0; }
kExprLocalGet, 0,
kExprCallIndirect, sig_index, kTableZero]) // --
.exportAs("main");
builder.addElementSegment(0, g, true, [f.index]);
builder.addActiveElementSegment(0, WasmInitExpr.GlobalGet(g), [f.index]);
let module = new WebAssembly.Module(builder.toBuffer());
......@@ -297,7 +297,7 @@ function js_div(a, b) { return (a / b) | 0; }
.exportAs("main");
builder.setTableBounds(kTableSize, kTableSize);
builder.addElementSegment(0, 0, false, [f1.index]);
builder.addActiveElementSegment(0, WasmInitExpr.I32Const(0), [f1.index]);
builder.addExportOfKind("table", kExternalTable, 0);
var m1 = new WebAssembly.Module(builder.toBuffer());
......@@ -316,7 +316,7 @@ function js_div(a, b) { return (a / b) | 0; }
.exportAs("main");
builder.addImportedTable("z", "table", kTableSize, kTableSize);
builder.addElementSegment(0, 1, false, [f2.index]);
builder.addActiveElementSegment(0, WasmInitExpr.I32Const(1), [f2.index]);
var m2 = new WebAssembly.Module(builder.toBuffer());
......@@ -411,7 +411,7 @@ function js_div(a, b) { return (a / b) | 0; }
kExprLocalGet, 0,
kExprCallIndirect, sig_index, kTableZero]) // --
.exportAs("main");
builder.addElementSegment(0, g, true, [g]);
builder.addActiveElementSegment(0, WasmInitExpr.GlobalGet(g), [g]);
let module = new WebAssembly.Module(builder.toBuffer());
var instances = [];
......@@ -542,7 +542,8 @@ function js_div(a, b) { return (a / b) | 0; }
let offset = i + 1;
let len = i + 2;
let index = indexes[i];
builder.addElementSegment(0, offset, false, new Array(len).fill(index));
builder.addActiveElementSegment(0, WasmInitExpr.I32Const(offset),
new Array(len).fill(index));
}
let instance = builder.instantiate();
......@@ -586,7 +587,7 @@ function js_div(a, b) { return (a / b) | 0; }
builder1.setName('module_1');
builder1.addFunction('f', kSig_i_i).addBody([kExprLocalGet, 0]);
builder1.addImportedTable('z', 'table');
builder1.addElementSegment(0, 0, false, [0]);
builder1.addActiveElementSegment(0, WasmInitExpr.I32Const(0), [0]);
let module1 = new WebAssembly.Module(builder1.toBuffer());
let instance1 =
new WebAssembly.Instance(module1, {z: {table: instance0.exports.table}});
......@@ -622,9 +623,10 @@ function js_div(a, b) { return (a / b) | 0; }
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.addFunction('main', kSig_i_v)
.addBody([kExprI32Const, 0, kExprI32LoadMem, 0, 0]);
builder.addImportedTable('', 'table');
builder.addElementSegment(0, 0, false, [0]);
builder.addActiveElementSegment(0, WasmInitExpr.I32Const(0), [0]);
builder.addImportedMemory('', 'memory', 1);
......@@ -732,7 +734,7 @@ function js_div(a, b) { return (a / b) | 0; }
builder.setTableBounds(10, 10);
let g = builder.addImportedGlobal("q", "base", kWasmI32);
builder.addElementSegment(0, g, true, [j, w]);
builder.addActiveElementSegment(0, WasmInitExpr.GlobalGet(g), [j, w]);
let module = new WebAssembly.Module(builder.toBuffer());
for (var i = 0; i < 5; i++) {
......@@ -781,11 +783,12 @@ function js_div(a, b) { return (a / b) | 0; }
.exportAs("main");
let g = builder.addImportedGlobal("q", "base", kWasmI32);
builder.addElementSegment(0, g, true, [j, w]);
builder.addActiveElementSegment(0, WasmInitExpr.GlobalGet(g), [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 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));
......@@ -821,7 +824,7 @@ function js_div(a, b) { return (a / b) | 0; }
kExprCallIndirect, 0, kTableZero
])
.exportFunc();
builder.addElementSegment(0, 0, false, [0, 1, 1, 0]);
builder.addActiveElementSegment(0, WasmInitExpr.I32Const(0), [0, 1, 1, 0]);
return builder.instantiate({q: {f2: i1.exports.f2, f1: i1.exports.f1}});
})();
......@@ -884,7 +887,7 @@ function js_div(a, b) { return (a / b) | 0; }
])
.exportFunc();
builder.exportMemoryAs("memory");
builder.addElementSegment(0, 0, false, [0, 1, 2, 3]);
builder.addActiveElementSegment(0, WasmInitExpr.I32Const(0), [0, 1, 2, 3]);
var instance = builder.instantiate({q: {f1: f100, f2: f200, f3: f300}});
setMemI32(instance, 0, 5000000);
setMemI32(instance, 4, 6000000);
......
......@@ -32,7 +32,8 @@ load("test/mjsunit/wasm/wasm-module-builder.js");
const f2 = builder_for_import.addFunction('f2', kSig_i_v)
.addBody([kExprI32Const, value2]).index;
builder_for_import.addElementSegment(t1, offset1, false, [f1, f2]);
builder_for_import.addActiveElementSegment(t1, WasmInitExpr.I32Const(offset1),
[f1, f2]);
const instance_for_import = builder_for_import.instantiate();
const table1 = instance_for_import.exports.table;
assertEquals(value1, table1.get(offset1)());
......@@ -55,11 +56,12 @@ load("test/mjsunit/wasm/wasm-module-builder.js");
.addBody([kExprI32Const, value5]).index;
builder.addElementSegment(t2, offset2, false, [f3, f4]);
builder.addElementSegment(t3, offset3, false, [f5, f4]);
builder.addElementSegment(t4, offset4, false, [f3, f5]);
builder.addActiveElementSegment(t2, WasmInitExpr.I32Const(offset2), [f3, f4]);
builder.addActiveElementSegment(t3, WasmInitExpr.I32Const(offset3), [f5, f4]);
builder.addActiveElementSegment(t4, WasmInitExpr.I32Const(offset4), [f3, f5]);
// Add one more overlapping offset
builder.addElementSegment(t4, offset4 + 1, false, [f4, f3]);
builder.addActiveElementSegment(t4, WasmInitExpr.I32Const(offset4 + 1),
[f4, f3]);
const instance = builder.instantiate(instance_for_import);
// table2 == table1
......
......@@ -115,7 +115,8 @@ load('test/mjsunit/wasm/wasm-module-builder.js');
.addBody([kExprLocalGet, 0, kExprLocalGet, 1, kExprI32Sub])
.exportFunc();
var table = builder.addTable(wasmRefType(binary_type), 3, 3, addition.index);
var table = builder.addTable(wasmRefType(binary_type), 3, 3,
WasmInitExpr.RefFunc(addition.index));
builder.addFunction('init', kSig_v_v)
.addBody([
......
......@@ -140,7 +140,7 @@ load("test/mjsunit/wasm/wasm-module-builder.js");
// Arbitrary location in the table.
const tableIndex = 3;
builder.addElementSegment(0, tableIndex,false,[pick]);
builder.addActiveElementSegment(0, WasmInitExpr.I32Const(tableIndex),[pick]);
let main = builder.addFunction("main", kSig_i_iii)
.addBody([
......
......@@ -117,8 +117,10 @@ const dummy_func = exports.set_table_func1;
const offset1 = 3;
const offset2 = 9;
builder.addElementSegment(t1, offset1, false, [f1.index, f2.index]);
builder.addElementSegment(t2, offset2, false, [f3.index, f1.index]);
builder.addActiveElementSegment(t1, WasmInitExpr.I32Const(offset1),
[f1.index, f2.index]);
builder.addActiveElementSegment(t2, WasmInitExpr.I32Const(offset2),
[f3.index, f1.index]);
const instance = builder.instantiate();
......
......@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --experimental-wasm-bulk-memory --experimental-wasm-reftypes
// Flags: --experimental-wasm-reftypes
load('test/mjsunit/wasm/wasm-module-builder.js');
......
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --experimental-wasm-bulk-memory
load("test/mjsunit/wasm/wasm-module-builder.js");
function addFunction(builder, k) {
......
......@@ -11,7 +11,8 @@ load("test/mjsunit/wasm/wasm-module-builder.js");
const f1 = builder.addFunction('f', kSig_i_v).addBody([kExprI32Const, 11]);
const f2 = builder.addFunction('f', kSig_i_v).addBody([kExprI32Const, 22]);
const offset = 3;
builder.addElementSegment(0, offset, false, [f1.index, f2.index]);
builder.addActiveElementSegment(0, WasmInitExpr.I32Const(offset),
[f1.index, f2.index]);
const instance = builder.instantiate();
......@@ -27,7 +28,8 @@ load("test/mjsunit/wasm/wasm-module-builder.js");
const f2 = builder.addFunction('f', kSig_i_v).addBody([kExprI32Const, 22])
.exportAs("f2");
const offset = 3;
builder.addElementSegment(0, offset, false, [f1.index, f2.index]);
builder.addActiveElementSegment(0, WasmInitExpr.I32Const(offset),
[f1.index, f2.index]);
const instance = builder.instantiate();
......@@ -42,8 +44,10 @@ load("test/mjsunit/wasm/wasm-module-builder.js");
const f1 = builder.addFunction('f', kSig_i_v).addBody([kExprI32Const, 11]);
const f2 = builder.addFunction('f', kSig_i_v).addBody([kExprI32Const, 22]);
const offset = 3;
builder.addElementSegment(0, offset, false, [f1.index, f2.index]);
builder.addElementSegment(0, offset + 1, false, [f1.index, f2.index]);
builder.addActiveElementSegment(0, WasmInitExpr.I32Const(offset),
[f1.index, f2.index]);
builder.addActiveElementSegment(0, WasmInitExpr.I32Const(offset + 1),
[f1.index, f2.index]);
const instance = builder.instantiate();
......@@ -55,10 +59,12 @@ load("test/mjsunit/wasm/wasm-module-builder.js");
print(arguments.callee.name);
const builder = new WasmModuleBuilder();
const table = builder.addTable(kWasmAnyFunc, 20).exportAs("table");
const f1 = builder.addFunction('f', kSig_i_v).addBody([kExprI32Const, 11]).exportAs("f1");
const f1 = builder.addFunction('f', kSig_i_v)
.addBody([kExprI32Const, 11]).exportAs("f1");
const f2 = builder.addFunction('f', kSig_i_v).addBody([kExprI32Const, 22]);
const offset = 3;
builder.addElementSegment(0, offset, false, [f1.index, f1.index, f1.index]);
builder.addActiveElementSegment(0, WasmInitExpr.I32Const(offset),
[f1.index, f1.index, f1.index]);
const instance = builder.instantiate();
......@@ -78,7 +84,8 @@ load("test/mjsunit/wasm/wasm-module-builder.js");
const f1 = builder.addFunction('f', kSig_i_v).addBody([kExprI32Const, 11]);
const f2 = builder.addFunction('f', kSig_i_v).addBody([kExprI32Const, 22]);
const offset = 3;
builder.addElementSegment(0, offset, false, [f1.index, f1.index, f1.index]);
builder.addActiveElementSegment(0, WasmInitExpr.I32Const(offset),
[f1.index, f1.index, f1.index]);
const instance = builder.instantiate();
......@@ -97,7 +104,8 @@ load("test/mjsunit/wasm/wasm-module-builder.js");
const f1 = builder.addFunction('f', kSig_i_v).addBody([kExprI32Const, 11]);
const f2 = builder.addFunction('f', kSig_i_v).addBody([kExprI32Const, 22]);
const offset = 3;
builder.addElementSegment(0, offset, false, [f1.index, f1.index, f1.index]);
builder.addActiveElementSegment(0, WasmInitExpr.I32Const(offset),
[f1.index, f1.index, f1.index]);
const instance = builder.instantiate();
assertEquals(null, instance.exports.table.get(offset - 1));
......@@ -111,7 +119,8 @@ load("test/mjsunit/wasm/wasm-module-builder.js");
const f1 = builder.addFunction('f', kSig_i_v).addBody([kExprI32Const, 11]);
const f2 = builder.addFunction('f', kSig_i_v).addBody([kExprI32Const, 22]);
const offset = 3;
builder.addElementSegment(0, offset, false, [f1.index, f1.index, f1.index]);
builder.addActiveElementSegment(0, WasmInitExpr.I32Const(offset),
[f1.index, f1.index, f1.index]);
const instance = builder.instantiate();
assertThrows(() => instance.exports.table.get(size + 3), RangeError);
......@@ -125,7 +134,8 @@ load("test/mjsunit/wasm/wasm-module-builder.js");
const import1 = builder.addImport("q", "fun", kSig_i_ii);
const f1 = builder.addFunction('f', kSig_i_v).addBody([kExprI32Const, 11]);
const offset = 3;
builder.addElementSegment(0, offset, false, [f1.index, import1]);
builder.addActiveElementSegment(0, WasmInitExpr.I32Const(offset),
[f1.index, import1]);
const instance = builder.instantiate({q: {fun: () => 33}});
assertEquals(33, instance.exports.table.get(offset + 1)());
......
......@@ -132,7 +132,7 @@ let id = (() => { // identity exported function
builder.addImportedTable("q", "table", 5, 32);
let g = builder.addImportedGlobal("q", "base", kWasmI32);
builder.addElementSegment(0, g, true,
builder.addActiveElementSegment(0, WasmInitExpr.GlobalGet(g),
[funcs.mul.index, funcs.add.index, funcs.sub.index]);
builder.addExportOfKind("table", kExternalTable, 0);
let module = new WebAssembly.Module(builder.toBuffer());
......@@ -179,7 +179,7 @@ let id = (() => { // identity exported function
let t = builder.addImport("q", "exp_ten", sig_i_v);
builder.setTableBounds(7, 35);
builder.addElementSegment(0, g1, true, [a, i, t]);
builder.addActiveElementSegment(0, WasmInitExpr.GlobalGet(g1), [a, i, t]);
builder.addExportOfKind("table", kExternalTable, 0);
let module = new WebAssembly.Module(builder.toBuffer());
......@@ -212,7 +212,8 @@ let id = (() => { // identity exported function
let funcs = addFunctions(builder1);
builder1.addImportedTable("q", "table", 6, 36);
builder1.addElementSegment(0, g, true,
builder1.addActiveElementSegment(
0, WasmInitExpr.GlobalGet(g),
[funcs.mul.index, funcs.add.index, funcs.sub.index]);
let module1 = new WebAssembly.Module(builder1.toBuffer());
......@@ -228,7 +229,7 @@ let id = (() => { // identity exported function
}
for (let i = 3; i < 10; i++) {
let instance1 = new WebAssembly.Instance(module1, {q: {base: i, table: table}});
new WebAssembly.Instance(module1, {q: {base: i, table: table}});
verifyTableFuncs(i);
var prev = table.length;
assertEquals(prev, table.grow(3));
......@@ -264,7 +265,7 @@ let id = (() => { // identity exported function
kExprLocalGet, 0,
kExprCallIndirect, index_i_ii, kTableZero])
.exportAs("main");
builder.addElementSegment(0, 0, false, [0]);
builder.addActiveElementSegment(0, WasmInitExpr.I32Const(0), [0]);
return new WebAssembly.Module(builder.toBuffer());
}
......
......@@ -24,7 +24,9 @@ function bytes(...input) {
for (let i = 0; i < input.length; i++) {
let val = input[i];
if (typeof val == 'string') {
assertEquals(1, val.length, 'string inputs must have length 1');
if (val.length != 1) {
throw new Error('string inputs must have length 1');
}
val = val.charCodeAt(0);
}
view[i] = val | 0;
......@@ -122,11 +124,11 @@ function wasmRefType(index) {
let kWasmI31Ref = 0x6a;
let kWasmRttWithDepth = 0x69;
function wasmRtt(index, depth) {
return { opcode: kWasmRttWithDepth, index: index, depth: depth };
return {opcode: kWasmRttWithDepth, index: index, depth: depth};
}
let kWasmRtt = 0x68;
function wasmRttNoDepth(index) {
return { opcode: kWasmRtt, index: index };
return {opcode: kWasmRtt, index: index};
}
let kWasmDataRef = 0x67;
......@@ -824,20 +826,21 @@ let kTrapElemSegmentDropped = 10;
let kTrapRethrowNull = 11;
let kTrapMsgs = [
'unreachable',
'memory access out of bounds',
'divide by zero',
'divide result unrepresentable',
'remainder by zero',
'float unrepresentable in integer range',
'table index is out of bounds',
'null function or function signature mismatch',
'operation does not support unaligned accesses',
'data segment has been dropped',
'element segment has been dropped',
'rethrowing null value'
'unreachable', // --
'memory access out of bounds', // --
'divide by zero', // --
'divide result unrepresentable', // --
'remainder by zero', // --
'float unrepresentable in integer range', // --
'table index is out of bounds', // --
'null function or function signature mismatch', // --
'operation does not support unaligned accesses', // --
'data segment has been dropped', // --
'element segment has been dropped', // --
'rethrowing null value' // --
];
// This requires test/mjsunit/mjsunit.js.
function assertTraps(trap, code) {
assertThrows(code, WebAssembly.RuntimeError, kTrapMsgs[trap]);
}
......@@ -940,7 +943,7 @@ class Binary {
}
emit_init_expr(expr) {
switch (expr.type) {
switch (expr.kind) {
case kExprGlobalGet:
this.emit_u8(kExprGlobalGet);
this.emit_u32v(expr.value);
......@@ -1070,28 +1073,28 @@ class WasmFunctionBuilder {
class WasmInitExpr {
static I32Const(value) {
return {type: kExprI32Const, value: value};
return {kind: kExprI32Const, value: value};
}
static I64Const(value) {
return {type: kExprI64Const, value: value};
return {kind: kExprI64Const, value: value};
}
static F32Const(value) {
return {type: kExprF32Const, value: value};
return {kind: kExprF32Const, value: value};
}
static F64Const(value) {
return {type: kExprF64Const, value: value};
return {kind: kExprF64Const, value: value};
}
static S128Const(value) {
return {type: kSimdPrefix, value: value};
return {kind: kSimdPrefix, value: value};
}
static GlobalGet(index) {
return {type: kExprGlobalGet, value: index};
return {kind: kExprGlobalGet, value: index};
}
static RefFunc(index) {
return {type: kExprRefFunc, value: index};
return {kind: kExprRefFunc, value: index};
}
static RefNull(type) {
return {type: kExprRefNull, value: type};
return {kind: kExprRefNull, value: type};
}
static defaultFor(type) {
......@@ -1130,14 +1133,14 @@ class WasmGlobalBuilder {
}
class WasmTableBuilder {
constructor(module, type, initial_size, max_size, init_func_index) {
constructor(module, type, initial_size, max_size, init_expr) {
this.module = module;
this.type = type;
this.initial_size = initial_size;
this.has_max = max_size != undefined;
this.has_max = max_size !== undefined;
this.max_size = max_size;
this.init_func_index = init_func_index;
this.has_init = init_func_index != undefined;
this.init_expr = init_expr;
this.has_init = init_expr !== undefined;
}
exportAs(name) {
......@@ -1148,14 +1151,17 @@ class WasmTableBuilder {
}
function makeField(type, mutability) {
assertEquals(
'boolean', typeof mutability, 'field mutability must be boolean');
if ((typeof mutability) != 'boolean') {
throw new Error('field mutability must be boolean');
}
return {type: type, mutability: mutability};
}
class WasmStruct {
constructor(fields) {
assertTrue(Array.isArray(fields), 'struct fields must be an array');
if (!Array.isArray(fields)) {
throw new Error('struct fields must be an array');
}
this.fields = fields;
}
}
......@@ -1166,6 +1172,41 @@ class WasmArray {
}
}
class WasmElemSegment {
constructor(table, offset, type, elements, is_decl) {
this.table = table;
this.offset = offset;
this.type = type;
this.elements = elements;
this.is_decl = is_decl;
// Invariant checks.
if ((table === undefined) != (offset === undefined)) {
throw new Error("invalid element segment");
}
for (let elem of elements) {
if (((typeof elem) == 'number') != (type === undefined)) {
throw new Error("invalid element");
}
}
}
is_active() {
return this.table !== undefined;
}
is_passive() {
return this.table === undefined && !this.is_decl;
}
is_declarative() {
return this.table === undefined && this.is_decl;
}
expressions_as_elements() {
return this.type !== undefined;
}
}
class WasmModuleBuilder {
constructor() {
this.types = [];
......@@ -1259,7 +1300,7 @@ class WasmModuleBuilder {
}
addGlobal(type, mutable, init) {
if (init == undefined) init = WasmInitExpr.defaultFor(type);
if (init === undefined) init = WasmInitExpr.defaultFor(type);
let glob = new WasmGlobalBuilder(this, type, mutable, init);
glob.index = this.globals.length + this.num_imported_globals;
this.globals.push(glob);
......@@ -1267,13 +1308,13 @@ class WasmModuleBuilder {
}
addTable(
type, initial_size, max_size = undefined, init_func_index = undefined) {
type, initial_size, max_size = undefined, init_expr = undefined) {
if (type == kWasmI32 || type == kWasmI64 || type == kWasmF32 ||
type == kWasmF64 || type == kWasmS128 || type == kWasmVoid) {
throw new Error('Tables must be of a reference type');
}
let table = new WasmTableBuilder(
this, type, initial_size, max_size, init_func_index);
this, type, initial_size, max_size, init_expr);
table.index = this.tables.length + this.num_imported_tables;
this.tables.push(table);
return table;
......@@ -1379,7 +1420,7 @@ class WasmModuleBuilder {
}
addExportOfKind(name, kind, index) {
if (index == undefined && kind != kExternalTable &&
if (index === undefined && kind != kExternalTable &&
kind != kExternalMemory) {
throw new Error(
'Index for exports other than tables/memories must be provided');
......@@ -1415,28 +1456,29 @@ class WasmModuleBuilder {
this.exports.push({name: name, kind: kExternalMemory, index: 0});
}
addElementSegment(table, base, is_global, array) {
this.element_segments.push({
table: table,
base: base,
is_global: is_global,
array: array,
is_active: true,
is_declarative: false
});
return this;
// {offset} is an initializer expression.
// If {type} is undefined, then {elements} are function indices. Otherwise,
// they are initializer expressions.
addActiveElementSegment(table, offset, elements, type) {
this.element_segments.push(
new WasmElemSegment(table, offset, type, elements, false));
return this.element_segments.length - 1;
}
addPassiveElementSegment(array) {
// If {type} is undefined, then {elements} are function indices. Otherwise,
// they are initializer expressions.
addPassiveElementSegment(elements, type) {
this.element_segments.push(
{array: array, is_active: false, is_declarative: false});
return this;
new WasmElemSegment(undefined, undefined, type, elements, false));
return this.element_segments.length - 1;
}
addDeclarativeElementSegment(array) {
// If {type} is undefined, then {elements} are function indices. Otherwise,
// they are initializer expressions.
addDeclarativeElementSegment(elements, type) {
this.element_segments.push(
{array: array, is_active: false, is_declarative: true});
return this;
new WasmElemSegment(undefined, undefined, type, elements, true));
return this.element_segments.length - 1;
}
appendToTable(array) {
......@@ -1455,7 +1497,7 @@ class WasmModuleBuilder {
if (table.has_max && table_size > table.max_size) {
table.max_size = table_size;
}
return this.addElementSegment(0, base, false, array);
return this.addActiveElementSegment(0, WasmInitExpr.I32Const(base), array);
}
setTableBounds(min, max = undefined) {
......@@ -1572,9 +1614,7 @@ class WasmModuleBuilder {
section.emit_u32v(table.initial_size);
if (table.has_max) section.emit_u32v(table.max_size);
if (table.has_init) {
section.emit_u8(kExprRefFunc);
section.emit_u32v(table.init_func_index);
section.emit_u8(kExprEnd);
section.emit_init_expr(table.init_expr);
}
}
});
......@@ -1587,8 +1627,9 @@ class WasmModuleBuilder {
section.emit_u8(1); // one memory entry
const has_max = wasm.memory.max !== undefined;
if (wasm.memory.is_memory64) {
assertFalse(
wasm.memory.shared, 'sharing memory64 is not supported (yet)');
if (wasm.memory.shared) {
throw new Error('sharing memory64 is not supported (yet)');
}
section.emit_u8(
has_max ? kLimitsMemory64WithMaximum : kLimitsMemory64NoMaximum);
section.emit_u64v(wasm.memory.min);
......@@ -1662,62 +1703,65 @@ class WasmModuleBuilder {
if (wasm.element_segments.length > 0) {
if (debug) print('emitting element segments @ ' + binary.length);
binary.emit_section(kElementSectionCode, section => {
var inits = wasm.element_segments;
section.emit_u32v(inits.length);
for (let init of inits) {
if (init.is_active) {
// Active segment.
if (init.table == 0) {
section.emit_u32v(kActiveNoIndex);
} else {
section.emit_u32v(kActiveWithIndex);
section.emit_u32v(init.table);
}
if (init.is_global) {
section.emit_u8(kExprGlobalGet);
var segments = wasm.element_segments;
section.emit_u32v(segments.length);
for (let segment of segments) {
// Emit flag and header.
// Each case below corresponds to a flag from
// https://webassembly.github.io/spec/core/binary/modules.html#element-section
// (not in increasing order).
if (segment.is_active()) {
if (segment.table == 0 && segment.type === undefined) {
if (segment.expressions_as_elements()) {
section.emit_u8(0x04);
section.emit_init_expr(segment.offset);
} else {
section.emit_u8(0x00)
section.emit_init_expr(segment.offset);
}
} else {
section.emit_u8(kExprI32Const);
}
section.emit_u32v(init.base);
section.emit_u8(kExprEnd);
if (init.table != 0) {
section.emit_u8(kExternalFunction);
}
section.emit_u32v(init.array.length);
for (let index of init.array) {
section.emit_u32v(index);
}
} else if (
init.is_declarative &&
init.array.every(index => index !== null)) {
section.emit_u8(kDeclarative);
section.emit_u8(kExternalFunction);
section.emit_u32v(init.array.length);
for (let index of init.array) {
section.emit_u32v(index);
if (segment.expressions_as_elements()) {
section.emit_u8(0x06);
section.emit_u32v(segment.table);
section.emit_init_expr(segment.offset);
section.emit_type(segment.type);
} else {
section.emit_u8(0x02);
section.emit_u32v(segment.table);
section.emit_init_expr(segment.offset);
section.emit_u8(kExternalFunction);
}
}
} else {
// Passive or declarative segment with elements.
section.emit_u8(
init.is_declarative ? kDeclarativeWithElements :
kPassiveWithElements); // flags
section.emit_u8(kWasmAnyFunc);
section.emit_u32v(init.array.length);
for (let index of init.array) {
if (index === null) {
section.emit_u8(kExprRefNull);
section.emit_u8(kWasmAnyFunc);
section.emit_u8(kExprEnd);
if (segment.expressions_as_elements()) {
if (segment.is_passive()) {
section.emit_u8(0x05);
} else {
section.emit_u8(0x07);
}
section.emit_type(segment.type);
} else {
if (segment.is_passive()) {
section.emit_u8(0x01);
} else {
section.emit_u8(kExprRefFunc);
section.emit_u32v(index);
section.emit_u8(kExprEnd);
section.emit_u8(0x03);
}
section.emit_u8(kExternalFunction);
}
}
// Emit elements.
section.emit_u32v(segment.elements.length);
for (let element of segment.elements) {
if (segment.expressions_as_elements()) {
section.emit_init_expr(element);
} else {
section.emit_u32v(element);
}
}
}
});
})
}
// If there are any passive data segments, add the DataCount section.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment