Commit ffc75252 authored by Frederik Gossen's avatar Frederik Gossen Committed by Commit Bot

[wasm-hints] Fix lazy compilation and validation in interpreter

The interpreter accesses code directly from the code manager. With lazy
validation, however, this code is not guaranteed to exist. The
interpreter now checks for this and compiles it lazily if needed. It
also handles exceptions that may arise from lazy validation.

Bug: v8:9003
Change-Id: I37c365f0a4d755ed55630d01c8526f2a3efa9a9e
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1594567Reviewed-by: 's avatarClemens Hammacher <clemensh@chromium.org>
Reviewed-by: 's avatarMichael Starzinger <mstarzinger@chromium.org>
Commit-Queue: Frederik Gossen <frgossen@google.com>
Cr-Commit-Position: refs/heads/master@{#61240}
parent a0fd7918
......@@ -20,6 +20,7 @@
#include "src/wasm/function-body-decoder-impl.h"
#include "src/wasm/function-body-decoder.h"
#include "src/wasm/memory-tracing.h"
#include "src/wasm/module-compiler.h"
#include "src/wasm/wasm-engine.h"
#include "src/wasm/wasm-external-refs.h"
#include "src/wasm/wasm-limits.h"
......@@ -3612,12 +3613,21 @@ class ThreadImpl {
return {ExternalCallResult::EXTERNAL_RETURNED};
}
static WasmCode* GetTargetCode(WasmCodeManager* code_manager,
Address target) {
static WasmCode* GetTargetCode(Isolate* isolate, Address target) {
WasmCodeManager* code_manager = isolate->wasm_engine()->code_manager();
NativeModule* native_module = code_manager->LookupNativeModule(target);
if (native_module->is_jump_table_slot(target)) {
uint32_t func_index =
native_module->GetFunctionIndexFromJumpTableSlot(target);
if (!native_module->HasCode(func_index)) {
bool success = CompileLazy(isolate, native_module, func_index);
if (!success) {
DCHECK(isolate->has_pending_exception());
return nullptr;
}
}
return native_module->GetCode(func_index);
}
WasmCode* code = native_module->Lookup(target);
......@@ -3631,8 +3641,12 @@ class ThreadImpl {
ImportedFunctionEntry entry(instance_object_, function_index);
Handle<Object> object_ref(entry.object_ref(), isolate_);
WasmCode* code =
GetTargetCode(isolate_->wasm_engine()->code_manager(), entry.target());
WasmCode* code = GetTargetCode(isolate_, entry.target());
// In case a function's body is invalid and the function is lazily validated
// and compiled we may get an exception.
if (code == nullptr) return TryHandleException(isolate_);
FunctionSig* sig = module()->functions[function_index].sig;
return CallExternalWasmFunction(isolate_, object_ref, code, sig);
}
......@@ -3661,8 +3675,11 @@ class ThreadImpl {
HandleScope handle_scope(isolate_); // Avoid leaking handles.
FunctionSig* signature = module()->signatures[sig_index];
Handle<Object> object_ref = handle(entry.object_ref(), isolate_);
WasmCode* code =
GetTargetCode(isolate_->wasm_engine()->code_manager(), entry.target());
WasmCode* code = GetTargetCode(isolate_, entry.target());
// In case a function's body is invalid and the function is lazily validated
// and compiled we may get an exception.
if (code == nullptr) return TryHandleException(isolate_);
if (!object_ref->IsWasmInstanceObject() || /* call to an import */
!instance_object_.is_identical_to(object_ref) /* cross-instance */) {
......
// 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: --experimental-wasm-compilation-hints --wasm-lazy-validation
load('test/mjsunit/wasm/wasm-module-builder.js');
(function testInterpreterCallsLazyFunctionInOtherInstance() {
print(arguments.callee.name);
let builder0 = new WasmModuleBuilder();
builder0.addFunction("getX", kSig_i_v)
.addBody([kExprI32Const, 42])
.setCompilationHint(kCompilationHintStrategyLazy,
kCompilationHintTierBaseline,
kCompilationHintTierBaseline)
.exportFunc();
let builder1 = new WasmModuleBuilder();
builder1.addImport("otherModule", "getX", kSig_i_v);
builder1.addFunction("plusX", kSig_i_i)
.addBody([kExprCallFunction, 0,
kExprGetLocal, 0,
kExprI32Add])
.setCompilationHint(kCompilationHintStrategyLazy,
kCompilationHintTierInterpreter,
kCompilationHintTierInterpreter)
.exportFunc();
let instance0 = builder0.instantiate();
let instance1 = builder1.instantiate(
{otherModule: {getX: instance0.exports.getX}});
assertEquals(46, instance1.exports.plusX(4));
})();
(function testInterpreterCallsLazyBadFunctionInOtherInstance() {
print(arguments.callee.name);
let builder0 = new WasmModuleBuilder();
builder0.addFunction("getX", kSig_i_v)
.addBody([kExprI64Const, 42])
.setCompilationHint(kCompilationHintStrategyLazy,
kCompilationHintTierBaseline,
kCompilationHintTierBaseline)
.exportFunc();
let builder1 = new WasmModuleBuilder();
builder1.addImport("otherModule", "getX", kSig_i_v);
builder1.addFunction("plusX", kSig_i_i)
.addBody([kExprCallFunction, 0,
kExprGetLocal, 0,
kExprI32Add])
.setCompilationHint(kCompilationHintStrategyLazy,
kCompilationHintTierInterpreter,
kCompilationHintTierInterpreter)
.exportFunc();
let instance0 = builder0.instantiate();
let instance1 = builder1.instantiate(
{otherModule: {getX: instance0.exports.getX}});
assertThrows(() => instance1.exports.plusX(4),
WebAssembly.CompileError,
"Compiling function #0:\"getX\" failed: type error in " +
"merge[0] (expected i32, got i64) @+57");
})();
(function testInterpreterCallsLazyFunctionThroughIndirection() {
print(arguments.callee.name);
let builder = new WasmModuleBuilder();
let sig_i_ii = builder.addType(kSig_i_ii);
let add = builder.addFunction('add', sig_i_ii)
.addBody([kExprGetLocal, 0,
kExprGetLocal, 1,
kExprI32Add])
.setCompilationHint(kCompilationHintStrategyLazy,
kCompilationHintTierInterpreter,
kCompilationHintTierInterpreter);
builder.appendToTable([add.index]);
builder.addFunction('main', kSig_i_iii)
.addBody([// Call indirect #0 with args <#1, #2>.
kExprGetLocal, 1,
kExprGetLocal, 2,
kExprGetLocal, 0,
kExprCallIndirect, sig_i_ii, kTableZero])
.setCompilationHint(kCompilationHintStrategyLazy,
kCompilationHintTierInterpreter,
kCompilationHintTierInterpreter)
.exportFunc();
assertEquals(99, builder.instantiate().exports.main(0, 22, 77));
})();
(function testInterpreterCallsLazyBadFunctionThroughIndirection() {
print(arguments.callee.name);
let builder = new WasmModuleBuilder();
let sig_i_ii = builder.addType(kSig_i_ii);
let add = builder.addFunction('add', sig_i_ii)
.addBody([kExprGetLocal, 0,
kExprGetLocal, 1,
kExprI64Add])
.setCompilationHint(kCompilationHintStrategyLazy,
kCompilationHintTierInterpreter,
kCompilationHintTierInterpreter);
builder.appendToTable([add.index]);
builder.addFunction('main', kSig_i_iii)
.addBody([// Call indirect #0 with args <#1, #2>.
kExprGetLocal, 1,
kExprGetLocal, 2,
kExprGetLocal, 0,
kExprCallIndirect, sig_i_ii, kTableZero])
.setCompilationHint(kCompilationHintStrategyLazy,
kCompilationHintTierInterpreter,
kCompilationHintTierInterpreter)
.exportFunc();
assertThrows(() => builder.instantiate().exports.main(0, 22, 77),
WebAssembly.CompileError,
"Compiling function #0:\"add\" failed: i64.add[1] expected " +
"type i64, found get_local of type i32 @+83");
})();
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