787d83c57c
* There are now two indexes for table.copy and memory.copy, one for the source and the one for the destination table/memory. (see https://github.com/WebAssembly/bulk-memory-operations/pull/43) * Reverse the order of the table.init and memory.init indexes, so the segment index is first and the table/memory index is second. (see https://github.com/WebAssembly/bulk-memory-operations/pull/45) Change-Id: I1781edd4200a7b693e3d0814999e6292aafa58d3 Reviewed-on: https://chromium-review.googlesource.com/c/1446149 Reviewed-by: Ben Titzer <titzer@chromium.org> Commit-Queue: Ben Smith <binji@chromium.org> Cr-Commit-Position: refs/heads/master@{#59259}
280 lines
7.4 KiB
JavaScript
280 lines
7.4 KiB
JavaScript
// Copyright 2019 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: --experimental-wasm-bulk-memory
|
|
|
|
load("test/mjsunit/wasm/wasm-module-builder.js");
|
|
|
|
(function TestTableCopyInbounds() {
|
|
print(arguments.callee.name);
|
|
let builder = new WasmModuleBuilder();
|
|
let sig_v_iii = builder.addType(kSig_v_iii);
|
|
let kTableSize = 5;
|
|
|
|
builder.setTableBounds(kTableSize, kTableSize);
|
|
|
|
builder.addFunction("copy", sig_v_iii)
|
|
.addBody([
|
|
kExprGetLocal, 0,
|
|
kExprGetLocal, 1,
|
|
kExprGetLocal, 2,
|
|
kNumericPrefix, kExprTableCopy, kTableZero, kTableZero])
|
|
.exportAs("copy");
|
|
|
|
let instance = builder.instantiate();
|
|
let copy = instance.exports.copy;
|
|
for (let i = 0; i < kTableSize; i++) {
|
|
copy(0, 0, i); // nop
|
|
copy(0, i, kTableSize - i);
|
|
copy(i, 0, kTableSize - i);
|
|
}
|
|
})();
|
|
|
|
function addFunction(builder, k) {
|
|
let m = builder.addFunction("", kSig_i_v)
|
|
.addBody([...wasmI32Const(k)]);
|
|
return m;
|
|
}
|
|
|
|
function addFunctions(builder, count) {
|
|
let o = {};
|
|
for (var i = 0; i < count; i++) {
|
|
o[`f${i}`] = addFunction(builder, i);
|
|
}
|
|
return o;
|
|
}
|
|
|
|
function assertTable(obj, ...elems) {
|
|
for (var i = 0; i < elems.length; i++) {
|
|
assertEquals(elems[i], obj.get(i));
|
|
}
|
|
}
|
|
|
|
(function TestTableCopyElems() {
|
|
print(arguments.callee.name);
|
|
|
|
let builder = new WasmModuleBuilder();
|
|
let sig_v_iii = builder.addType(kSig_v_iii);
|
|
let kTableSize = 5;
|
|
|
|
builder.setTableBounds(kTableSize, kTableSize);
|
|
|
|
{
|
|
let o = addFunctions(builder, kTableSize);
|
|
builder.addElementSegment(0, false,
|
|
[o.f0.index, o.f1.index, o.f2.index, o.f3.index, o.f4.index]);
|
|
}
|
|
|
|
builder.addFunction("copy", sig_v_iii)
|
|
.addBody([
|
|
kExprGetLocal, 0,
|
|
kExprGetLocal, 1,
|
|
kExprGetLocal, 2,
|
|
kNumericPrefix, kExprTableCopy, kTableZero, kTableZero])
|
|
.exportAs("copy");
|
|
|
|
builder.addExportOfKind("table", kExternalTable, 0);
|
|
|
|
let instance = builder.instantiate();
|
|
let table = instance.exports.table;
|
|
let f0 = table.get(0), f1 = table.get(1), f2 = table.get(2),
|
|
f3 = table.get(3), f4 = table.get(4);
|
|
let copy = instance.exports.copy;
|
|
|
|
assertEquals(0, f0());
|
|
assertEquals(1, f1());
|
|
assertEquals(2, f2());
|
|
|
|
assertTable(table, f0, f1, f2, f3, f4);
|
|
copy(0, 1, 1);
|
|
assertTable(table, f1, f1, f2, f3, f4);
|
|
copy(0, 1, 2);
|
|
assertTable(table, f1, f2, f2, f3, f4);
|
|
copy(3, 0, 2);
|
|
assertTable(table, f1, f2, f2, f1, f2);
|
|
copy(1, 0, 2);
|
|
assertTable(table, f1, f1, f2, f1, f2);
|
|
})();
|
|
|
|
function assertCall(call, ...elems) {
|
|
for (var i = 0; i < elems.length; i++) {
|
|
assertEquals(elems[i], call(i));
|
|
}
|
|
}
|
|
|
|
(function TestTableCopyCalls() {
|
|
print(arguments.callee.name);
|
|
|
|
let builder = new WasmModuleBuilder();
|
|
let sig_v_iii = builder.addType(kSig_v_iii);
|
|
let sig_i_i = builder.addType(kSig_i_i);
|
|
let sig_i_v = builder.addType(kSig_i_v);
|
|
let kTableSize = 5;
|
|
|
|
builder.setTableBounds(kTableSize, kTableSize);
|
|
|
|
{
|
|
let o = addFunctions(builder, 5);
|
|
builder.addElementSegment(0, false,
|
|
[o.f0.index, o.f1.index, o.f2.index, o.f3.index, o.f4.index]);
|
|
}
|
|
|
|
builder.addFunction("copy", sig_v_iii)
|
|
.addBody([
|
|
kExprGetLocal, 0,
|
|
kExprGetLocal, 1,
|
|
kExprGetLocal, 2,
|
|
kNumericPrefix, kExprTableCopy, kTableZero, kTableZero])
|
|
.exportAs("copy");
|
|
|
|
builder.addFunction("call", sig_i_i)
|
|
.addBody([
|
|
kExprGetLocal, 0,
|
|
kExprCallIndirect, sig_i_v, kTableZero])
|
|
.exportAs("call");
|
|
|
|
let instance = builder.instantiate();
|
|
let copy = instance.exports.copy;
|
|
let call = instance.exports.call;
|
|
|
|
assertCall(call, 0, 1, 2, 3, 4);
|
|
copy(0, 1, 1);
|
|
assertCall(call, 1, 1, 2, 3, 4);
|
|
copy(0, 1, 2);
|
|
assertCall(call, 1, 2, 2, 3, 4);
|
|
copy(3, 0, 2);
|
|
assertCall(call, 1, 2, 2, 1, 2);
|
|
})();
|
|
|
|
(function TestTableCopyOob1() {
|
|
print(arguments.callee.name);
|
|
|
|
let builder = new WasmModuleBuilder();
|
|
let sig_v_iii = builder.addType(kSig_v_iii);
|
|
let kTableSize = 5;
|
|
|
|
builder.setTableBounds(kTableSize, kTableSize);
|
|
|
|
builder.addFunction("copy", sig_v_iii)
|
|
.addBody([
|
|
kExprGetLocal, 0,
|
|
kExprGetLocal, 1,
|
|
kExprGetLocal, 2,
|
|
kNumericPrefix, kExprTableCopy, kTableZero, kTableZero])
|
|
.exportAs("copy");
|
|
|
|
let instance = builder.instantiate();
|
|
let copy = instance.exports.copy;
|
|
copy(0, 0, 1); // nop
|
|
copy(0, 0, kTableSize); // nop
|
|
assertThrows(() => copy(0, 0, kTableSize+1));
|
|
assertThrows(() => copy(1, 0, kTableSize));
|
|
assertThrows(() => copy(0, 1, kTableSize));
|
|
|
|
{
|
|
let big = 1000000;
|
|
assertThrows(() => copy(big, 0, 0));
|
|
assertThrows(() => copy(0, big, 0));
|
|
}
|
|
|
|
|
|
for (let big = 4294967295; big > 1000; big >>>= 1) {
|
|
assertThrows(() => copy(big, 0, 1));
|
|
assertThrows(() => copy(0, big, 1));
|
|
assertThrows(() => copy(0, 0, big));
|
|
}
|
|
|
|
for (let big = -1000; big != 0; big <<= 1) {
|
|
assertThrows(() => copy(big, 0, 1));
|
|
assertThrows(() => copy(0, big, 1));
|
|
assertThrows(() => copy(0, 0, big));
|
|
}
|
|
|
|
})();
|
|
|
|
(function TestTableCopyShared() {
|
|
print(arguments.callee.name);
|
|
let kTableSize = 5;
|
|
|
|
let table = new WebAssembly.Table({element: "anyfunc",
|
|
initial: kTableSize,
|
|
maximum: kTableSize});
|
|
|
|
let module = (() => {
|
|
let builder = new WasmModuleBuilder();
|
|
let sig_v_iii = builder.addType(kSig_v_iii);
|
|
let sig_i_i = builder.addType(kSig_i_i);
|
|
let sig_i_v = builder.addType(kSig_i_v);
|
|
|
|
builder.addImportedTable("m", "table", kTableSize, kTableSize);
|
|
var g = builder.addImportedGlobal("m", "g", kWasmI32);
|
|
|
|
for (let i = 0; i < kTableSize; i++) {
|
|
let f = builder.addFunction("", kSig_i_v)
|
|
.addBody([
|
|
kExprGetGlobal, g,
|
|
...wasmI32Const(i),
|
|
kExprI32Add
|
|
]);
|
|
f.exportAs(`f${i}`);
|
|
}
|
|
|
|
builder.addFunction("copy", sig_v_iii)
|
|
.addBody([
|
|
kExprGetLocal, 0,
|
|
kExprGetLocal, 1,
|
|
kExprGetLocal, 2,
|
|
kNumericPrefix, kExprTableCopy, kTableZero, kTableZero])
|
|
.exportAs("copy");
|
|
|
|
builder.addFunction("call", sig_i_i)
|
|
.addBody([
|
|
kExprGetLocal, 0,
|
|
kExprCallIndirect, sig_i_v, kTableZero])
|
|
.exportAs("call");
|
|
|
|
return builder.toModule();
|
|
})();
|
|
|
|
// Two different instances with different globals, to verify that
|
|
// dispatch tables get updated with the right instance.
|
|
let x = new WebAssembly.Instance(module, {m: {g: 1000, table: table}});
|
|
let y = new WebAssembly.Instance(module, {m: {g: 2000, table: table}});
|
|
|
|
let x_call = x.exports.call;
|
|
let y_call = y.exports.call;
|
|
|
|
assertNotEquals(x.exports.f3, y.exports.f3);
|
|
|
|
table.set(0, x.exports.f0);
|
|
table.set(1, x.exports.f1);
|
|
table.set(2, x.exports.f2);
|
|
table.set(3, y.exports.f3);
|
|
table.set(4, y.exports.f4);
|
|
|
|
assertEquals(2003, table.get(3)(3));
|
|
assertEquals(2003, x_call(3));
|
|
assertEquals(2003, y_call(3));
|
|
|
|
// Check that calling copy on either of them updates the dispatch table
|
|
// on both of them.
|
|
assertCall(x_call, 1000, 1001, 1002, 2003, 2004);
|
|
assertCall(y_call, 1000, 1001, 1002, 2003, 2004);
|
|
|
|
x.exports.copy(0, 1, 1);
|
|
|
|
assertCall(x_call, 1001, 1001, 1002, 2003, 2004);
|
|
assertCall(y_call, 1001, 1001, 1002, 2003, 2004);
|
|
|
|
y.exports.copy(0, 1, 2);
|
|
|
|
assertCall(x_call, 1001, 1002, 1002, 2003, 2004);
|
|
assertCall(y_call, 1001, 1002, 1002, 2003, 2004);
|
|
|
|
x.exports.copy(3, 0, 2);
|
|
|
|
assertCall(x_call, 1001, 1002, 1002, 1001, 1002);
|
|
assertCall(y_call, 1001, 1002, 1002, 1001, 1002);
|
|
})();
|