Chromium Code Reviews| Index: src/debug/debug.cc |
| diff --git a/src/debug/debug.cc b/src/debug/debug.cc |
| index 1ea420fefe8e1eda7a9f3bf57fc02c13383d8e1f..d42acb89619c1c78d83e15331b1269726a41deca 100644 |
| --- a/src/debug/debug.cc |
| +++ b/src/debug/debug.cc |
| @@ -17,6 +17,7 @@ |
| #include "src/full-codegen/full-codegen.h" |
| #include "src/global-handles.h" |
| #include "src/interpreter/bytecodes.h" |
| +#include "src/interpreter/interpreter.h" |
| #include "src/isolate-inl.h" |
| #include "src/list.h" |
| #include "src/log.h" |
| @@ -209,7 +210,7 @@ BreakLocation::BytecodeArrayIterator::GetDebugBreakType() { |
| BytecodeArray* bytecode_array = |
| debug_info_->abstract_code()->GetBytecodeArray(); |
| interpreter::Bytecode bytecode = |
| - static_cast<interpreter::Bytecode>(bytecode_array->get(code_offset())); |
| + interpreter::Bytecodes::FromByte(bytecode_array->get(code_offset())); |
| if (bytecode == interpreter::Bytecode::kDebugger) { |
| return DEBUGGER_STATEMENT; |
| @@ -238,7 +239,6 @@ BreakLocation BreakLocation::FromCodeOffset(Handle<DebugInfo> debug_info, |
| return it->GetBreakLocation(); |
| } |
| -// Move GetFirstFrameSummary Definition to here as FromFrame use it. |
| FrameSummary GetFirstFrameSummary(JavaScriptFrame* frame) { |
| List<FrameSummary> frames(FLAG_max_inlining_levels + 1); |
| frame->Summarize(&frames); |
| @@ -247,11 +247,13 @@ FrameSummary GetFirstFrameSummary(JavaScriptFrame* frame) { |
| BreakLocation BreakLocation::FromFrame(Handle<DebugInfo> debug_info, |
| JavaScriptFrame* frame) { |
| - // Code offset to the instruction after the current one, possibly a break |
| - // location as well. So the "- 1" to exclude it from the search. |
| - // Get code offset from the unoptimized code. |
| + // 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. |
| FrameSummary summary = GetFirstFrameSummary(frame); |
| - return FromCodeOffset(debug_info, summary.code_offset() - 1); |
| + int call_offset = summary.code_offset(); |
| + if (!frame->is_interpreted()) call_offset--; |
| + return FromCodeOffset(debug_info, call_offset); |
| } |
| // Find the break point at the supplied address, or the closest one before |
| @@ -400,10 +402,16 @@ void BreakLocation::SetDebugBreak() { |
| : builtins->Slot_DebugBreak(); |
| Address pc = code->instruction_start() + code_offset(); |
| DebugCodegen::PatchDebugBreakSlot(isolate(), pc, target); |
| - DCHECK(IsDebugBreak()); |
| } else { |
| - // TODO(yangguo): implement this once we have a way to record break points. |
| + BytecodeArray* bytecode_array = abstract_code()->GetBytecodeArray(); |
|
Yang
2016/02/16 09:22:20
We may eventually want to move to a representation
|
| + interpreter::Bytecode bytecode = |
| + interpreter::Bytecodes::FromByte(bytecode_array->get(code_offset())); |
| + interpreter::Bytecode debugbreak = |
| + interpreter::Bytecodes::GetDebugBreak(bytecode); |
| + bytecode_array->set(code_offset(), |
| + interpreter::Bytecodes::ToByte(debugbreak)); |
| } |
| + DCHECK(IsDebugBreak()); |
| } |
| @@ -417,10 +425,12 @@ void BreakLocation::ClearDebugBreak() { |
| DCHECK(code->kind() == Code::FUNCTION); |
| Address pc = code->instruction_start() + code_offset(); |
| DebugCodegen::ClearDebugBreakSlot(isolate(), pc); |
| - DCHECK(!IsDebugBreak()); |
| } else { |
| - // TODO(yangguo): implement this once we have a way to record break points. |
| + BytecodeArray* bytecode_array = abstract_code()->GetBytecodeArray(); |
| + BytecodeArray* original = debug_info_->shared()->bytecode_array(); |
| + bytecode_array->set(code_offset(), original->get(code_offset())); |
| } |
| + DCHECK(!IsDebugBreak()); |
| } |
| @@ -433,8 +443,10 @@ bool BreakLocation::IsDebugBreak() const { |
| Address pc = code->instruction_start() + code_offset(); |
| return DebugCodegen::DebugBreakSlotIsPatched(pc); |
| } else { |
| - // TODO(yangguo): implement this once we have a way to record break points. |
| - return false; |
| + BytecodeArray* bytecode_array = abstract_code()->GetBytecodeArray(); |
| + interpreter::Bytecode bytecode = |
| + interpreter::Bytecodes::FromByte(bytecode_array->get(code_offset())); |
| + return interpreter::Bytecodes::IsDebugBreak(bytecode); |
| } |
| } |
| @@ -999,10 +1011,13 @@ void Debug::PrepareStep(StepAction step_action) { |
| summary = GetFirstFrameSummary(frame); |
| } |
| - // PC points to the instruction after the current one, possibly a break |
| - // location as well. So the "- 1" to exclude it from the search. |
| + // 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. |
| + int call_offset = summary.code_offset(); |
| + if (!frame->is_interpreted()) call_offset--; |
|
rmcilroy
2016/02/16 10:46:38
Could you extract this code into a helper - it's r
Yang
2016/02/19 13:09:17
Done.
|
| BreakLocation location = |
| - BreakLocation::FromCodeOffset(debug_info, summary.code_offset() - 1); |
| + BreakLocation::FromCodeOffset(debug_info, call_offset); |
| // At a return statement we will step out either way. |
| if (location.IsReturn()) step_action = StepOut; |
| @@ -1523,7 +1538,7 @@ void Debug::RemoveDebugInfoAndClearFromShared(Handle<DebugInfo> debug_info) { |
| prev->set_next(current->next()); |
| } |
| delete current; |
| - shared->set_debug_info(isolate_->heap()->undefined_value()); |
| + shared->set_debug_info(DebugInfo::uninitialized()); |
| return; |
| } |
| // Move to next in list. |
| @@ -1534,14 +1549,25 @@ void Debug::RemoveDebugInfoAndClearFromShared(Handle<DebugInfo> debug_info) { |
| UNREACHABLE(); |
| } |
| - |
| -void Debug::SetAfterBreakTarget(JavaScriptFrame* frame) { |
| - after_break_target_ = NULL; |
| - |
| - if (LiveEdit::SetAfterBreakTarget(this)) return; // LiveEdit did the job. |
| - |
| - // Continue just after the slot. |
| - after_break_target_ = frame->pc(); |
| +Object* Debug::SetAfterBreakTarget(JavaScriptFrame* frame) { |
| + if (frame->is_interpreted()) { |
| + // Find the handler from the original bytecode array. |
| + InterpretedFrame* interpreted_frame = |
| + reinterpret_cast<InterpretedFrame*>(frame); |
| + SharedFunctionInfo* shared = interpreted_frame->function()->shared(); |
| + BytecodeArray* bytecode_array = shared->bytecode_array(); |
| + int bytecode_offset = interpreted_frame->GetBytecodeOffset(); |
| + interpreter::Bytecode bytecode = |
| + interpreter::Bytecodes::FromByte(bytecode_array->get(bytecode_offset)); |
| + return isolate_->interpreter()->GetHandler(bytecode); |
| + } else { |
| + after_break_target_ = NULL; |
| + if (!LiveEdit::SetAfterBreakTarget(this)) { |
| + // Continue just after the slot. |
| + after_break_target_ = frame->pc(); |
| + } |
| + return isolate_->heap()->undefined_value(); |
| + } |
| } |
| @@ -1623,10 +1649,11 @@ void Debug::GetStepinPositions(JavaScriptFrame* frame, StackFrame::Id frame_id, |
| summary = GetFirstFrameSummary(frame); |
| } |
| - // Find range of break points starting from the break point where execution |
| - // has stopped. The code offset points to the instruction after the current |
| - // possibly a break location, too. Subtract one to exclude it from the search. |
| - int call_offset = summary.code_offset() - 1; |
| + // 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. |
| + int call_offset = summary.code_offset(); |
| + if (!frame->is_interpreted()) call_offset--; |
| List<BreakLocation> locations; |
| BreakLocation::FromCodeOffsetSameStatement(debug_info, call_offset, |
| &locations); |