Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(171)

Unified Diff: src/debug/debug.cc

Issue 2096863003: [wasm] prototype for breakpoint support. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@extend-script-functionality
Patch Set: Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/debug/debug.h ('k') | src/debug/debug-frames.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/debug/debug.cc
diff --git a/src/debug/debug.cc b/src/debug/debug.cc
index 631a6fdbc58e29faac969b2d6a105fad01c0fb86..28906dbca1f9cdd8a5343ba3b260e9431f044101 100644
--- a/src/debug/debug.cc
+++ b/src/debug/debug.cc
@@ -32,11 +32,29 @@ namespace internal {
namespace {
-inline int CallOffsetFromCodeOffset(int code_offset, bool is_interpreted) {
+inline int GetCodeOffset(StandardFrame* frame) {
+ // Frame summary is top-down, i.e. caller before callee.
+ // For whatever reason, javascript takes the lowest caller as the code offset
+ // for the frame, where for wasm we need the highest one.
+ return frame->is_java_script() ? FrameSummary::GetFirst(frame).code_offset()
+ : FrameSummary::GetLast(frame).code_offset();
+}
+
+inline int CallOffsetFromCodeOffset(int code_offset, StandardFrame* frame) {
// Code offset points to the instruction after the call. Subtract 1 to
- // exclude that instruction from the search. For bytecode, the code offset
- // still points to the call.
- return is_interpreted ? code_offset : code_offset - 1;
+ // exclude that instruction from the search. For interpreted frames, the code
+ // offset still points to the call.
+ bool interpreted = frame->is_interpreted() || frame->is_wasm_interpreted();
+ return interpreted ? code_offset : code_offset - 1;
+}
+
+std::pair<Handle<JSObject>, int> GetWasmObjectAndFunctionIndexFromCode(
+ Code* code) {
+ FixedArray* deopt_data = code->deoptimization_data();
+ DCHECK_EQ(2, deopt_data->length());
+ Handle<JSObject> wasm(JSObject::cast(deopt_data->get(0)));
+ int func_index = Smi::cast(deopt_data->get(1))->value();
+ return std::make_pair(wasm, func_index);
}
} // namespace
@@ -85,6 +103,9 @@ BreakLocation::Iterator* BreakLocation::GetIterator(
Handle<DebugInfo> debug_info, BreakLocatorType type) {
if (debug_info->abstract_code()->IsBytecodeArray()) {
return new BytecodeArrayIterator(debug_info, type);
+ } else if (debug_info->abstract_code()->GetCode()->kind() ==
+ Code::WASM_FUNCTION) {
+ return new WasmBytecodeIterator(debug_info, type);
} else {
return new CodeIterator(debug_info, type);
}
@@ -264,6 +285,64 @@ BreakLocation BreakLocation::BytecodeArrayIterator::GetBreakLocation() {
position(), statement_position());
}
+namespace {
+
+wasm::WasmInstructionIterator GetWasmInsnIterator(
+ Handle<DebugInfo> debug_info) {
+ auto wasm_and_index = GetWasmObjectAndFunctionIndexFromCode(
+ debug_info->abstract_code()->GetCode());
+ Handle<wasm::WasmDebugInfo> wasm_debug_info(
+ wasm::GetDebugInfo(wasm_and_index.first));
+ return wasm::WasmDebugInfo::GetInstructionIterator(wasm_debug_info,
+ wasm_and_index.second);
+}
+
+} // namespace
+
+BreakLocation::WasmBytecodeIterator::WasmBytecodeIterator(
+ Handle<DebugInfo> debug_info, BreakLocatorType type)
+ : Iterator(debug_info),
+ wasm_insn_iterator(GetWasmInsnIterator(debug_info)),
+ break_locator_type_(type) {
+ // Get wasm object and function index from deopt data.
+ Code* code = debug_info->abstract_code()->GetCode();
+ Handle<JSObject> wasm;
+ std::tie(wasm, func_index) = GetWasmObjectAndFunctionIndexFromCode(code);
+ wasm_debug_info = handle(wasm::GetDebugInfo(wasm));
+ Next();
+}
+
+BreakLocation BreakLocation::WasmBytecodeIterator::GetBreakLocation() {
+ DebugBreakType type;
+ switch (wasm_debug_info->GetInstructionType(func_index,
+ wasm_insn_iterator.pc_offset())) {
+ case wasm::WasmDebugInfo::InstructionType::RETURN:
+ type = DEBUG_BREAK_SLOT_AT_RETURN;
+ break;
+ case wasm::WasmDebugInfo::InstructionType::CALL:
+ type = DEBUG_BREAK_SLOT_AT_CALL;
+ break;
+ default:
+ type = DEBUG_BREAK_SLOT;
+ break;
+ }
+ return BreakLocation(debug_info_, type, code_offset(), position(),
+ statement_position());
+}
+
+void BreakLocation::WasmBytecodeIterator::Next() {
+ ++break_index_;
+ for (bool first = break_index_ == 0; !Done(); first = false) {
+ if (!first) wasm_insn_iterator.Next();
+ position_ = statement_position_ = wasm_insn_iterator.pc_offset();
+ if (break_locator_type_ == ALL_BREAK_LOCATIONS) break;
+ DCHECK_EQ(BreakLocatorType::CALLS_AND_RETURNS, break_locator_type_);
+ using InsnType = wasm::WasmDebugInfo::InstructionType;
+ InsnType type = wasm_debug_info->GetInstructionType(func_index, position_);
+ if (type == InsnType::RETURN || type == InsnType::CALL) break;
+ }
+}
+
// Find the break point at the supplied address, or the closest one before
// the address.
BreakLocation BreakLocation::FromCodeOffset(Handle<DebugInfo> debug_info,
@@ -273,11 +352,12 @@ BreakLocation BreakLocation::FromCodeOffset(Handle<DebugInfo> debug_info,
return it->GetBreakLocation();
}
-BreakLocation BreakLocation::FromFrame(Handle<DebugInfo> debug_info,
- JavaScriptFrame* frame) {
- int code_offset = FrameSummary::GetFirst(frame).code_offset();
- int call_offset =
- CallOffsetFromCodeOffset(code_offset, frame->is_interpreted());
+BreakLocation BreakLocation::FromFrame(StandardFrame* frame) {
+ // Get the debug info (create it if it does not exist).
+ Handle<DebugInfo> debug_info(DebugInfo::cast(frame->debug_info(true)));
+
+ int code_offset = GetCodeOffset(frame);
+ int call_offset = CallOffsetFromCodeOffset(code_offset, frame);
return FromCodeOffset(debug_info, call_offset);
}
@@ -297,7 +377,7 @@ int BreakLocation::BreakIndexFromCodeOffset(Handle<DebugInfo> debug_info,
// Run through all break points to locate the one closest to the address.
int closest_break = 0;
int distance = kMaxInt;
- DCHECK(0 <= offset && offset < debug_info->abstract_code()->Size());
+ DCHECK_LE(0, offset);
for (base::SmartPointer<Iterator> it(GetIterator(debug_info)); !it->Done();
it->Next()) {
// Check if this break point is closer that what was previously found.
@@ -406,12 +486,21 @@ void BreakLocation::SetDebugBreak() {
DCHECK(IsDebugBreakSlot());
if (abstract_code()->IsCode()) {
Code* code = abstract_code()->GetCode();
- DCHECK(code->kind() == Code::FUNCTION);
- Builtins* builtins = isolate()->builtins();
- Handle<Code> target = IsReturn() ? builtins->Return_DebugBreak()
- : builtins->Slot_DebugBreak();
- Address pc = code->instruction_start() + code_offset();
- DebugCodegen::PatchDebugBreakSlot(isolate(), pc, target);
+ if (code->kind() == Code::FUNCTION) {
+ Builtins* builtins = isolate()->builtins();
+ Handle<Code> target = IsReturn() ? builtins->Return_DebugBreak()
+ : builtins->Slot_DebugBreak();
+ Address pc = code->instruction_start() + code_offset();
+ DebugCodegen::PatchDebugBreakSlot(isolate(), pc, target);
+ } else {
+ DCHECK(code->kind() == Code::WASM_FUNCTION);
+ // Get wasm object and function index from deopt data.
+ Handle<JSObject> wasm;
+ int func_index;
+ std::tie(wasm, func_index) = GetWasmObjectAndFunctionIndexFromCode(code);
+ Handle<wasm::WasmDebugInfo> debug_info(wasm::GetDebugInfo(wasm));
+ wasm::WasmDebugInfo::SetBreakpoint(debug_info, func_index, position());
+ }
} else {
BytecodeArray* bytecode_array = abstract_code()->GetBytecodeArray();
interpreter::Bytecode bytecode =
@@ -449,9 +538,16 @@ bool BreakLocation::IsDebugBreak() const {
DCHECK(IsDebugBreakSlot());
if (abstract_code()->IsCode()) {
Code* code = abstract_code()->GetCode();
- DCHECK(code->kind() == Code::FUNCTION);
- Address pc = code->instruction_start() + code_offset();
- return DebugCodegen::DebugBreakSlotIsPatched(pc);
+ if (code->kind() == Code::FUNCTION) {
+ Address pc = code->instruction_start() + code_offset();
+ return DebugCodegen::DebugBreakSlotIsPatched(pc);
+ }
+ DCHECK(code->kind() == Code::WASM_FUNCTION);
+ Handle<JSObject> wasm;
+ int func_index;
+ std::tie(wasm, func_index) = GetWasmObjectAndFunctionIndexFromCode(code);
+ Handle<wasm::WasmDebugInfo> wasm_debug_info(wasm::GetDebugInfo(wasm));
+ return wasm_debug_info->HasBreakpoint(func_index, position());
} else {
BytecodeArray* bytecode_array = abstract_code()->GetBytecodeArray();
interpreter::Bytecode bytecode =
@@ -574,7 +670,7 @@ void Debug::Unload() {
debug_context_ = Handle<Context>();
}
-void Debug::Break(JavaScriptFrame* frame) {
+void Debug::Break(StandardFrame* frame) {
HandleScope scope(isolate_);
// Initialize LiveEdit.
@@ -590,17 +686,8 @@ void Debug::Break(JavaScriptFrame* frame) {
// Postpone interrupt during breakpoint processing.
PostponeInterruptsScope postpone(isolate_);
- // Get the debug info (create it if it does not exist).
- Handle<JSFunction> function(frame->function());
- Handle<SharedFunctionInfo> shared(function->shared());
- if (!EnsureDebugInfo(shared, function)) {
- // Return if we failed to retrieve the debug info.
- return;
- }
- Handle<DebugInfo> debug_info(shared->GetDebugInfo(), isolate_);
-
// Find the break location where execution has stopped.
- BreakLocation location = BreakLocation::FromFrame(debug_info, frame);
+ BreakLocation location = BreakLocation::FromFrame(frame);
// Find actual break points, if any, and trigger debug break event.
Handle<Object> break_points_hit = CheckBreakPoints(&location);
@@ -634,8 +721,7 @@ void Debug::Break(JavaScriptFrame* frame) {
step_break = location.IsTailCall();
// Fall through.
case StepIn: {
- FrameSummary summary = FrameSummary::GetFirst(frame);
- int offset = summary.code_offset();
+ int offset = GetCodeOffset(frame);
step_break = step_break || location.IsReturn() ||
(current_fp != last_fp) ||
(thread_local_.last_statement_position_ !=
@@ -713,7 +799,7 @@ bool Debug::IsMutedAtCurrentLocation(JavaScriptFrame* frame) {
// Enter the debugger.
DebugScope debug_scope(this);
if (debug_scope.failed()) return false;
- BreakLocation current_position = BreakLocation::FromFrame(debug_info, frame);
+ BreakLocation current_position = BreakLocation::FromFrame(frame);
List<BreakLocation> break_locations;
BreakLocation::AllForStatementPosition(
debug_info, current_position.statement_position(), &break_locations);
@@ -799,36 +885,40 @@ bool Debug::SetBreakPointForScript(Handle<Script> script,
Handle<Object> break_point_object,
int* source_position,
BreakPositionAlignment alignment) {
- if (script->type() == Script::TYPE_WASM) {
- // TODO(clemensh): set breakpoint for wasm.
- return false;
- }
HandleScope scope(isolate_);
- // Obtain shared function info for the function.
- Handle<Object> result =
- FindSharedFunctionInfoInScript(script, *source_position);
- if (result->IsUndefined(isolate_)) return false;
-
- // Make sure the function has set up the debug info.
- Handle<SharedFunctionInfo> shared = Handle<SharedFunctionInfo>::cast(result);
- if (!EnsureDebugInfo(shared, Handle<JSFunction>::null())) {
- // Return if retrieving debug info failed.
- return false;
+ Handle<DebugInfo> debug_info;
+ int start_position = 0;
+ if (script->type() == Script::TYPE_WASM) {
+ Handle<wasm::WasmDebugInfo> wasm_debug(
+ wasm::GetDebugInfo(handle(script->wasm_object(), isolate_)), isolate_);
+ uint32_t func_index = script->wasm_function_index();
+ debug_info = handle(
+ wasm::WasmDebugInfo::GetDebugInfo(wasm_debug, func_index), isolate_);
+ } else {
+ // Obtain shared function info for the function.
+ Handle<Object> result =
+ FindSharedFunctionInfoInScript(script, *source_position);
+ if (result->IsUndefined(isolate_)) return false;
+
+ // Get debug info, create it if necessary.
+ Handle<SharedFunctionInfo> shared =
+ Handle<SharedFunctionInfo>::cast(result);
+ if (!EnsureDebugInfo(shared, Handle<JSFunction>::null())) {
+ // Return if retrieving debug info failed.
+ return false;
+ }
+ debug_info = handle(shared->GetDebugInfo(), isolate_);
+ start_position = shared->start_position();
}
// Find position within function. The script position might be before the
// source position of the first function.
- int position;
- if (shared->start_position() > *source_position) {
- position = 0;
- } else {
- position = *source_position - shared->start_position();
- }
+ int position =
+ start_position > *source_position ? 0 : *source_position - start_position;
- Handle<DebugInfo> debug_info(shared->GetDebugInfo());
// Source positions starts with zero.
- DCHECK(position >= 0);
+ DCHECK_LE(0, position);
// Find the break point and change it.
BreakLocation location =
@@ -840,7 +930,7 @@ bool Debug::SetBreakPointForScript(Handle<Script> script,
position = (alignment == STATEMENT_ALIGNED) ? location.statement_position()
: location.position();
- *source_position = position + shared->start_position();
+ *source_position = position + start_position;
// At least one active break point now.
DCHECK(debug_info->GetBreakPointCount() > 0);
@@ -1045,8 +1135,7 @@ void Debug::PrepareStep(StepAction step_action) {
summary = FrameSummary::GetFirst(frame);
}
- int call_offset =
- CallOffsetFromCodeOffset(summary.code_offset(), frame->is_interpreted());
+ int call_offset = CallOffsetFromCodeOffset(summary.code_offset(), frame);
BreakLocation location =
BreakLocation::FromCodeOffset(debug_info, call_offset);
@@ -1603,7 +1692,7 @@ void Debug::RemoveDebugInfoAndClearFromShared(Handle<DebugInfo> debug_info) {
UNREACHABLE();
}
-void Debug::SetAfterBreakTarget(JavaScriptFrame* frame) {
+void Debug::SetAfterBreakTarget(StandardFrame* frame) {
after_break_target_ = NULL;
if (!LiveEdit::SetAfterBreakTarget(this)) {
// Continue just after the slot.
@@ -2315,7 +2404,6 @@ DebugScope::DebugScope(Debug* debug)
StackTraceFrameIterator it(isolate());
bool has_frames = !it.done();
// We don't currently support breaking inside wasm framess.
- DCHECK(!has_frames || !it.is_wasm());
debug_->thread_local_.break_frame_id_ =
has_frames ? it.frame()->id() : StackFrame::NO_ID;
debug_->SetNextBreakId();
« no previous file with comments | « src/debug/debug.h ('k') | src/debug/debug-frames.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698