[wasm] Fix tables bounds check, add Table.Grow tests
BUG=v8:6749 R=titzer@chromium.org Change-Id: I4ac2ac8d8ca98d71dbc5a86c3cca268cd836997c Reviewed-on: https://chromium-review.googlesource.com/645146 Commit-Queue: Deepti Gandluri <gdeepti@chromium.org> Reviewed-by: Ben Titzer <titzer@chromium.org> Cr-Commit-Position: refs/heads/master@{#47837}
This commit is contained in:
parent
cfcdeab002
commit
a636fcc9d2
@ -1786,6 +1786,11 @@ void InstanceBuilder::InitializeTables(
|
||||
// uninitialized entries will always fail the signature check.
|
||||
table_instance.signature_table->set(i, Smi::FromInt(kInvalidSigIndex));
|
||||
}
|
||||
} else {
|
||||
// Table is imported, patch table bounds check
|
||||
DCHECK_LE(table_size, table_instance.function_table->length());
|
||||
code_specialization->PatchTableSize(
|
||||
table_size, table_instance.function_table->length());
|
||||
}
|
||||
int int_index = static_cast<int>(index);
|
||||
|
||||
|
@ -16,7 +16,7 @@ builder0.addFunction('main', kSig_i_i)
|
||||
kExprCallIndirect, sig_index, kTableZero
|
||||
]) // --
|
||||
.exportAs('main');
|
||||
builder0.setFunctionTableLength(3);
|
||||
builder0.setFunctionTableBounds(3, 3);
|
||||
builder0.addExportOfKind('table', kExternalTable);
|
||||
let module0 = new WebAssembly.Module(builder0.toBuffer());
|
||||
let instance0 = new WebAssembly.Instance(module0);
|
||||
|
@ -189,7 +189,7 @@ load("test/mjsunit/wasm/wasm-module-builder.js");
|
||||
kExprCallIndirect, sig_index1, kTableZero]) // --
|
||||
.exportAs("main");
|
||||
|
||||
builder.setFunctionTableLength(kTableSize);
|
||||
builder.setFunctionTableBounds(kTableSize, kTableSize);
|
||||
builder.addFunctionTableInit(0, false, [f1.index]);
|
||||
builder.addExportOfKind("table", kExternalTable, 0);
|
||||
|
||||
|
@ -147,7 +147,7 @@ assertTraps(kTrapFuncInvalid, "module.exports.main(12, 3)");
|
||||
kExprCallIndirect, 0, kTableZero]) // --
|
||||
.exportAs("main");
|
||||
|
||||
builder.setFunctionTableLength(length);
|
||||
builder.setFunctionTableBounds(length, length);
|
||||
builder.addFunctionTableInit(base, false, [f.add.index, f.sub.index, f.mul.index]);
|
||||
|
||||
return builder.instantiate();
|
||||
@ -184,7 +184,7 @@ assertTraps(kTrapFuncInvalid, "module.exports.main(12, 3)");
|
||||
kExprCallIndirect, 0, kTableZero]) // --
|
||||
.exportAs("main");
|
||||
|
||||
builder.setFunctionTableLength(10);
|
||||
builder.setFunctionTableBounds(10, 10);
|
||||
var g = builder.addImportedGlobal("fff", "base", kWasmI32);
|
||||
builder.addFunctionTableInit(g, true, [f.mul.index, f.add.index, f.sub.index]);
|
||||
|
||||
|
@ -49,7 +49,7 @@ function js_div(a, b) { return (a / b) | 0; }
|
||||
|
||||
f.add.exportAs("blarg");
|
||||
|
||||
builder.setFunctionTableLength(10);
|
||||
builder.setFunctionTableBounds(10, 10);
|
||||
let g = builder.addImportedGlobal("q", "base", kWasmI32);
|
||||
builder.addFunctionTableInit(g, true, [f.mul.index, f.add.index,
|
||||
f.sub.index,
|
||||
@ -109,7 +109,7 @@ function js_div(a, b) { return (a / b) | 0; }
|
||||
|
||||
let d = builder.addImport("q", "js_div", kSig_i_ii);
|
||||
let f = AddFunctions(builder);
|
||||
builder.setFunctionTableLength(kTableSize);
|
||||
builder.setFunctionTableBounds(kTableSize, kTableSize);
|
||||
let g = builder.addImportedGlobal("q", "base", kWasmI32);
|
||||
builder.addFunctionTableInit(g, true, [f.mul.index, f.add.index,
|
||||
f.sub.index,
|
||||
@ -300,7 +300,7 @@ function js_div(a, b) { return (a / b) | 0; }
|
||||
kExprCallIndirect, sig_index1, kTableZero]) // --
|
||||
.exportAs("main");
|
||||
|
||||
builder.setFunctionTableLength(kTableSize);
|
||||
builder.setFunctionTableBounds(kTableSize, kTableSize);
|
||||
builder.addFunctionTableInit(0, false, [f1.index]);
|
||||
builder.addExportOfKind("table", kExternalTable, 0);
|
||||
|
||||
@ -349,7 +349,7 @@ function js_div(a, b) { return (a / b) | 0; }
|
||||
for (var impsize = 1; impsize < 4; impsize++) {
|
||||
print(" expsize = " + expsize + ", impsize = " + impsize);
|
||||
var builder = new WasmModuleBuilder();
|
||||
builder.setFunctionTableLength(expsize);
|
||||
builder.setFunctionTableBounds(expsize, expsize);
|
||||
builder.addExportOfKind("expfoo", kExternalTable, 0);
|
||||
|
||||
let m1 = new WebAssembly.Module(builder.toBuffer());
|
||||
@ -538,7 +538,7 @@ function js_div(a, b) { return (a / b) | 0; }
|
||||
for (let num_segments = 1; num_segments < 4; ++num_segments) {
|
||||
var builder = new WasmModuleBuilder();
|
||||
|
||||
builder.setFunctionTableLength(kTableSize);
|
||||
builder.setFunctionTableBounds(kTableSize, kTableSize);
|
||||
builder.addExportOfKind("table", kExternalTable, 0);
|
||||
let f = AddFunctions(builder);
|
||||
let indexes = [f.mul.index, f.add.index, f.sub.index];
|
||||
@ -580,7 +580,7 @@ function js_div(a, b) { return (a / b) | 0; }
|
||||
kExprCallIndirect, sig_index, kTableZero
|
||||
])
|
||||
.exportAs('main');
|
||||
builder0.setFunctionTableLength(3);
|
||||
builder0.setFunctionTableBounds(3, 3);
|
||||
builder0.addExportOfKind('table', kExternalTable);
|
||||
let module0 = new WebAssembly.Module(builder0.toBuffer());
|
||||
let instance0 = new WebAssembly.Instance(module0);
|
||||
@ -601,67 +601,3 @@ function js_div(a, b) { return (a / b) | 0; }
|
||||
() => instance0.exports.main(0), WebAssembly.RuntimeError,
|
||||
/signature mismatch/);
|
||||
})();
|
||||
|
||||
(function ModulesInstancesSharedTableBoundsCheck() {
|
||||
print("ModulesInstancesSharedTableBoundsCheck");
|
||||
let table = new WebAssembly.Table({element: "anyfunc",
|
||||
initial: 1, maximum:1000000});
|
||||
|
||||
function CallModuleBuilder() {
|
||||
var builder = new WasmModuleBuilder();
|
||||
builder.addType(kSig_i_v);
|
||||
builder.addType(kSig_v_v);
|
||||
let index_i_ii = builder.addType(kSig_i_ii);
|
||||
let index_i_i = builder.addType(kSig_i_i);
|
||||
builder.addImportedTable("x", "table", 1, 10000000);
|
||||
builder.addFunction("add", index_i_ii)
|
||||
.addBody([
|
||||
kExprGetLocal, 0,
|
||||
kExprGetLocal, 1,
|
||||
kExprI32Add]);
|
||||
builder.addFunction("main", index_i_i)
|
||||
.addBody([
|
||||
kExprI32Const, 5,
|
||||
kExprI32Const, 5,
|
||||
kExprGetLocal, 0,
|
||||
kExprCallIndirect, index_i_ii, kTableZero])
|
||||
.exportAs("main");
|
||||
builder.addFunctionTableInit(0, false, [0], true);
|
||||
return new WebAssembly.Module(builder.toBuffer());
|
||||
}
|
||||
|
||||
var instances = [], modules = [];
|
||||
modules[0] = CallModuleBuilder();
|
||||
modules[1] = CallModuleBuilder();
|
||||
|
||||
// Modules[0] shared by instances[0..2], modules[1] shared by instances[3, 4]
|
||||
instances[0] = new WebAssembly.Instance(modules[0], {x: {table:table}});
|
||||
instances[1] = new WebAssembly.Instance(modules[0], {x: {table:table}});
|
||||
instances[2] = new WebAssembly.Instance(modules[0], {x: {table:table}});
|
||||
instances[3] = new WebAssembly.Instance(modules[1], {x: {table:table}});
|
||||
instances[4] = new WebAssembly.Instance(modules[1], {x: {table:table}});
|
||||
|
||||
function VerifyTableBoundsCheck(size) {
|
||||
print("Verifying bounds for size = " + size);
|
||||
assertEquals(size, table.length);
|
||||
for (let i = 0; i < 5; i++) {
|
||||
// Sanity check for indirect call
|
||||
assertEquals(10, instances[i].exports.main(0));
|
||||
// Bounds check at different out of bounds indices
|
||||
assertInvalidFunction = function(s) {
|
||||
assertThrows(
|
||||
() => instances[i].exports.main(s), WebAssembly.RuntimeError,
|
||||
/invalid function/);
|
||||
}
|
||||
assertInvalidFunction(size);
|
||||
assertInvalidFunction(size + 1);
|
||||
assertInvalidFunction(size + 1000);
|
||||
assertInvalidFunction(2 * size);
|
||||
}
|
||||
}
|
||||
|
||||
for (let i = 0; i < 4; i++) {
|
||||
VerifyTableBoundsCheck(99900 * i + 1);
|
||||
table.grow(99900);
|
||||
}
|
||||
})();
|
||||
|
@ -265,7 +265,7 @@ let exportingModuleBinary2 = (() => {
|
||||
builder.addFunction('foo', kSig_v_v).addBody([]).exportAs('a');
|
||||
builder.addMemory(1, 1, false);
|
||||
builder.exportMemoryAs('b');
|
||||
builder.setFunctionTableLength(1);
|
||||
builder.setFunctionTableBounds(1, 1);
|
||||
builder.addExportOfKind('c', kExternalTable, 0);
|
||||
var o = builder.addGlobal(kWasmI32, false).exportAs('x');
|
||||
return new Int8Array(builder.toBuffer());
|
||||
|
302
test/mjsunit/wasm/table-grow.js
Normal file
302
test/mjsunit/wasm/table-grow.js
Normal file
@ -0,0 +1,302 @@
|
||||
// Copyright 2017 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.
|
||||
|
||||
load("test/mjsunit/wasm/wasm-constants.js");
|
||||
load("test/mjsunit/wasm/wasm-module-builder.js");
|
||||
|
||||
let kMaxTableSize = 10000000;
|
||||
|
||||
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 testBounds(func, table) {
|
||||
for (let i = 0; i < table.length; i++) {
|
||||
assertEquals(0, func(i));
|
||||
}
|
||||
let l = table.length;
|
||||
let oob = [l, l + 1, l + 2, l * 2, l * 3, l + 10000];
|
||||
for (let i of oob) {
|
||||
assertThrows(() => func(i));
|
||||
}
|
||||
}
|
||||
|
||||
function addMain(builder) {
|
||||
builder.addImportedTable("imp", "table", 0, kMaxTableSize);
|
||||
builder.addFunction("main", kSig_i_i)
|
||||
.addBody([
|
||||
kExprI32Const, 0,
|
||||
kExprGetLocal, 0,
|
||||
kExprCallIndirect, 0, kTableZero])
|
||||
.exportAs("main");
|
||||
}
|
||||
|
||||
let id = (() => { // identity exported function
|
||||
let builder = new WasmModuleBuilder();
|
||||
builder.addFunction("id", kSig_i_i)
|
||||
.addBody([kExprGetLocal, 0])
|
||||
.exportAs("id");
|
||||
let module = new WebAssembly.Module(builder.toBuffer());
|
||||
return (new WebAssembly.Instance(builder.toModule())).exports.id;
|
||||
})();
|
||||
|
||||
(function TableGrowBoundsCheck() {
|
||||
print("TableGrowBoundsCheck");
|
||||
let builder = new WasmModuleBuilder();
|
||||
addMain(builder);
|
||||
let module = WebAssembly.Module(builder.toBuffer());
|
||||
let table = new WebAssembly.Table({element: "anyfunc",
|
||||
initial: 1, maximum:kMaxTableSize});
|
||||
function fillTable() {
|
||||
for (let i = 0; i < table.length; i++) table.set(i, id);
|
||||
return table;
|
||||
}
|
||||
fillTable();
|
||||
let instance1 = new WebAssembly.Instance(module, {imp: {table:table}});
|
||||
testBounds(instance1.exports.main, table);
|
||||
|
||||
for (let i = 0; i < 4; i++) {
|
||||
table.grow(1);
|
||||
fillTable(table);
|
||||
testBounds(instance1.exports.main, table);
|
||||
}
|
||||
let instance2 = new WebAssembly.Instance(module, {imp: {table:table}});
|
||||
testBounds(instance2.exports.main, table);
|
||||
|
||||
for (let i = 0; i < 4; i++) {
|
||||
table.grow(1);
|
||||
fillTable(table);
|
||||
testBounds(instance1.exports.main, table);
|
||||
testBounds(instance2.exports.main, table);
|
||||
}
|
||||
})();
|
||||
|
||||
(function TableGrowBoundsZeroInitial() {
|
||||
print("TableGrowBoundsZeroInitial");
|
||||
let builder = new WasmModuleBuilder();
|
||||
addMain(builder);
|
||||
let module = WebAssembly.Module(builder.toBuffer());
|
||||
var table = new WebAssembly.Table({element: "anyfunc",
|
||||
initial: 0, maximum:kMaxTableSize});
|
||||
function growTableByOne() {
|
||||
table.grow(1);
|
||||
table.set(table.length - 1, id);
|
||||
}
|
||||
let instance1 = new WebAssembly.Instance(module, {imp: {table:table}});
|
||||
testBounds(instance1.exports.main, table);
|
||||
|
||||
for (let i = 0; i < 4; i++) {
|
||||
growTableByOne();
|
||||
testBounds(instance1.exports.main, table);
|
||||
}
|
||||
let instance2 = new WebAssembly.Instance(module, {imp: {table:table}});
|
||||
testBounds(instance2.exports.main, table);
|
||||
|
||||
for (let i = 0; i < 4; i++) {
|
||||
growTableByOne();
|
||||
testBounds(instance1.exports.main, table);
|
||||
testBounds(instance2.exports.main, table);
|
||||
}
|
||||
})();
|
||||
|
||||
(function InstancesShareTableAndGrowTest() {
|
||||
print("InstancesShareTableAndGrowTest");
|
||||
let builder = new WasmModuleBuilder();
|
||||
let funcs = addFunctions(builder);
|
||||
builder.addFunction("main", kSig_i_ii)
|
||||
.addBody([
|
||||
kExprI32Const, 15, // --
|
||||
kExprGetLocal, 0, // --
|
||||
kExprGetLocal, 1, // --
|
||||
kExprCallIndirect, 0, kTableZero]) // --
|
||||
.exportAs("main");
|
||||
|
||||
builder.addImportedTable("q", "table", 5, 32);
|
||||
let g = builder.addImportedGlobal("q", "base", kWasmI32);
|
||||
builder.addFunctionTableInit(g, true,
|
||||
[funcs.mul.index, funcs.add.index, funcs.sub.index]);
|
||||
builder.addExportOfKind("table", kExternalTable, 0);
|
||||
let module = new WebAssembly.Module(builder.toBuffer());
|
||||
let t1 = new WebAssembly.Table({element: "anyfunc",
|
||||
initial: 5, maximum: 30});
|
||||
|
||||
for (let i = 0; i < 5; i++) {
|
||||
print("base = " + i);
|
||||
let instance = new WebAssembly.Instance(module, {q: {base: i, table: t1}});
|
||||
main = instance.exports.main;
|
||||
assertEquals(i * 5 + 5, t1.length);
|
||||
|
||||
// mul
|
||||
assertEquals(15, main(1, i));
|
||||
assertEquals(30, main(2, i));
|
||||
// add
|
||||
assertEquals(20, main(5, i+1));
|
||||
assertEquals(25, main(10, i+1));
|
||||
//sub
|
||||
assertEquals(10, main(5, i+2));
|
||||
assertEquals(5, main(10, i+2));
|
||||
|
||||
assertThrows(() => t1.set(t1.length, id), RangeError);
|
||||
assertThrows(() => t1.set(t1.length + 5, id), RangeError);
|
||||
assertEquals(i * 5 + 5, t1.grow(5));
|
||||
}
|
||||
|
||||
t1.set(t1.length - 1, id);
|
||||
assertThrows(() => t1.set(t1.length, id), RangeError);
|
||||
assertThrows(() => t1.grow(2), RangeError);
|
||||
})();
|
||||
|
||||
(function ModulesShareTableAndGrowTest() {
|
||||
print("ModulesShareTableAndGrowTest");
|
||||
let builder = new WasmModuleBuilder();
|
||||
let sig_i_ii = builder.addType(kSig_i_ii);
|
||||
let sig_i_i = builder.addType(kSig_i_i);
|
||||
let sig_i_v = builder.addType(kSig_i_v);
|
||||
|
||||
let g1 = builder.addImportedGlobal("q", "base", kWasmI32);
|
||||
|
||||
let a = builder.addImport("q", "exp_add", sig_i_ii);
|
||||
let i = builder.addImport("q", "exp_inc", sig_i_i);
|
||||
let t = builder.addImport("q", "exp_ten", sig_i_v);
|
||||
|
||||
builder.setFunctionTableBounds(7, 35);
|
||||
// builder.addFunctionTableInit(g1, true,
|
||||
// [funcs.mul.index, funcs.add.index, funcs.sub.index]);
|
||||
builder.addFunctionTableInit(g1, true, [a, i, t]);
|
||||
|
||||
builder.addExportOfKind("table", kExternalTable, 0);
|
||||
let module = new WebAssembly.Module(builder.toBuffer());
|
||||
|
||||
function exp_add(a, b) { return a + b; }
|
||||
function exp_inc(a) { return a + 1 | 0; }
|
||||
function exp_ten() { return 10; }
|
||||
|
||||
let instance = new WebAssembly.Instance(module, {q: {base: 0,
|
||||
exp_add: exp_add, exp_inc: exp_inc, exp_ten: exp_ten}});
|
||||
|
||||
let table = instance.exports.table;
|
||||
exp_a = table.get(0);
|
||||
exp_i = table.get(1);
|
||||
exp_t = table.get(2);
|
||||
|
||||
assertEquals(exp_a(1, 4), 5);
|
||||
assertEquals(exp_i(8), 9);
|
||||
assertEquals(exp_t(0), 10);
|
||||
|
||||
let builder1 = new WasmModuleBuilder();
|
||||
let g = builder1.addImportedGlobal("q", "base", kWasmI32);
|
||||
let funcs = addFunctions(builder1);
|
||||
|
||||
builder1.addImportedTable("q", "table", 6, 36);
|
||||
builder1.addFunctionTableInit(g, true,
|
||||
[funcs.mul.index, funcs.add.index, funcs.sub.index]);
|
||||
let module1 = new WebAssembly.Module(builder1.toBuffer());
|
||||
|
||||
function verifyTableFuncs(base) {
|
||||
assertEquals(exp_a(1, 4), 5);
|
||||
assertEquals(exp_i(8), 9);
|
||||
assertEquals(exp_t(0), 10);
|
||||
|
||||
mul = table.get(base);
|
||||
add = table.get(base + 1);
|
||||
sub = table.get(base + 2);
|
||||
|
||||
assertEquals(20, mul(10, 2));
|
||||
assertEquals(12, add(10, 2));
|
||||
assertEquals(8, sub(10, 2));
|
||||
}
|
||||
|
||||
for (let i = 3; i < 10; i++) {
|
||||
let instance1 = new WebAssembly.Instance(module1, {q: {base: i, table: table}});
|
||||
verifyTableFuncs(i);
|
||||
assertEquals(table.length, table.grow(3));
|
||||
verifyTableFuncs(i);
|
||||
|
||||
assertThrows(() => table.set(table.length, id), RangeError);
|
||||
assertThrows(() => table.set(table.length + 5, id), RangeError);
|
||||
}
|
||||
})();
|
||||
|
||||
(function ModulesInstancesSharedTableBoundsCheck() {
|
||||
print("ModulesInstancesSharedTableBoundsCheck");
|
||||
let table = new WebAssembly.Table({element: "anyfunc",
|
||||
initial: 1, maximum: kMaxTableSize});
|
||||
|
||||
function CallModuleBuilder() {
|
||||
var builder = new WasmModuleBuilder();
|
||||
builder.addType(kSig_i_v);
|
||||
builder.addType(kSig_v_v);
|
||||
let index_i_ii = builder.addType(kSig_i_ii);
|
||||
let index_i_i = builder.addType(kSig_i_i);
|
||||
builder.addImportedTable("x", "table", 1, kMaxTableSize);
|
||||
builder.addFunction("add", index_i_ii)
|
||||
.addBody([
|
||||
kExprGetLocal, 0,
|
||||
kExprGetLocal, 1,
|
||||
kExprI32Add]);
|
||||
builder.addFunction("main", index_i_i)
|
||||
.addBody([
|
||||
kExprI32Const, 5,
|
||||
kExprI32Const, 5,
|
||||
kExprGetLocal, 0,
|
||||
kExprCallIndirect, index_i_ii, kTableZero])
|
||||
.exportAs("main");
|
||||
builder.addFunctionTableInit(0, false, [0], true);
|
||||
return new WebAssembly.Module(builder.toBuffer());
|
||||
}
|
||||
|
||||
var instances = [], modules = [];
|
||||
modules[0] = CallModuleBuilder();
|
||||
modules[1] = CallModuleBuilder();
|
||||
|
||||
// Modules[0] shared by instances[0..2], modules[1] shared by instances[3, 4]
|
||||
instances[0] = new WebAssembly.Instance(modules[0], {x: {table:table}});
|
||||
instances[1] = new WebAssembly.Instance(modules[0], {x: {table:table}});
|
||||
instances[2] = new WebAssembly.Instance(modules[0], {x: {table:table}});
|
||||
instances[3] = new WebAssembly.Instance(modules[1], {x: {table:table}});
|
||||
instances[4] = new WebAssembly.Instance(modules[1], {x: {table:table}});
|
||||
|
||||
function VerifyTableBoundsCheck(size) {
|
||||
print("Verifying bounds for size = " + size);
|
||||
assertEquals(size, table.length);
|
||||
for (let i = 0; i < 5; i++) {
|
||||
// Sanity check for indirect call
|
||||
assertEquals(10, instances[i].exports.main(0));
|
||||
// Bounds check at different out of bounds indices
|
||||
assertInvalidFunction = function(s) {
|
||||
assertThrows(
|
||||
() => instances[i].exports.main(s), WebAssembly.RuntimeError,
|
||||
/invalid function/);
|
||||
}
|
||||
assertInvalidFunction(size);
|
||||
assertInvalidFunction(size + 1);
|
||||
assertInvalidFunction(size + 1000);
|
||||
assertInvalidFunction(2 * size);
|
||||
}
|
||||
}
|
||||
|
||||
for (let i = 0; i < 4; i++) {
|
||||
VerifyTableBoundsCheck(99900 * i + 1);
|
||||
table.grow(99900);
|
||||
}
|
||||
})();
|
@ -156,7 +156,8 @@ class WasmModuleBuilder {
|
||||
this.exceptions = [];
|
||||
this.functions = [];
|
||||
this.function_table = [];
|
||||
this.function_table_length = 0;
|
||||
this.function_table_length_min = 0;
|
||||
this.function_table_length_max = 0;
|
||||
this.function_table_inits = [];
|
||||
this.segments = [];
|
||||
this.explicit = [];
|
||||
@ -276,8 +277,11 @@ class WasmModuleBuilder {
|
||||
array: array});
|
||||
if (!is_global) {
|
||||
var length = base + array.length;
|
||||
if (length > this.function_table_length && !is_import) {
|
||||
this.function_table_length = length;
|
||||
if (length > this.function_table_length_min && !is_import) {
|
||||
this.function_table_length_min = length;
|
||||
}
|
||||
if (length > this.function_table_length_max && !is_import) {
|
||||
this.function_table_length_max = length;
|
||||
}
|
||||
}
|
||||
return this;
|
||||
@ -291,8 +295,9 @@ class WasmModuleBuilder {
|
||||
return this.addFunctionTableInit(this.function_table.length, false, array);
|
||||
}
|
||||
|
||||
setFunctionTableLength(length) {
|
||||
this.function_table_length = length;
|
||||
setFunctionTableBounds(min, max) {
|
||||
this.function_table_length_min = min;
|
||||
this.function_table_length_max = max;
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -371,14 +376,16 @@ class WasmModuleBuilder {
|
||||
}
|
||||
|
||||
// Add function_table.
|
||||
if (wasm.function_table_length > 0) {
|
||||
if (wasm.function_table_length_min > 0) {
|
||||
if (debug) print("emitting table @ " + binary.length);
|
||||
binary.emit_section(kTableSectionCode, section => {
|
||||
section.emit_u8(1); // one table entry
|
||||
section.emit_u8(kWasmAnyFunctionTypeForm);
|
||||
section.emit_u8(1);
|
||||
section.emit_u32v(wasm.function_table_length);
|
||||
section.emit_u32v(wasm.function_table_length);
|
||||
// TODO(gdeepti): Cleanup to use optional max flag,
|
||||
// fix up tests to set correct initial/maximum values
|
||||
section.emit_u32v(1);
|
||||
section.emit_u32v(wasm.function_table_length_min);
|
||||
section.emit_u32v(wasm.function_table_length_max);
|
||||
});
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user