1876767992
This brings our constants back in line with the changed spec text. We already use kExprTableGet and kExprTableSet, but for locals and globals we still use the old wording. This renaming is mostly mechanical. PS1 was created using: ag -l 'kExpr(Get|Set)Global' src test | \ xargs -L1 sed -E 's/kExpr(Get|Set)Global\b/kExprGlobal\1/g' -i PS2 contains manual fixes. R=mstarzinger@chromium.org Bug: v8:9810 Change-Id: I064a6448cd95bc24d31a5931b5b4ef2464ea88b1 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1847355 Commit-Queue: Clemens Backes <clemensb@chromium.org> Reviewed-by: Michael Starzinger <mstarzinger@chromium.org> Cr-Commit-Position: refs/heads/master@{#64163}
203 lines
7.0 KiB
JavaScript
203 lines
7.0 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: --expose-wasm --experimental-wasm-anyref --experimental-wasm-return-call
|
|
|
|
load("test/mjsunit/wasm/wasm-module-builder.js");
|
|
|
|
(function IndirectCallToNonZeroTable() {
|
|
print(arguments.callee.name);
|
|
|
|
const builder = new WasmModuleBuilder();
|
|
const placeholder = builder.addTable(kWasmAnyFunc, 3).index;
|
|
const table1 = builder.addTable(kWasmAnyFunc, 3).index;
|
|
const table2 = builder.addTable(kWasmAnyFunc, 5).index;
|
|
const sig_index = builder.addType(kSig_i_v);
|
|
const other_sig = builder.addType(kSig_i_i);
|
|
|
|
const v1 = 16;
|
|
const v2 = 26;
|
|
const v3 = 36;
|
|
const v4 = 46;
|
|
const v5 = 56;
|
|
|
|
const f_unreachable = builder.addFunction('unreachable', sig_index)
|
|
.addBody([kExprUnreachable]).index;
|
|
const f1 = builder.addFunction('f1', sig_index)
|
|
.addBody([kExprI32Const, v1])
|
|
.index;
|
|
const f2 = builder.addFunction('f2', sig_index)
|
|
.addBody([kExprI32Const, v2])
|
|
.index;
|
|
const f3 = builder.addFunction('f3', sig_index)
|
|
.addBody([kExprI32Const, v3])
|
|
.index;
|
|
const f4 = builder.addFunction('f4', sig_index)
|
|
.addBody([kExprI32Const, v4])
|
|
.index;
|
|
const f5 = builder.addFunction('f5', sig_index)
|
|
.addBody([kExprI32Const, v5])
|
|
.index;
|
|
|
|
builder.addFunction('call1', kSig_i_i)
|
|
.addBody([kExprLocalGet, 0, // function index
|
|
kExprCallIndirect, sig_index, table1])
|
|
.exportAs('call1');
|
|
builder.addFunction('return_call1', kSig_i_i)
|
|
.addBody([kExprLocalGet, 0, // function index
|
|
kExprReturnCallIndirect, sig_index, table1])
|
|
.exportAs('return_call1');
|
|
builder.addFunction('call2', kSig_i_i)
|
|
.addBody([kExprLocalGet, 0, // function index
|
|
kExprCallIndirect, sig_index, table2])
|
|
.exportAs('call2');
|
|
builder.addFunction('return_call2', kSig_i_i)
|
|
.addBody([kExprLocalGet, 0, // function index
|
|
kExprReturnCallIndirect, sig_index, table2])
|
|
.exportAs('return_call2');
|
|
|
|
builder.addFunction('call_invalid_sig', kSig_i_i)
|
|
.addBody([kExprLocalGet, 0, kExprLocalGet, 0, // function index + param
|
|
kExprCallIndirect, other_sig, table2])
|
|
.exportAs('call_invalid_sig');
|
|
builder.addFunction('return_call_invalid_sig', kSig_i_i)
|
|
.addBody([kExprLocalGet, 0, kExprLocalGet, 0, // function index + param
|
|
kExprReturnCallIndirect, other_sig, table2])
|
|
.exportAs('return_call_invalid_sig');
|
|
|
|
// We want to crash if we call through the table with index 0.
|
|
builder.addElementSegment(placeholder, 0, false,
|
|
[f_unreachable, f_unreachable, f_unreachable]);
|
|
builder.addElementSegment(table1, 0, false, [f1, f2, f3]);
|
|
// Keep one slot in table2 uninitialized. We should trap if we call it.
|
|
builder.addElementSegment(table2, 1, false,
|
|
[f_unreachable, f_unreachable, f4, f5]);
|
|
|
|
const instance = builder.instantiate();
|
|
|
|
assertEquals(v1, instance.exports.call1(0));
|
|
assertEquals(v2, instance.exports.call1(1));
|
|
assertEquals(v3, instance.exports.call1(2));
|
|
assertTraps(kTrapFuncInvalid, () => instance.exports.call1(3));
|
|
assertEquals(v1, instance.exports.return_call1(0));
|
|
assertEquals(v2, instance.exports.return_call1(1));
|
|
assertEquals(v3, instance.exports.return_call1(2));
|
|
assertTraps(kTrapFuncInvalid, () => instance.exports.return_call1(3));
|
|
|
|
// Try to call through the uninitialized table entry.
|
|
assertTraps(kTrapFuncSigMismatch, () => instance.exports.call2(0));
|
|
assertEquals(v4, instance.exports.call2(3));
|
|
assertEquals(v5, instance.exports.call2(4));
|
|
assertTraps(kTrapFuncSigMismatch,
|
|
() => instance.exports.call_invalid_sig(4));
|
|
assertTraps(kTrapFuncSigMismatch, () => instance.exports.return_call2(0));
|
|
assertEquals(v4, instance.exports.return_call2(3));
|
|
assertEquals(v5, instance.exports.return_call2(4));
|
|
assertTraps(kTrapFuncSigMismatch,
|
|
() => instance.exports.return_call_invalid_sig(4));
|
|
})();
|
|
|
|
(function IndirectCallToImportedNonZeroTable() {
|
|
print(arguments.callee.name);
|
|
|
|
const table_size = 10;
|
|
const placeholder = new WebAssembly.Table(
|
|
{ initial: table_size, maximum: table_size, element: "anyfunc" });
|
|
const table = new WebAssembly.Table(
|
|
{ initial: table_size, maximum: table_size, element: "anyfunc" });
|
|
|
|
const builder = new WasmModuleBuilder();
|
|
builder.addImportedTable("m", "placeholder", table_size, table_size);
|
|
const t1 = builder.addImportedTable("m", "table", table_size, table_size);
|
|
|
|
// We initialize the module twice and put the function f1 in the table at
|
|
// the index defined by {g}. Thereby we can initialize the table at different
|
|
// slots for different instances. The function f1 also returns {g} so that we
|
|
// can see that actually different functions get called.
|
|
const g = builder.addImportedGlobal("m", "base", kWasmI32);
|
|
|
|
const sig_index = builder.addType(kSig_i_v);
|
|
const f1 = builder.addFunction("foo", sig_index)
|
|
.addBody([kExprGlobalGet, g, kExprI32Const, 12, kExprI32Add]);
|
|
|
|
builder.addFunction('call', kSig_i_i)
|
|
.addBody([kExprLocalGet, 0, // function index
|
|
kExprCallIndirect, sig_index, t1])
|
|
.exportAs('call');
|
|
|
|
builder.addElementSegment(t1, g, true, [f1.index]);
|
|
const base1 = 3;
|
|
const base2 = 5;
|
|
|
|
const instance1 = builder.instantiate({
|
|
m: {
|
|
placeholder: placeholder,
|
|
table: table,
|
|
base: base1
|
|
}
|
|
});
|
|
|
|
const instance2 = builder.instantiate({
|
|
m: {
|
|
placeholder: placeholder,
|
|
table: table,
|
|
base: base2
|
|
}
|
|
});
|
|
|
|
assertEquals(base1 + 12, instance1.exports.call(base1));
|
|
assertEquals(base2 + 12, instance1.exports.call(base2));
|
|
assertEquals(base1 + 12, instance2.exports.call(base1));
|
|
assertEquals(base2 + 12, instance2.exports.call(base2));
|
|
})();
|
|
|
|
function js_div(a, b) { return (a / b) | 0; }
|
|
|
|
(function CallImportedFunction() {
|
|
let kTableSize = 10;
|
|
print(arguments.callee.name);
|
|
|
|
var builder = new WasmModuleBuilder();
|
|
|
|
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 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.addFunction("main", kSig_i_ii)
|
|
.addBody([
|
|
kExprI32Const, 55, // --
|
|
kExprLocalGet, 0, // --
|
|
kExprLocalGet, 1, // --
|
|
kExprCallIndirect, 0, table_index]) // --
|
|
.exportAs("main");
|
|
|
|
let m = new WebAssembly.Module(builder.toBuffer());
|
|
|
|
let table = new WebAssembly.Table({
|
|
element: "anyfunc",
|
|
initial: kTableSize,
|
|
maximum: kTableSize
|
|
});
|
|
let placeholder = new WebAssembly.Table({
|
|
element: "anyfunc",
|
|
initial: kTableSize,
|
|
maximum: kTableSize
|
|
});
|
|
|
|
let instance = new WebAssembly.Instance(m, {
|
|
q: {
|
|
base: 0, table: table, placeholder: placeholder,
|
|
js_div: js_div
|
|
}
|
|
});
|
|
|
|
assertEquals(13, instance.exports.main(4, 0));
|
|
})();
|