Commit 2af2d88b authored by Michael Starzinger's avatar Michael Starzinger Committed by Commit Bot

[wasm] Fix interpreter entry with shared code.

This makes sure that debug info and interpreter handle are created
lazily, even when interpretation is triggered by a different Isolate
sharing the same WasmEngine (and hence the native module).

R=titzer@chromium.org
TEST=mjsunit/wasm/worker-interpreter
BUG=v8:7424

Change-Id: Iba17e207a537007fd2e642cede22dad7a708c6c7
Reviewed-on: https://chromium-review.googlesource.com/1181045
Commit-Queue: Michael Starzinger <mstarzinger@chromium.org>
Reviewed-by: 's avatarBen Titzer <titzer@chromium.org>
Cr-Commit-Position: refs/heads/master@{#55220}
parent 28cde914
......@@ -263,8 +263,13 @@ RUNTIME_FUNCTION(Runtime_WasmRunInterpreter) {
frame_pointer = it.frame()->fp();
}
bool success = instance->debug_info()->RunInterpreter(frame_pointer,
func_index, arg_buffer);
// Run the function in the interpreter. Note that neither the {WasmDebugInfo}
// nor the {InterpreterHandle} have to exist, because interpretation might
// have been triggered by another Isolate sharing the same WasmEngine.
Handle<WasmDebugInfo> debug_info =
WasmInstanceObject::GetOrCreateDebugInfo(instance);
bool success = WasmDebugInfo::RunInterpreter(
isolate, debug_info, frame_pointer, func_index, arg_buffer);
if (!success) {
DCHECK(isolate->has_pending_exception());
......
......@@ -643,13 +643,16 @@ void WasmDebugInfo::PrepareStep(StepAction step_action) {
GetInterpreterHandle(this)->PrepareStep(step_action);
}
bool WasmDebugInfo::RunInterpreter(Address frame_pointer, int func_index,
// static
bool WasmDebugInfo::RunInterpreter(Isolate* isolate,
Handle<WasmDebugInfo> debug_info,
Address frame_pointer, int func_index,
Address arg_buffer) {
DCHECK_LE(0, func_index);
Handle<WasmInstanceObject> instance(wasm_instance(),
wasm_instance()->GetIsolate());
return GetInterpreterHandle(this)->Execute(
instance, frame_pointer, static_cast<uint32_t>(func_index), arg_buffer);
auto* handle = GetOrCreateInterpreterHandle(isolate, debug_info);
Handle<WasmInstanceObject> instance(debug_info->wasm_instance(), isolate);
return handle->Execute(instance, frame_pointer,
static_cast<uint32_t>(func_index), arg_buffer);
}
std::vector<std::pair<uint32_t, int>> WasmDebugInfo::GetInterpretedStack(
......
......@@ -577,8 +577,9 @@ class WasmDebugInfo : public Struct, public NeverReadOnlySpaceObject {
// interpreter for unwinding and frame inspection.
// Returns true if exited regularly, false if a trap occurred. In the latter
// case, a pending exception will have been set on the isolate.
bool RunInterpreter(Address frame_pointer, int func_index,
Address arg_buffer);
static bool RunInterpreter(Isolate* isolate, Handle<WasmDebugInfo>,
Address frame_pointer, int func_index,
Address arg_buffer);
// Get the stack of the wasm interpreter as pairs of <function index, byte
// offset>. The list is ordered bottom-to-top, i.e. caller before callee.
......
// 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: --allow-natives-syntax --no-wasm-disable-structured-cloning
load("test/mjsunit/wasm/wasm-constants.js");
load("test/mjsunit/wasm/wasm-module-builder.js");
(function TestPostInterpretedModule() {
let builder = new WasmModuleBuilder();
let add = builder.addFunction("add", kSig_i_ii)
.addBody([kExprGetLocal, 0, kExprGetLocal, 1, kExprI32Add])
.exportFunc();
let module = builder.toModule();
let instance = new WebAssembly.Instance(module);
let exp = instance.exports;
let workerScript = `
var instance = null;
onmessage = function(message) {
try {
if (message.command == 'module') {
instance = new WebAssembly.Instance(message.module);
postMessage('OK');
}
if (message.command == 'call') {
let result = instance.exports.add(40, 2);
postMessage(result);
}
} catch(e) {
postMessage('ERROR: ' + e);
}
}
`;
let worker = new Worker(workerScript);
// Call method without using the interpreter.
var initial_interpreted = %WasmNumInterpretedCalls(instance);
assertEquals(23, exp.add(20, 3));
assertEquals(initial_interpreted + 0, %WasmNumInterpretedCalls(instance));
// Send module to the worker, still not interpreting.
worker.postMessage({ command:'module', module:module });
assertEquals('OK', worker.getMessage());
worker.postMessage({ command:'call' });
assertEquals(42, worker.getMessage());
assertEquals(initial_interpreted + 0, %WasmNumInterpretedCalls(instance));
// Switch to the interpreter and call method.
%RedirectToWasmInterpreter(instance, add.index);
assertEquals(23, exp.add(20, 3));
assertEquals(initial_interpreted + 1, %WasmNumInterpretedCalls(instance));
// Let worker call interpreted function.
worker.postMessage({ command:'call' });
assertEquals(42, worker.getMessage());
assertEquals(initial_interpreted + 1, %WasmNumInterpretedCalls(instance));
// All done.
worker.terminate();
})();
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