Commit ae3f94bd authored by Philip Pfaffe's avatar Philip Pfaffe Committed by Commit Bot

Expose a proxy object to evaluateOnCallFrame for WebAssembly

When debugging WebAssembly, calls to evaluateOnCallFrame always return
undefined. This CL enables evaluateOnCallFrame for WebAssembly and
creates a proxy object that is injected into the evaluation context.

Bug: chromium:1127914
Change-Id: I3f5cff3be2c9de45c7b1f3f7ed4fc2e1cc545ac6
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2429265
Commit-Queue: Philip Pfaffe <pfaffe@chromium.org>
Reviewed-by: 's avatarClemens Backes <clemensb@chromium.org>
Reviewed-by: 's avatarBenedikt Meurer <bmeurer@chromium.org>
Reviewed-by: 's avatarSimon Zünd <szuend@chromium.org>
Cr-Commit-Position: refs/heads/master@{#70315}
parent a5024f9b
......@@ -18,6 +18,7 @@
#include "src/objects/contexts.h"
#include "src/snapshot/snapshot.h"
#include "src/wasm/wasm-debug.h"
#include "src/wasm/wasm-js.h"
namespace v8 {
namespace internal {
......@@ -106,6 +107,9 @@ V8_EXPORT MaybeHandle<Object> DebugEvaluate::WebAssembly(
StackTraceFrameIterator it(isolate, frame_id);
if (!it.is_wasm()) return isolate->factory()->undefined_value();
WasmFrame* frame = WasmFrame::cast(it.frame());
Handle<JSProxy> context_extension = WasmJs::GetJSDebugProxy(frame);
DisableBreak disable_break_scope(isolate->debug(), /*disable=*/true);
......@@ -114,12 +118,14 @@ V8_EXPORT MaybeHandle<Object> DebugEvaluate::WebAssembly(
return {};
}
Handle<Context> context = isolate->native_context();
Handle<JSObject> receiver(context->global_proxy(), isolate);
Handle<ScopeInfo> scope_info =
ScopeInfo::CreateForWithScope(isolate, Handle<ScopeInfo>::null());
Handle<Context> context = isolate->factory()->NewWithContext(
isolate->native_context(), scope_info, context_extension);
Handle<Object> result;
if (!DebugEvaluate::Evaluate(isolate, shared_info, context, receiver, source,
throw_on_side_effect)
if (!DebugEvaluate::Evaluate(isolate, shared_info, context, context_extension,
source, throw_on_side_effect)
.ToHandle(&result)) {
return {};
}
......
......@@ -340,6 +340,12 @@ class DebugInfoImpl {
debug_break_fp);
}
const WasmFunction& GetFunctionAtAddress(Address pc) {
FrameInspectionScope scope(this, pc);
auto* module = native_module_->module();
return module->functions[scope.code->index()];
}
Handle<JSObject> GetLocalScopeObject(Isolate* isolate, Address pc, Address fp,
Address debug_break_fp) {
FrameInspectionScope scope(this, pc);
......@@ -909,6 +915,10 @@ WasmValue DebugInfo::GetStackValue(int index, Address pc, Address fp,
return impl_->GetStackValue(index, pc, fp, debug_break_fp);
}
const wasm::WasmFunction& DebugInfo::GetFunctionAtAddress(Address pc) {
return impl_->GetFunctionAtAddress(pc);
}
Handle<JSObject> DebugInfo::GetLocalScopeObject(Isolate* isolate, Address pc,
Address fp,
Address debug_break_fp) {
......
......@@ -34,6 +34,7 @@ class NativeModule;
class WasmCode;
class WireBytesRef;
class WasmValue;
struct WasmFunction;
// Side table storing information used to inspect Liftoff frames at runtime.
// This table is only created on demand for debugging, so it is not optimized
......@@ -153,6 +154,9 @@ class V8_EXPORT_PRIVATE DebugInfo {
WasmValue GetLocalValue(int local, Address pc, Address fp,
Address debug_break_fp);
int GetStackDepth(Address pc);
const wasm::WasmFunction& GetFunctionAtAddress(Address pc);
WasmValue GetStackValue(int index, Address pc, Address fp,
Address debug_break_fp);
......
This diff is collapsed.
......@@ -9,6 +9,8 @@
namespace v8 {
namespace internal {
class JSProxy;
class WasmFrame;
namespace wasm {
class StreamingDecoder;
......@@ -19,6 +21,8 @@ class WasmJs {
public:
V8_EXPORT_PRIVATE static void Install(Isolate* isolate,
bool exposed_on_global_object);
V8_EXPORT_PRIVATE static Handle<JSProxy> GetJSDebugProxy(WasmFrame* frame);
};
} // namespace internal
......
......@@ -525,15 +525,37 @@ WASM_COMPILED_EXEC_TEST(WasmDebugEvaluate_JavaScript) {
uint16_t index = 0;
runner.builder().AddIndirectFunctionTable(&index, 1);
TestCode<int> code(
TestCode<int64_t> code(
&runner,
{WASM_SET_GLOBAL(0, WASM_I32V_2('B')),
WASM_SET_LOCAL(0, WASM_I32V_2('A')), WASM_RETURN1(WASM_GET_LOCAL(0))},
{ValueType::kI32});
WASM_SET_LOCAL(0, WASM_I64V_2('A')), WASM_RETURN1(WASM_GET_LOCAL(0))},
{ValueType::kI64});
code.BreakOnReturn(&runner);
Isolate* isolate = runner.main_isolate();
Handle<String> snippet = V8String(isolate, "213");
Handle<String> snippet =
V8String(isolate,
"JSON.stringify(["
//"$global0, "
//"$table0, "
"$var0, "
//"$main, "
//"$memory0, "
//"globals[0], "
//"tables[0], "
"locals[0], "
//"functions[0], "
//"memories[0], "
//"memories, "
//"tables, "
//"stack, "
//"imports, "
//"exports, "
//"globals, "
"locals, "
//"functions, "
"], (k, v) => k === 'at' || typeof v === 'undefined' || typeof "
"v === 'object' ? v : v.toString())");
WasmJSBreakHandler break_handler(isolate, snippet);
CHECK(!code.Run(&runner).is_null());
......@@ -541,7 +563,10 @@ WASM_COMPILED_EXEC_TEST(WasmDebugEvaluate_JavaScript) {
WasmJSBreakHandler::EvaluationResult result =
break_handler.result().ToChecked();
CHECK_WITH_MSG(result.error.IsNothing(), result.error.ToChecked().c_str());
CHECK_EQ(result.result.ToChecked(), "213");
CHECK_EQ(result.result.ToChecked(), "[\"65\",\"65\",{}]");
//"[\"66\",{},\"65\",\"function 0() { [native code] }\",{},"
//"\"66\",{},\"65\",\"function 0() { [native code] }\",{},"
//"{},{},{\"0\":\"65\"},{},{},{},{},{}]");
}
} // namespace
......
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