[wasm][debug] Move breakpoint cctests to Liftoff
The cctests for breakpoints were still executing in the interpreter. This CL moves them over to Liftoff. Note that the additional methods on {DebugInfo} will be reused for other purposes, see https://crrev.com/c/1941139. R=jkummerow@chromium.org Bug: v8:10389 Change-Id: Ia88150612377d6e7db0514af1efe091124b3ddce Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2162852 Reviewed-by: Jakob Kummerow <jkummerow@chromium.org> Commit-Queue: Clemens Backes <clemensb@chromium.org> Cr-Commit-Position: refs/heads/master@{#67360}
This commit is contained in:
parent
460ed1f076
commit
780746d64c
@ -545,7 +545,7 @@ class V8_EXPORT_PRIVATE FrameSummary {
|
|||||||
uint32_t function_index() const;
|
uint32_t function_index() const;
|
||||||
wasm::WasmCode* code() const { return code_; }
|
wasm::WasmCode* code() const { return code_; }
|
||||||
int code_offset() const { return code_offset_; }
|
int code_offset() const { return code_offset_; }
|
||||||
int byte_offset() const;
|
V8_EXPORT_PRIVATE int byte_offset() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
wasm::WasmCode* const code_;
|
wasm::WasmCode* const code_;
|
||||||
@ -956,7 +956,7 @@ class WasmCompiledFrame : public StandardFrame {
|
|||||||
|
|
||||||
// Accessors.
|
// Accessors.
|
||||||
WasmInstanceObject wasm_instance() const;
|
WasmInstanceObject wasm_instance() const;
|
||||||
wasm::NativeModule* native_module() const;
|
V8_EXPORT_PRIVATE wasm::NativeModule* native_module() const;
|
||||||
wasm::WasmCode* wasm_code() const;
|
wasm::WasmCode* wasm_code() const;
|
||||||
uint32_t function_index() const;
|
uint32_t function_index() const;
|
||||||
Script script() const override;
|
Script script() const override;
|
||||||
|
@ -549,15 +549,34 @@ class DebugInfoImpl {
|
|||||||
explicit DebugInfoImpl(NativeModule* native_module)
|
explicit DebugInfoImpl(NativeModule* native_module)
|
||||||
: native_module_(native_module) {}
|
: native_module_(native_module) {}
|
||||||
|
|
||||||
|
int GetNumLocals(Isolate* isolate, Address pc) {
|
||||||
|
FrameInspectionScope scope(this, isolate, pc);
|
||||||
|
if (!scope.code->is_liftoff()) return 0;
|
||||||
|
return scope.debug_side_table->num_locals();
|
||||||
|
}
|
||||||
|
|
||||||
WasmValue GetLocalValue(int local, Isolate* isolate, Address pc, Address fp,
|
WasmValue GetLocalValue(int local, Isolate* isolate, Address pc, Address fp,
|
||||||
Address debug_break_fp) {
|
Address debug_break_fp) {
|
||||||
wasm::WasmCodeRefScope wasm_code_ref_scope;
|
FrameInspectionScope scope(this, isolate, pc);
|
||||||
wasm::WasmCode* code =
|
return GetValue(scope.debug_side_table_entry, local, fp, debug_break_fp);
|
||||||
isolate->wasm_engine()->code_manager()->LookupCode(pc);
|
}
|
||||||
auto* debug_side_table = GetDebugSideTable(code, isolate->allocator());
|
|
||||||
int pc_offset = static_cast<int>(pc - code->instruction_start());
|
int GetStackDepth(Isolate* isolate, Address pc) {
|
||||||
auto* debug_side_table_entry = debug_side_table->GetEntry(pc_offset);
|
FrameInspectionScope scope(this, isolate, pc);
|
||||||
return GetValue(debug_side_table_entry, local, fp, debug_break_fp);
|
if (!scope.code->is_liftoff()) return 0;
|
||||||
|
int num_locals = static_cast<int>(scope.debug_side_table->num_locals());
|
||||||
|
int value_count = scope.debug_side_table_entry->num_values();
|
||||||
|
return value_count - num_locals;
|
||||||
|
}
|
||||||
|
|
||||||
|
WasmValue GetStackValue(int index, Isolate* isolate, Address pc, Address fp,
|
||||||
|
Address debug_break_fp) {
|
||||||
|
FrameInspectionScope scope(this, isolate, pc);
|
||||||
|
int num_locals = static_cast<int>(scope.debug_side_table->num_locals());
|
||||||
|
int value_count = scope.debug_side_table_entry->num_values();
|
||||||
|
if (num_locals + index >= value_count) return {};
|
||||||
|
return GetValue(scope.debug_side_table_entry, num_locals + index, fp,
|
||||||
|
debug_break_fp);
|
||||||
}
|
}
|
||||||
|
|
||||||
Handle<JSObject> GetLocalScopeObject(Isolate* isolate, Address pc, Address fp,
|
Handle<JSObject> GetLocalScopeObject(Isolate* isolate, Address pc, Address fp,
|
||||||
@ -806,6 +825,25 @@ class DebugInfoImpl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
struct FrameInspectionScope {
|
||||||
|
FrameInspectionScope(DebugInfoImpl* debug_info, Isolate* isolate,
|
||||||
|
Address pc)
|
||||||
|
: code(isolate->wasm_engine()->code_manager()->LookupCode(pc)),
|
||||||
|
pc_offset(static_cast<int>(pc - code->instruction_start())),
|
||||||
|
debug_side_table(code->is_liftoff() ? debug_info->GetDebugSideTable(
|
||||||
|
code, isolate->allocator())
|
||||||
|
: nullptr),
|
||||||
|
debug_side_table_entry(debug_side_table
|
||||||
|
? debug_side_table->GetEntry(pc_offset)
|
||||||
|
: nullptr) {}
|
||||||
|
|
||||||
|
wasm::WasmCodeRefScope wasm_code_ref_scope;
|
||||||
|
wasm::WasmCode* code;
|
||||||
|
int pc_offset;
|
||||||
|
const DebugSideTable* debug_side_table;
|
||||||
|
const DebugSideTable::Entry* debug_side_table_entry;
|
||||||
|
};
|
||||||
|
|
||||||
const DebugSideTable* GetDebugSideTable(WasmCode* code,
|
const DebugSideTable* GetDebugSideTable(WasmCode* code,
|
||||||
AccountingAllocator* allocator) {
|
AccountingAllocator* allocator) {
|
||||||
{
|
{
|
||||||
@ -978,11 +1016,24 @@ DebugInfo::DebugInfo(NativeModule* native_module)
|
|||||||
|
|
||||||
DebugInfo::~DebugInfo() = default;
|
DebugInfo::~DebugInfo() = default;
|
||||||
|
|
||||||
|
int DebugInfo::GetNumLocals(Isolate* isolate, Address pc) {
|
||||||
|
return impl_->GetNumLocals(isolate, pc);
|
||||||
|
}
|
||||||
|
|
||||||
WasmValue DebugInfo::GetLocalValue(int local, Isolate* isolate, Address pc,
|
WasmValue DebugInfo::GetLocalValue(int local, Isolate* isolate, Address pc,
|
||||||
Address fp, Address debug_break_fp) {
|
Address fp, Address debug_break_fp) {
|
||||||
return impl_->GetLocalValue(local, isolate, pc, fp, debug_break_fp);
|
return impl_->GetLocalValue(local, isolate, pc, fp, debug_break_fp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int DebugInfo::GetStackDepth(Isolate* isolate, Address pc) {
|
||||||
|
return impl_->GetStackDepth(isolate, pc);
|
||||||
|
}
|
||||||
|
|
||||||
|
WasmValue DebugInfo::GetStackValue(int index, Isolate* isolate, Address pc,
|
||||||
|
Address fp, Address debug_break_fp) {
|
||||||
|
return impl_->GetStackValue(index, isolate, pc, fp, debug_break_fp);
|
||||||
|
}
|
||||||
|
|
||||||
Handle<JSObject> DebugInfo::GetLocalScopeObject(Isolate* isolate, Address pc,
|
Handle<JSObject> DebugInfo::GetLocalScopeObject(Isolate* isolate, Address pc,
|
||||||
Address fp,
|
Address fp,
|
||||||
Address debug_break_fp) {
|
Address debug_break_fp) {
|
||||||
|
@ -137,15 +137,20 @@ Handle<JSObject> GetModuleScopeObject(Handle<WasmInstanceObject>);
|
|||||||
|
|
||||||
// Debug info per NativeModule, created lazily on demand.
|
// Debug info per NativeModule, created lazily on demand.
|
||||||
// Implementation in {wasm-debug.cc} using PIMPL.
|
// Implementation in {wasm-debug.cc} using PIMPL.
|
||||||
class DebugInfo {
|
class V8_EXPORT_PRIVATE DebugInfo {
|
||||||
public:
|
public:
|
||||||
explicit DebugInfo(NativeModule*);
|
explicit DebugInfo(NativeModule*);
|
||||||
~DebugInfo();
|
~DebugInfo();
|
||||||
|
|
||||||
|
// For the frame inspection methods below:
|
||||||
// {fp} is the frame pointer of the Liftoff frame, {debug_break_fp} that of
|
// {fp} is the frame pointer of the Liftoff frame, {debug_break_fp} that of
|
||||||
// the {WasmDebugBreak} frame (if any).
|
// the {WasmDebugBreak} frame (if any).
|
||||||
|
int GetNumLocals(Isolate*, Address pc);
|
||||||
WasmValue GetLocalValue(int local, Isolate*, Address pc, Address fp,
|
WasmValue GetLocalValue(int local, Isolate*, Address pc, Address fp,
|
||||||
Address debug_break_fp);
|
Address debug_break_fp);
|
||||||
|
int GetStackDepth(Isolate*, Address pc);
|
||||||
|
WasmValue GetStackValue(int index, Isolate*, Address pc, Address fp,
|
||||||
|
Address debug_break_fp);
|
||||||
|
|
||||||
Handle<JSObject> GetLocalScopeObject(Isolate*, Address pc, Address fp,
|
Handle<JSObject> GetLocalScopeObject(Isolate*, Address pc, Address fp,
|
||||||
Address debug_break_fp);
|
Address debug_break_fp);
|
||||||
|
@ -7,8 +7,8 @@
|
|||||||
#include "src/execution/frames-inl.h"
|
#include "src/execution/frames-inl.h"
|
||||||
#include "src/objects/property-descriptor.h"
|
#include "src/objects/property-descriptor.h"
|
||||||
#include "src/utils/utils.h"
|
#include "src/utils/utils.h"
|
||||||
|
#include "src/wasm/wasm-debug.h"
|
||||||
#include "src/wasm/wasm-objects-inl.h"
|
#include "src/wasm/wasm-objects-inl.h"
|
||||||
|
|
||||||
#include "test/cctest/cctest.h"
|
#include "test/cctest/cctest.h"
|
||||||
#include "test/cctest/compiler/value-helper.h"
|
#include "test/cctest/compiler/value-helper.h"
|
||||||
#include "test/cctest/wasm/wasm-run-utils.h"
|
#include "test/cctest/wasm/wasm-run-utils.h"
|
||||||
@ -116,7 +116,7 @@ class BreakHandler : public debug::DebugDelegate {
|
|||||||
|
|
||||||
// Check the current position.
|
// Check the current position.
|
||||||
StackTraceFrameIterator frame_it(isolate_);
|
StackTraceFrameIterator frame_it(isolate_);
|
||||||
auto summ = FrameSummary::GetTop(frame_it.frame()).AsWasmInterpreted();
|
auto summ = FrameSummary::GetTop(frame_it.frame()).AsWasmCompiled();
|
||||||
CHECK_EQ(expected_breaks_[count_].position, summ.byte_offset());
|
CHECK_EQ(expected_breaks_[count_].position, summ.byte_offset());
|
||||||
|
|
||||||
expected_breaks_[count_].pre_action();
|
expected_breaks_[count_].pre_action();
|
||||||
@ -152,14 +152,6 @@ Handle<BreakPoint> SetBreakpoint(WasmRunnerBase* runner, int function_index,
|
|||||||
runner->main_isolate()->factory()->NewBreakPoint(
|
runner->main_isolate()->factory()->NewBreakPoint(
|
||||||
break_index++, runner->main_isolate()->factory()->empty_string());
|
break_index++, runner->main_isolate()->factory()->empty_string());
|
||||||
CHECK(WasmScript::SetBreakPoint(script, &code_offset, break_point));
|
CHECK(WasmScript::SetBreakPoint(script, &code_offset, break_point));
|
||||||
int set_byte_offset = code_offset - func_offset;
|
|
||||||
CHECK_EQ(expected_set_byte_offset, set_byte_offset);
|
|
||||||
// Also set breakpoint on the debug info of the instance directly, since the
|
|
||||||
// instance chain is not setup properly in tests.
|
|
||||||
Handle<WasmDebugInfo> debug_info =
|
|
||||||
WasmInstanceObject::GetOrCreateDebugInfo(instance);
|
|
||||||
WasmDebugInfo::SetBreakpoint(debug_info, function_index, set_byte_offset);
|
|
||||||
|
|
||||||
return break_point;
|
return break_point;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -172,11 +164,6 @@ void ClearBreakpoint(WasmRunnerBase* runner, int function_index,
|
|||||||
Handle<Script> script(instance->module_object().script(),
|
Handle<Script> script(instance->module_object().script(),
|
||||||
runner->main_isolate());
|
runner->main_isolate());
|
||||||
CHECK(WasmScript::ClearBreakPoint(script, code_offset, break_point));
|
CHECK(WasmScript::ClearBreakPoint(script, code_offset, break_point));
|
||||||
// Also clear breakpoint on the debug info of the instance directly, since the
|
|
||||||
// instance chain is not setup properly in tests.
|
|
||||||
Handle<WasmDebugInfo> debug_info =
|
|
||||||
WasmInstanceObject::GetOrCreateDebugInfo(instance);
|
|
||||||
WasmDebugInfo::ClearBreakpoint(debug_info, function_index, byte_offset);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wrapper with operator<<.
|
// Wrapper with operator<<.
|
||||||
@ -243,21 +230,23 @@ class CollectValuesBreakHandler : public debug::DebugDelegate {
|
|||||||
HandleScope handles(isolate_);
|
HandleScope handles(isolate_);
|
||||||
|
|
||||||
StackTraceFrameIterator frame_it(isolate_);
|
StackTraceFrameIterator frame_it(isolate_);
|
||||||
auto summ = FrameSummary::GetTop(frame_it.frame()).AsWasmInterpreted();
|
WasmCompiledFrame* frame = WasmCompiledFrame::cast(frame_it.frame());
|
||||||
Handle<WasmInstanceObject> instance = summ.wasm_instance();
|
DebugInfo* debug_info = frame->native_module()->GetDebugInfo();
|
||||||
|
|
||||||
auto frame =
|
int num_locals = debug_info->GetNumLocals(isolate_, frame->pc());
|
||||||
instance->debug_info().GetInterpretedFrame(frame_it.frame()->fp(), 0);
|
CHECK_EQ(expected.locals.size(), num_locals);
|
||||||
CHECK_EQ(expected.locals.size(), frame->GetLocalCount());
|
for (int i = 0; i < num_locals; ++i) {
|
||||||
for (int i = 0; i < frame->GetLocalCount(); ++i) {
|
WasmValue local_value = debug_info->GetLocalValue(
|
||||||
CHECK_EQ(WasmValWrapper{expected.locals[i]},
|
i, isolate_, frame->pc(), frame->fp(), frame->callee_fp());
|
||||||
WasmValWrapper{frame->GetLocalValue(i)});
|
CHECK_EQ(WasmValWrapper{expected.locals[i]}, WasmValWrapper{local_value});
|
||||||
}
|
}
|
||||||
|
|
||||||
CHECK_EQ(expected.stack.size(), frame->GetStackHeight());
|
int stack_depth = debug_info->GetStackDepth(isolate_, frame->pc());
|
||||||
for (int i = 0; i < frame->GetStackHeight(); ++i) {
|
CHECK_EQ(expected.stack.size(), stack_depth);
|
||||||
CHECK_EQ(WasmValWrapper{expected.stack[i]},
|
for (int i = 0; i < stack_depth; ++i) {
|
||||||
WasmValWrapper{frame->GetStackValue(i)});
|
WasmValue stack_value = debug_info->GetStackValue(
|
||||||
|
i, isolate_, frame->pc(), frame->fp(), frame->callee_fp());
|
||||||
|
CHECK_EQ(WasmValWrapper{expected.stack[i]}, WasmValWrapper{stack_value});
|
||||||
}
|
}
|
||||||
|
|
||||||
isolate_->debug()->PrepareStep(StepAction::StepIn);
|
isolate_->debug()->PrepareStep(StepAction::StepIn);
|
||||||
@ -379,6 +368,7 @@ WASM_COMPILED_EXEC_TEST(WasmSimpleStepping) {
|
|||||||
|
|
||||||
WASM_COMPILED_EXEC_TEST(WasmStepInAndOut) {
|
WASM_COMPILED_EXEC_TEST(WasmStepInAndOut) {
|
||||||
WasmRunner<int, int> runner(execution_tier);
|
WasmRunner<int, int> runner(execution_tier);
|
||||||
|
runner.TierDown();
|
||||||
WasmFunctionCompiler& f2 = runner.NewFunction<void>();
|
WasmFunctionCompiler& f2 = runner.NewFunction<void>();
|
||||||
f2.AllocateLocal(kWasmI32);
|
f2.AllocateLocal(kWasmI32);
|
||||||
|
|
||||||
|
@ -579,8 +579,10 @@ void WasmFunctionCompiler::Build(const byte* start, const byte* end) {
|
|||||||
func_wire_bytes.begin(), func_wire_bytes.end()};
|
func_wire_bytes.begin(), func_wire_bytes.end()};
|
||||||
NativeModule* native_module =
|
NativeModule* native_module =
|
||||||
builder_->instance_object()->module_object().native_module();
|
builder_->instance_object()->module_object().native_module();
|
||||||
|
ForDebugging for_debugging =
|
||||||
|
native_module->IsTieredDown() ? kForDebugging : kNoDebugging;
|
||||||
WasmCompilationUnit unit(function_->func_index, builder_->execution_tier(),
|
WasmCompilationUnit unit(function_->func_index, builder_->execution_tier(),
|
||||||
kNoDebugging);
|
for_debugging);
|
||||||
WasmFeatures unused_detected_features;
|
WasmFeatures unused_detected_features;
|
||||||
WasmCompilationResult result = unit.ExecuteCompilation(
|
WasmCompilationResult result = unit.ExecuteCompilation(
|
||||||
isolate()->wasm_engine(), &env,
|
isolate()->wasm_engine(), &env,
|
||||||
|
@ -260,7 +260,10 @@ class TestingModuleBuilder {
|
|||||||
|
|
||||||
void SetExecutable() { native_module_->SetExecutable(true); }
|
void SetExecutable() { native_module_->SetExecutable(true); }
|
||||||
|
|
||||||
void TierDown() { native_module_->TierDown(isolate_); }
|
void TierDown() {
|
||||||
|
native_module_->TierDown(isolate_);
|
||||||
|
execution_tier_ = ExecutionTier::kLiftoff;
|
||||||
|
}
|
||||||
|
|
||||||
CompilationEnv CreateCompilationEnv();
|
CompilationEnv CreateCompilationEnv();
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user