Skip to content

Commit

Permalink
deps: V8: backport 442977e
Browse files Browse the repository at this point in the history
Original commit message:

  Merged: [wasm] Fix dispatch table instance update

  This CL fixes a bug where the receiving instance was updated improperly
  in the dispatch table(s) of an imported table.

  BUG=chromium:875322
  R=​mstarzinger@chromium.org
  CC=titzer@chromium.org

  Change-Id: Iff24953a1fb6a8ab794e12a7a976d544b56fc3c2
  Originally-reviewed-on: https://chromium-review.googlesource.com/1196886
  No-Try: true
  No-Presubmit: true
  No-Treechecks: true
  Reviewed-on: https://chromium-review.googlesource.com/1212922
  Reviewed-by: Michael Starzinger <mstarzinger@chromium.org>
  Commit-Queue: Clemens Hammacher <clemensh@chromium.org>
  Cr-Commit-Position: refs/branch-heads/6.9@{nodejs#45}
  Cr-Branched-From: d7b61abe7b48928aed739f02bf7695732d359e7e-refs/heads/6.9.427@{#1}
  Cr-Branched-From: b7e108d6016bf6b7de3a34e6d61cb522f5193460-refs/heads/master@{nodejs#54504}

Refs: v8/v8@442977e

PR-URL: nodejs#25242
Reviewed-By: Michaël Zasso <targos@protonmail.com>
  • Loading branch information
ofrobots authored and rvagg committed Feb 28, 2019
1 parent f9fc1ea commit fa12b24
Show file tree
Hide file tree
Showing 3 changed files with 252 additions and 9 deletions.
2 changes: 1 addition & 1 deletion common.gypi
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@

# Reset this number to 0 on major V8 upgrades.
# Increment by one for each non-official patch applied to deps/v8.
'v8_embedder_string': '-node.12',
'v8_embedder_string': '-node.48',

# Enable disassembler for `--print-code` v8 options
'v8_enable_disassembler': 1,
Expand Down
15 changes: 7 additions & 8 deletions deps/v8/src/wasm/module-compiler.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2653,20 +2653,20 @@ void InstanceBuilder::LoadTableSegments(Handle<WasmInstanceObject> instance) {

// Update the local dispatch table first.
uint32_t sig_id = module_->signature_ids[function->sig_index];
WasmInstanceObject* target_instance = *instance;
Handle<WasmInstanceObject> target_instance = instance;
Address call_target;
const bool is_import = func_index < module_->num_imported_functions;
if (is_import) {
// For imported calls, take target instance and address from the
// import table.
ImportedFunctionEntry entry(instance, func_index);
target_instance = entry.instance();
target_instance = handle(entry.instance(), isolate_);
call_target = entry.target();
} else {
call_target = native_module->GetCallTargetForFunction(func_index);
}
IndirectFunctionTableEntry(instance, table_index)
.set(sig_id, target_instance, call_target);
.set(sig_id, *target_instance, call_target);

if (!table_instance.table_object.is_null()) {
// Update the table object's other dispatch tables.
Expand Down Expand Up @@ -2700,17 +2700,16 @@ void InstanceBuilder::LoadTableSegments(Handle<WasmInstanceObject> instance) {
}
table_instance.js_wrappers->set(table_index,
*js_wrappers_[func_index]);
// UpdateDispatchTables() should update this instance as well.
// UpdateDispatchTables() updates all other dispatch tables, since
// we have not yet added the dispatch table we are currently building.
WasmTableObject::UpdateDispatchTables(
isolate_, table_instance.table_object, table_index, function->sig,
instance, call_target);
target_instance, call_target);
}
}
}

// TODO(titzer): we add the new dispatch table at the end to avoid
// redundant work and also because the new instance is not yet fully
// initialized.
// Add the new dispatch table at the end to avoid redundant lookups.
if (!table_instance.table_object.is_null()) {
// Add the new dispatch table to the WebAssembly.Table object.
WasmTableObject::AddDispatchTable(isolate_, table_instance.table_object,
Expand Down
244 changes: 244 additions & 0 deletions deps/v8/test/mjsunit/wasm/import-table.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,244 @@
// Copyright 2018 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

load("test/mjsunit/wasm/wasm-constants.js");
load("test/mjsunit/wasm/wasm-module-builder.js");

function addConstFunc(builder, val) {
return builder.addFunction("const" + val, kSig_i_v)
.addBody(wasmI32Const(val)).index;
}

function addSigs(builder, pad) {
for (let i = 0; i < pad; i++) {
let params = [];
for (let j = 0; j < i; j++) params.push(kWasmF32);
builder.addType(makeSig(params, []));
}

return { i_v: builder.addType(kSig_i_v) };
}

let kTableSize = 50;

(function TestAliasedImportedTable() {
print(arguments.callee.name);

{
let builder = new WasmModuleBuilder();
let signums = addSigs(builder, 1);

builder.addImportedTable("m", "table", kTableSize, kTableSize);
let f15 = addConstFunc(builder, 15);
let call = builder.addFunction("call", kSig_i_i)
.addBody([
kExprGetLocal, 0,
kExprCallIndirect, signums.i_v, kTableZero
])
.exportAs("call");
let f17 = addConstFunc(builder, 17);
builder.addExport("f15", f15);
builder.addExport("f17", f17);
builder.addFunctionTableInit(15, false, [f15], true);
builder.addFunctionTableInit(1, false, [call.index], true);

var mod1 = builder.toModule();
}

{
let builder = new WasmModuleBuilder();
let signums = addSigs(builder, 5); // ensure different sigids

builder.addImportedTable("m", "table", kTableSize, kTableSize);
let f15 = builder.addImport("m", "f15", kSig_i_v);
let f17 = builder.addImport("m", "f17", kSig_i_v);
let f21 = addConstFunc(builder, 21);
let call = builder.addFunction("call", kSig_i_i)
.addBody([
kExprGetLocal, 0,
kExprCallIndirect, signums.i_v, kTableZero
])
.exportAs("call");
let f26 = addConstFunc(builder, 26);
builder.addFunctionTableInit(17, false, [f17], true);
builder.addFunctionTableInit(21, false, [f21], true);
builder.addFunctionTableInit(26, false, [f26], true);
builder.addFunctionTableInit(5, false, [call.index], true);

var mod2 = builder.toModule();
}

var table = new WebAssembly.Table({initial: kTableSize,
maximum: kTableSize, element: "anyfunc"});
var i1 = new WebAssembly.Instance(mod1, {m: {table: table}});

var i2 = new WebAssembly.Instance(mod2,
{m: {table: table, f15: i1.exports.f15, f17: i1.exports.f17}});

for (i of [15, 17, 21, 26]) {
print(i);
assertEquals(i, i1.exports.call(i));
assertEquals(i, i2.exports.call(i));
}
for (i of [0, 1, 5, 16]) {
assertThrows(() => i1.exports.call(i));
assertThrows(() => i2.exports.call(i));
}
})();

function addConstFuncUsingGlobal(builder, val) {
let g = builder.addGlobal(kWasmI32, false);
g.init = val;
return builder.addFunction("global" + val, kSig_i_v)
.addBody([kExprGetGlobal, g.index]).index;
}

(function TestAliasedImportedTableInstanceGlobals() {
print(arguments.callee.name);

{
let builder = new WasmModuleBuilder();
let signums = addSigs(builder, 1);

builder.addImportedTable("m", "table", kTableSize, kTableSize);
let f14 = addConstFuncUsingGlobal(builder, 14);
let call = builder.addFunction("call", kSig_i_i)
.addBody([
kExprGetLocal, 0,
kExprCallIndirect, signums.i_v, kTableZero
])
.exportAs("call");
let f18 = addConstFuncUsingGlobal(builder, 18);
builder.addExport("f14", f14);
builder.addExport("f18", f18);
builder.addFunctionTableInit(14, false, [f14], true);
builder.addFunctionTableInit(1, false, [call.index], true);

var mod1 = builder.toModule();
}

{
let builder = new WasmModuleBuilder();
let signums = addSigs(builder, 3); // ensure different sigids

builder.addImportedTable("m", "table", kTableSize, kTableSize);
let f14 = builder.addImport("m", "f14", kSig_i_v);
let f18 = builder.addImport("m", "f18", kSig_i_v);
let f22 = addConstFuncUsingGlobal(builder, 22);
let call = builder.addFunction("call", kSig_i_i)
.addBody([
kExprGetLocal, 0,
kExprCallIndirect, signums.i_v, kTableZero
])
.exportAs("call");
let f28 = addConstFuncUsingGlobal(builder, 28);
builder.addFunctionTableInit(18, false, [f18], true);
builder.addFunctionTableInit(22, false, [f22], true);
builder.addFunctionTableInit(28, false, [f28], true);
builder.addFunctionTableInit(5, false, [call.index], true);

var mod2 = builder.toModule();
}

var table = new WebAssembly.Table({initial: kTableSize,
maximum: kTableSize, element: "anyfunc"});
var i1 = new WebAssembly.Instance(mod1, {m: {table: table}});

var i2 = new WebAssembly.Instance(mod2,
{m: {table: table, f14: i1.exports.f14, f18: i1.exports.f18}});

for (i of [14, 18, 22, 28]) {
print(i);
assertEquals(i, i1.exports.call(i));
assertEquals(i, i2.exports.call(i));
}
for (i of [0, 1, 5, 16]) {
assertThrows(() => i1.exports.call(i));
assertThrows(() => i2.exports.call(i));
}
})();


function addConstFuncUsingMemory(builder, val) {
var addr = builder.address;
builder.address += 8;
var bytes = [val & 0xff, (val>>8) & 0xff, (val>>16) & 0xff, (val>>24) & 0xff];
builder.addDataSegment(addr, bytes);
return builder.addFunction("mem" + val, kSig_i_v)
.addBody([
...wasmI32Const(addr),
kExprI32LoadMem, 0, 0
]).index;
}

(function TestAliasedImportedTableInstanceMemories() {
print(arguments.callee.name);

{
let builder = new WasmModuleBuilder();
builder.address = 8;
let signums = addSigs(builder, 1);

builder.addMemory(1, 1, false);
builder.addImportedTable("m", "table", kTableSize, kTableSize);
let f13 = addConstFuncUsingMemory(builder, 13);
let call = builder.addFunction("call", kSig_i_i)
.addBody([
kExprGetLocal, 0,
kExprCallIndirect, signums.i_v, kTableZero
])
.exportAs("call");
let f19 = addConstFuncUsingMemory(builder, 19);
builder.addExport("f13", f13);
builder.addExport("f19", f19);
builder.addFunctionTableInit(13, false, [f13], true);
builder.addFunctionTableInit(1, false, [call.index], true);

var mod1 = builder.toModule();
}

{
let builder = new WasmModuleBuilder();
builder.address = 8;
let signums = addSigs(builder, 4); // ensure different sigids

builder.addMemory(1, 1, false);
builder.addImportedTable("m", "table", kTableSize, kTableSize);
let f13 = builder.addImport("m", "f13", kSig_i_v);
let f19 = builder.addImport("m", "f19", kSig_i_v);
let f23 = addConstFuncUsingMemory(builder, 23);
let call = builder.addFunction("call", kSig_i_i)
.addBody([
kExprGetLocal, 0,
kExprCallIndirect, signums.i_v, kTableZero
])
.exportAs("call");
let f29 = addConstFuncUsingMemory(builder, 29);
builder.addFunctionTableInit(19, false, [f19], true);
builder.addFunctionTableInit(23, false, [f23], true);
builder.addFunctionTableInit(29, false, [f29], true);
builder.addFunctionTableInit(5, false, [call.index], true);

var mod2 = builder.toModule();
}

var table = new WebAssembly.Table({initial: kTableSize,
maximum: kTableSize, element: "anyfunc"});
var i1 = new WebAssembly.Instance(mod1, {m: {table: table}});

var i2 = new WebAssembly.Instance(mod2,
{m: {table: table, f13: i1.exports.f13, f19: i1.exports.f19}});

for (i of [13, 19, 23, 29]) {
print(i);
assertEquals(i, i1.exports.call(i));
assertEquals(i, i2.exports.call(i));
}
for (i of [0, 1, 5, 16]) {
assertThrows(() => i1.exports.call(i));
assertThrows(() => i2.exports.call(i));
}
})();

0 comments on commit fa12b24

Please sign in to comment.