Commit 903d8731 authored by Ben L. Titzer's avatar Ben L. Titzer Committed by Commit Bot

[wasm] Fix target instance for indirect calls to imports

In the case of an indirect call to an imported function, the target
instance stored in the IFT was actually wrong.

Bug: chromium:834619
Change-Id: Id2ac4158335ecf2b58e1983ce37df852a9ebd1b2
Reviewed-on: https://chromium-review.googlesource.com/1030174
Commit-Queue: Ben Titzer <titzer@chromium.org>
Reviewed-by: 's avatarClemens Hammacher <clemensh@chromium.org>
Cr-Commit-Position: refs/heads/master@{#52831}
parent 006f3f56
......@@ -50,6 +50,8 @@ WasmCompilationUnit::WasmCompilationUnit(Isolate* isolate, ModuleEnv* env,
native_module_(native_module),
lower_simd_(lower_simd),
mode_(mode) {
DCHECK_GE(index, env->module->num_imported_functions);
DCHECK_LT(index, env->module->functions.size());
SwitchMode(mode);
}
......
......@@ -2706,8 +2706,16 @@ void InstanceBuilder::LoadTableSegments(Handle<WasmInstanceObject> instance) {
wasm::WasmCode* wasm_code =
native_module->GetIndirectlyCallableCode(func_index);
IndirectFunctionTableEntry(*instance, table_index)
.set(sig_id, *instance, wasm_code);
if (func_index < module_->num_imported_functions) {
// Imported functions have the target instance put into the IFT.
WasmInstanceObject* target_instance =
ImportedFunctionEntry(*instance, func_index).instance();
IndirectFunctionTableEntry(*instance, table_index)
.set(sig_id, target_instance, wasm_code);
} else {
IndirectFunctionTableEntry(*instance, table_index)
.set(sig_id, *instance, wasm_code);
}
if (!table_instance.table_object.is_null()) {
// Update the table object's other dispatch tables.
......
......@@ -858,8 +858,17 @@ WasmCode* NativeModule::GetIndirectlyCallableCode(uint32_t func_index) {
if (!code || code->kind() != WasmCode::kLazyStub) {
return code;
}
#if DEBUG
auto num_imported_functions =
compiled_module()->shared()->module()->num_imported_functions;
if (func_index < num_imported_functions) {
DCHECK(!code->IsAnonymous());
}
#endif
if (!code->IsAnonymous()) {
DCHECK_EQ(func_index, code->index());
// If the function wasn't imported, its index should match.
DCHECK_IMPLIES(func_index >= num_imported_functions,
func_index == code->index());
return code;
}
if (!lazy_compile_stubs_.get()) {
......
// 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: --wasm-lazy-compilation
load("test/mjsunit/wasm/wasm-constants.js");
load("test/mjsunit/wasm/wasm-module-builder.js");
(function ExportedFunctionsImportedOrder() {
print(arguments.callee.name);
let i1 = (() => {
let builder = new WasmModuleBuilder();
builder.addFunction("f1", kSig_i_v)
.addBody(
[kExprI32Const, 1])
.exportFunc();
builder.addFunction("f2", kSig_i_v)
.addBody(
[kExprI32Const, 2])
.exportFunc();
return builder.instantiate();
})();
let i2 = (() => {
let builder = new WasmModuleBuilder();
builder.addImport("q", "f2", kSig_i_v);
builder.addImport("q", "f1", kSig_i_v);
builder.addFunction("main", kSig_i_i)
.addBody([
kExprGetLocal, 0,
kExprCallIndirect, 0, kTableZero
])
.exportFunc();
builder.addFunctionTableInit(0, false, [0, 1, 1, 0]);
return builder.instantiate({q: {f2: i1.exports.f2, f1: i1.exports.f1}});
})();
print("--->calling 0");
assertEquals(2, i2.exports.main(0));
print("--->calling 1");
assertEquals(1, i2.exports.main(1));
print("--->calling 2");
assertEquals(1, i2.exports.main(2));
print("--->calling 3");
assertEquals(2, i2.exports.main(3));
})();
......@@ -797,3 +797,105 @@ function js_div(a, b) { return (a / b) | 0; }
assertThrows(() => {instance.exports.main(j, i+2)});
}
})();
(function ExportedFunctionsImportedOrder() {
print(arguments.callee.name);
let i1 = (() => {
let builder = new WasmModuleBuilder();
builder.addFunction("f1", kSig_i_v)
.addBody(
[kExprI32Const, 1])
.exportFunc();
builder.addFunction("f2", kSig_i_v)
.addBody(
[kExprI32Const, 2])
.exportFunc();
return builder.instantiate();
})();
let i2 = (() => {
let builder = new WasmModuleBuilder();
builder.addImport("q", "f2", kSig_i_v);
builder.addImport("q", "f1", kSig_i_v);
builder.addFunction("main", kSig_i_i)
.addBody([
kExprGetLocal, 0,
kExprCallIndirect, 0, kTableZero
])
.exportFunc();
builder.addFunctionTableInit(0, false, [0, 1, 1, 0]);
return builder.instantiate({q: {f2: i1.exports.f2, f1: i1.exports.f1}});
})();
assertEquals(2, i2.exports.main(0));
assertEquals(1, i2.exports.main(1));
assertEquals(1, i2.exports.main(2));
assertEquals(2, i2.exports.main(3));
})();
(function IndirectCallsToImportedFunctions() {
print(arguments.callee.name);
let module = (() => {
let builder = new WasmModuleBuilder();
builder.addMemory(1, 1, false);
builder.addFunction("f", kSig_i_v)
.addBody([
kExprI32Const, 0,
kExprI32LoadMem, 0, 4,
])
.exportFunc();
builder.exportMemoryAs("memory");
return new WebAssembly.Module(builder.toBuffer());
})();
function setMemI32(instance, offset, val) {
var array = new Int32Array(instance.exports.memory.buffer);
array[offset/4] = val;
}
function makeFun(val) {
let instance = new WebAssembly.Instance(module);
setMemI32(instance, 0, 2000000);
setMemI32(instance, 4, val);
setMemI32(instance, 8, 3000000);
return instance.exports.f;
}
let f300 = makeFun(300);
let f100 = makeFun(100);
let f200 = makeFun(200);
let main = (() => {
let builder = new WasmModuleBuilder();
builder.addMemory(1, 1, false);
builder.addImport("q", "f1", kSig_i_v);
builder.addImport("q", "f2", kSig_i_v);
builder.addImport("q", "f3", kSig_i_v);
builder.addFunction("f", kSig_i_v)
.addBody([
kExprI32Const, 8,
kExprI32LoadMem, 0, 0,
]);
builder.addFunction("main", kSig_i_i)
.addBody([
kExprGetLocal, 0,
kExprCallIndirect, 0, kTableZero
])
.exportFunc();
builder.exportMemoryAs("memory");
builder.addFunctionTableInit(0, false, [0, 1, 2, 3]);
var instance = builder.instantiate({q: {f1: f100, f2: f200, f3: f300}});
setMemI32(instance, 0, 5000000);
setMemI32(instance, 4, 6000000);
setMemI32(instance, 8, 400);
return instance.exports.main;
})();
assertEquals(100, main(0));
assertEquals(200, main(1));
assertEquals(300, main(2));
assertEquals(400, main(3));
})();
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment