2019-05-07 11:00:04 +00:00
|
|
|
// 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.
|
|
|
|
|
2020-06-09 15:54:14 +00:00
|
|
|
// Flags: --expose-wasm --experimental-wasm-reftypes
|
2019-05-07 11:00:04 +00:00
|
|
|
|
|
|
|
load('test/mjsunit/wasm/wasm-module-builder.js');
|
|
|
|
|
|
|
|
function dummy_func(val) {
|
|
|
|
let builder = new WasmModuleBuilder();
|
|
|
|
builder.addFunction('dummy', kSig_i_v)
|
|
|
|
.addBody([kExprI32Const, val])
|
|
|
|
.exportAs('dummy');
|
|
|
|
return builder.instantiate().exports.dummy;
|
|
|
|
}
|
|
|
|
|
2020-06-09 15:54:14 +00:00
|
|
|
let kSig_v_iri = makeSig([kWasmI32, kWasmExternRef, kWasmI32], []);
|
2019-05-07 11:00:04 +00:00
|
|
|
let kSig_v_iai = makeSig([kWasmI32, kWasmAnyFunc, kWasmI32], []);
|
2020-06-09 15:54:14 +00:00
|
|
|
let kSig_r_i = makeSig([kWasmI32], [kWasmExternRef]);
|
2019-05-07 11:00:04 +00:00
|
|
|
|
|
|
|
const builder = new WasmModuleBuilder();
|
|
|
|
const size = 10;
|
|
|
|
const maximum = size;
|
|
|
|
const import_ref =
|
2020-06-09 15:54:14 +00:00
|
|
|
builder.addImportedTable('imp', 'table_ref', size, maximum, kWasmExternRef);
|
2019-05-07 11:00:04 +00:00
|
|
|
const import_func =
|
|
|
|
builder.addImportedTable('imp', 'table_func', size, maximum, kWasmAnyFunc);
|
2020-06-09 15:54:14 +00:00
|
|
|
const internal_ref = builder.addTable(kWasmExternRef, size, maximum).index;
|
2019-05-07 11:00:04 +00:00
|
|
|
const internal_func = builder.addTable(kWasmAnyFunc, size, maximum).index;
|
|
|
|
|
2020-06-09 15:54:14 +00:00
|
|
|
// Add fill and get functions for the externref tables.
|
2019-05-07 11:00:04 +00:00
|
|
|
for (index of [import_ref, internal_ref]) {
|
|
|
|
builder.addFunction(`fill${index}`, kSig_v_iri)
|
|
|
|
.addBody([
|
2019-10-08 12:38:48 +00:00
|
|
|
kExprLocalGet, 0, kExprLocalGet, 1, kExprLocalGet, 2, kNumericPrefix,
|
2019-05-07 11:00:04 +00:00
|
|
|
kExprTableFill, index
|
|
|
|
])
|
|
|
|
.exportFunc();
|
|
|
|
|
|
|
|
builder.addFunction(`get${index}`, kSig_r_i)
|
2019-10-08 12:38:48 +00:00
|
|
|
.addBody([kExprLocalGet, 0, kExprTableGet, index])
|
2019-05-07 11:00:04 +00:00
|
|
|
.exportFunc();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Add fill and call functions for the anyfunc tables.
|
|
|
|
const sig_index = builder.addType(kSig_i_v);
|
|
|
|
for (index of [import_func, internal_func]) {
|
|
|
|
builder.addFunction(`fill${index}`, kSig_v_iai)
|
|
|
|
.addBody([
|
2019-10-08 12:38:48 +00:00
|
|
|
kExprLocalGet, 0, kExprLocalGet, 1, kExprLocalGet, 2, kNumericPrefix,
|
2019-05-07 11:00:04 +00:00
|
|
|
kExprTableFill, index
|
|
|
|
])
|
|
|
|
.exportFunc();
|
|
|
|
|
|
|
|
builder.addFunction(`call${index}`, kSig_i_i)
|
2019-10-08 12:38:48 +00:00
|
|
|
.addBody([kExprLocalGet, 0, kExprCallIndirect, sig_index, index])
|
2019-05-07 11:00:04 +00:00
|
|
|
.exportFunc();
|
|
|
|
}
|
|
|
|
|
|
|
|
const table_ref =
|
2020-06-09 15:54:14 +00:00
|
|
|
new WebAssembly.Table({element: 'externref', initial: size, maximum: maximum});
|
2019-05-07 11:00:04 +00:00
|
|
|
const table_func = new WebAssembly.Table(
|
|
|
|
{element: 'anyfunc', initial: size, maximum: maximum});
|
|
|
|
|
|
|
|
const instance =
|
|
|
|
builder.instantiate({imp: {table_ref: table_ref, table_func: table_func}});
|
|
|
|
|
2020-06-09 15:54:14 +00:00
|
|
|
function checkExternRefTable(getter, start, count, value) {
|
2019-05-07 11:00:04 +00:00
|
|
|
for (i = 0; i < count; ++i) {
|
|
|
|
assertEquals(value, getter(start + i));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-06-09 15:54:14 +00:00
|
|
|
(function testExternRefTableIsUninitialized() {
|
2019-05-07 11:00:04 +00:00
|
|
|
print(arguments.callee.name);
|
|
|
|
|
2020-06-09 15:54:14 +00:00
|
|
|
checkExternRefTable(instance.exports[`get${import_ref}`], 0, size, null);
|
|
|
|
checkExternRefTable(instance.exports[`get${internal_ref}`], 0, size, null);
|
2019-05-07 11:00:04 +00:00
|
|
|
})();
|
|
|
|
|
2020-06-09 15:54:14 +00:00
|
|
|
(function testExternRefTableFill() {
|
2019-05-07 11:00:04 +00:00
|
|
|
print(arguments.callee.name);
|
|
|
|
// Fill table and check the content.
|
|
|
|
let start = 1;
|
|
|
|
let value = {foo: 23};
|
|
|
|
let count = 3;
|
|
|
|
instance.exports[`fill${import_ref}`](start, value, count);
|
2020-06-09 15:54:14 +00:00
|
|
|
checkExternRefTable(instance.exports[`get${import_ref}`], start, count, value);
|
2019-05-07 11:00:04 +00:00
|
|
|
value = 'foo';
|
|
|
|
instance.exports[`fill${internal_ref}`](start, value, count);
|
2020-06-09 15:54:14 +00:00
|
|
|
checkExternRefTable(instance.exports[`get${internal_ref}`], start, count, value);
|
2019-05-07 11:00:04 +00:00
|
|
|
})();
|
|
|
|
|
2020-06-09 15:54:14 +00:00
|
|
|
(function testExternRefTableFillOOB() {
|
2019-05-07 11:00:04 +00:00
|
|
|
print(arguments.callee.name);
|
2020-02-17 16:21:02 +00:00
|
|
|
// Fill table out-of-bounds, check if the table wasn't altered.
|
2019-05-07 11:00:04 +00:00
|
|
|
let start = 7;
|
|
|
|
let value = {foo: 27};
|
|
|
|
// {maximum + 4} elements definitely don't fit into the table.
|
|
|
|
let count = maximum + 4;
|
|
|
|
assertTraps(
|
|
|
|
kTrapTableOutOfBounds,
|
|
|
|
() => instance.exports[`fill${import_ref}`](start, value, count));
|
2020-06-09 15:54:14 +00:00
|
|
|
checkExternRefTable(
|
2020-02-17 16:21:02 +00:00
|
|
|
instance.exports[`get${import_ref}`], start, size - start, null);
|
2019-05-07 11:00:04 +00:00
|
|
|
|
|
|
|
value = 45;
|
|
|
|
assertTraps(
|
|
|
|
kTrapTableOutOfBounds,
|
|
|
|
() => instance.exports[`fill${internal_ref}`](start, value, count));
|
2020-06-09 15:54:14 +00:00
|
|
|
checkExternRefTable(
|
2020-02-17 16:21:02 +00:00
|
|
|
instance.exports[`get${internal_ref}`], start, size - start, null);
|
2019-05-07 11:00:04 +00:00
|
|
|
})();
|
|
|
|
|
2020-06-09 15:54:14 +00:00
|
|
|
(function testExternRefTableFillOOBCountZero() {
|
2019-05-07 11:00:04 +00:00
|
|
|
print(arguments.callee.name);
|
|
|
|
// Fill 0 elements at an oob position. This should trap.
|
|
|
|
let start = size + 32;
|
|
|
|
let value = 'bar';
|
|
|
|
assertTraps(
|
|
|
|
kTrapTableOutOfBounds,
|
|
|
|
() => instance.exports[`fill${import_ref}`](start, value, 0));
|
|
|
|
assertTraps(
|
|
|
|
kTrapTableOutOfBounds,
|
|
|
|
() => instance.exports[`fill${internal_ref}`](start, value, 0));
|
|
|
|
})();
|
|
|
|
|
|
|
|
function checkAnyFuncTable(call, start, count, value) {
|
|
|
|
for (i = 0; i < count; ++i) {
|
|
|
|
if (value) {
|
|
|
|
assertEquals(value, call(start + i));
|
|
|
|
} else {
|
|
|
|
assertTraps(kTrapFuncSigMismatch, () => call(start + i));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-06-09 15:54:14 +00:00
|
|
|
(function testExternRefTableIsUninitialized() {
|
2019-05-07 11:00:04 +00:00
|
|
|
print(arguments.callee.name);
|
|
|
|
// Check that the table is uninitialized.
|
|
|
|
checkAnyFuncTable(instance.exports[`call${import_func}`], 0, size);
|
|
|
|
checkAnyFuncTable(instance.exports[`call${internal_func}`], 0, size);
|
|
|
|
})();
|
|
|
|
|
|
|
|
(function testAnyFuncTableFill() {
|
|
|
|
print(arguments.callee.name);
|
|
|
|
// Fill and check the result.
|
|
|
|
let start = 1;
|
|
|
|
let value = 44;
|
|
|
|
let count = 3;
|
|
|
|
instance.exports[`fill${import_func}`](start, dummy_func(value), count);
|
|
|
|
checkAnyFuncTable(
|
|
|
|
instance.exports[`call${import_func}`], start, count, value);
|
|
|
|
value = 21;
|
|
|
|
instance.exports[`fill${internal_func}`](start, dummy_func(value), count);
|
|
|
|
checkAnyFuncTable(
|
|
|
|
instance.exports[`call${internal_func}`], start, count, value);
|
|
|
|
})();
|
|
|
|
|
|
|
|
(function testAnyFuncTableFillOOB() {
|
|
|
|
print(arguments.callee.name);
|
2020-02-17 16:21:02 +00:00
|
|
|
// Fill table out-of-bounds, check if the table wasn't altered.
|
2019-05-07 11:00:04 +00:00
|
|
|
let start = 7;
|
|
|
|
let value = 38;
|
|
|
|
// {maximum + 4} elements definitely don't fit into the table.
|
|
|
|
let count = maximum + 4;
|
|
|
|
assertTraps(
|
|
|
|
kTrapTableOutOfBounds,
|
|
|
|
() => instance.exports[`fill${import_func}`](
|
|
|
|
start, dummy_func(value), count));
|
|
|
|
checkAnyFuncTable(
|
2020-02-17 16:21:02 +00:00
|
|
|
instance.exports[`call${import_func}`], start, size - start, null);
|
2019-05-07 11:00:04 +00:00
|
|
|
|
|
|
|
value = 46;
|
|
|
|
assertTraps(
|
|
|
|
kTrapTableOutOfBounds,
|
|
|
|
() => instance.exports[`fill${internal_func}`](
|
|
|
|
start, dummy_func(value), count));
|
|
|
|
checkAnyFuncTable(
|
2020-02-17 16:21:02 +00:00
|
|
|
instance.exports[`call${internal_func}`], start, size - start, null);
|
2019-05-07 11:00:04 +00:00
|
|
|
})();
|
|
|
|
|
|
|
|
(function testAnyFuncTableFillOOBCountZero() {
|
|
|
|
print(arguments.callee.name);
|
|
|
|
// Fill 0 elements at an oob position. This should trap.
|
|
|
|
let start = size + 32;
|
|
|
|
let value = dummy_func(33);
|
|
|
|
assertTraps(
|
|
|
|
kTrapTableOutOfBounds,
|
|
|
|
() => instance.exports[`fill${import_func}`](start, null, 0));
|
|
|
|
assertTraps(
|
|
|
|
kTrapTableOutOfBounds,
|
|
|
|
() => instance.exports[`fill${internal_func}`](start, null, 0));
|
2019-05-13 10:52:12 +00:00
|
|
|
|
|
|
|
// Check that table.fill at position `size` is still valid.
|
|
|
|
instance.exports[`fill${import_func}`](size, null, 0);
|
|
|
|
instance.exports[`fill${internal_func}`](size, null, 0);
|
2019-05-07 11:00:04 +00:00
|
|
|
})();
|