Index: src/debug.cc |
diff --git a/src/debug.cc b/src/debug.cc |
index b7bf3e39aa08bc12d88df301247a0c5513a810e6..c3c0dcb667028d21893f713012ff72a414cf4fda 100644 |
--- a/src/debug.cc |
+++ b/src/debug.cc |
@@ -117,7 +117,6 @@ void BreakLocation::Iterator::Next() { |
continue; |
} |
- // Check for break at return. |
if (RelocInfo::IsJSReturn(rmode())) { |
// Set the positions to the end of the function. |
if (debug_info_->shared()->HasSourceCode()) { |
@@ -127,43 +126,21 @@ void BreakLocation::Iterator::Next() { |
position_ = 0; |
} |
statement_position_ = position_; |
- break_index_++; |
break; |
} |
- if (RelocInfo::IsCodeTarget(rmode())) { |
- // Check for breakable code target. Look in the original code as setting |
- // break points can cause the code targets in the running (debugged) code |
- // to be of a different kind than in the original code. |
- Address target = original_rinfo()->target_address(); |
- Code* code = Code::GetCodeFromTargetAddress(target); |
- |
- if (RelocInfo::IsConstructCall(rmode()) || code->is_call_stub()) { |
- break_index_++; |
- break; |
- } |
- |
- if (code->kind() == Code::STUB && |
- CodeStub::GetMajorKey(code) == CodeStub::CallFunction) { |
- break_index_++; |
- break; |
- } |
- } |
- |
- // Skip below if we only want locations for calls and returns. |
- if (type_ == CALLS_AND_RETURNS) continue; |
- |
- if (RelocInfo::IsDebuggerStatement(rmode())) { |
- break_index_++; |
+ if (RelocInfo::IsDebugBreakSlot(rmode()) && |
+ (type_ == ALL_BREAK_LOCATIONS || |
+ RelocInfo::DebugBreakIsCall(rinfo()->data()))) { |
break; |
} |
- if (RelocInfo::IsDebugBreakSlot(rmode()) && type_ != CALLS_AND_RETURNS) { |
- // There is always a possible break point at a debug break slot. |
- break_index_++; |
+ if (RelocInfo::IsDebuggerStatement(rmode()) && |
+ type_ == ALL_BREAK_LOCATIONS) { |
break; |
} |
} |
+ break_index_++; |
} |
@@ -311,9 +288,6 @@ void BreakLocation::SetDebugBreak() { |
} else if (IsDebugBreakSlot()) { |
// Patch the code in the break slot. |
SetDebugBreakAtSlot(); |
- } else { |
- // Patch the IC call. |
- SetDebugBreakAtIC(); |
} |
DCHECK(IsDebugBreak()); |
} |
@@ -329,13 +303,6 @@ void BreakLocation::ClearDebugBreak() { |
} else if (IsDebugBreakSlot()) { |
// Restore the code in the break slot. |
RestoreFromOriginal(Assembler::kDebugBreakSlotLength); |
- } else { |
- // Restore the IC call. |
- rinfo().set_target_address(original_rinfo().target_address()); |
- // Some ICs store data in the feedback vector. Clear this to ensure we |
- // won't miss future stepping requirements. |
- SharedFunctionInfo* shared = debug_info_->shared(); |
- shared->feedback_vector()->ClearICSlots(shared); |
} |
DCHECK(!IsDebugBreak()); |
} |
@@ -348,13 +315,7 @@ void BreakLocation::RestoreFromOriginal(int length_in_bytes) { |
bool BreakLocation::IsStepInLocation() const { |
- if (IsConstructCall()) return true; |
- if (RelocInfo::IsCodeTarget(rmode())) { |
- HandleScope scope(debug_info_->GetIsolate()); |
- Handle<Code> target_code = CodeTarget(); |
- return target_code->is_call_stub(); |
- } |
- return false; |
+ return IsConstructCall() || IsCall(); |
} |
@@ -363,52 +324,8 @@ bool BreakLocation::IsDebugBreak() const { |
return rinfo().IsPatchedReturnSequence(); |
} else if (IsDebugBreakSlot()) { |
return rinfo().IsPatchedDebugBreakSlotSequence(); |
- } else { |
- return Debug::IsDebugBreak(rinfo().target_address()); |
- } |
-} |
- |
- |
-// Find the builtin to use for invoking the debug break |
-static Handle<Code> DebugBreakForIC(Handle<Code> code, RelocInfo::Mode mode) { |
- Isolate* isolate = code->GetIsolate(); |
- |
- // Find the builtin debug break function matching the calling convention |
- // used by the call site. |
- if (code->is_inline_cache_stub()) { |
- DCHECK(code->kind() == Code::CALL_IC); |
- return isolate->builtins()->CallICStub_DebugBreak(); |
- } |
- if (RelocInfo::IsConstructCall(mode)) { |
- if (code->has_function_cache()) { |
- return isolate->builtins()->CallConstructStub_Recording_DebugBreak(); |
- } else { |
- return isolate->builtins()->CallConstructStub_DebugBreak(); |
- } |
- } |
- if (code->kind() == Code::STUB) { |
- DCHECK(CodeStub::GetMajorKey(*code) == CodeStub::CallFunction); |
- return isolate->builtins()->CallFunctionStub_DebugBreak(); |
- } |
- |
- UNREACHABLE(); |
- return Handle<Code>::null(); |
-} |
- |
- |
-void BreakLocation::SetDebugBreakAtIC() { |
- // Patch the original code with the current address as the current address |
- // might have changed by the inline caching since the code was copied. |
- original_rinfo().set_target_address(rinfo().target_address()); |
- |
- if (RelocInfo::IsCodeTarget(rmode_)) { |
- Handle<Code> target_code = CodeTarget(); |
- |
- // Patch the code to invoke the builtin debug break function matching the |
- // calling convention used by the call site. |
- Handle<Code> debug_break_code = DebugBreakForIC(target_code, rmode_); |
- rinfo().set_target_address(debug_break_code->entry()); |
} |
+ return false; |
} |
@@ -417,20 +334,6 @@ Handle<Object> BreakLocation::BreakPointObjects() const { |
} |
-Handle<Code> BreakLocation::CodeTarget() const { |
- DCHECK(IsCodeTarget()); |
- Address target = rinfo().target_address(); |
- return Handle<Code>(Code::GetCodeFromTargetAddress(target)); |
-} |
- |
- |
-Handle<Code> BreakLocation::OriginalCodeTarget() const { |
- DCHECK(IsCodeTarget()); |
- Address target = original_rinfo().target_address(); |
- return Handle<Code>(Code::GetCodeFromTargetAddress(target)); |
-} |
- |
- |
bool BreakLocation::Iterator::RinfoDone() const { |
DCHECK(reloc_iterator_.done() == reloc_iterator_original_.done()); |
return reloc_iterator_.done(); |
@@ -442,7 +345,7 @@ void BreakLocation::Iterator::RinfoNext() { |
reloc_iterator_original_.next(); |
#ifdef DEBUG |
DCHECK(reloc_iterator_.done() == reloc_iterator_original_.done()); |
- DCHECK(reloc_iterator_.done() || rmode() == original_rmode()); |
+ DCHECK(reloc_iterator_.done() || rmode() == original_rinfo()->rmode()); |
#endif |
} |
@@ -941,7 +844,7 @@ bool Debug::SetBreakPoint(Handle<JSFunction> function, |
// Find the break point and change it. |
BreakLocation location = BreakLocation::FromPosition( |
- debug_info, SOURCE_BREAK_LOCATIONS, *source_position, STATEMENT_ALIGNED); |
+ debug_info, ALL_BREAK_LOCATIONS, *source_position, STATEMENT_ALIGNED); |
*source_position = location.statement_position(); |
location.SetBreakPoint(break_point_object); |
@@ -985,7 +888,7 @@ bool Debug::SetBreakPointForScript(Handle<Script> script, |
// Find the break point and change it. |
BreakLocation location = BreakLocation::FromPosition( |
- debug_info, SOURCE_BREAK_LOCATIONS, position, alignment); |
+ debug_info, ALL_BREAK_LOCATIONS, position, alignment); |
location.SetBreakPoint(break_point_object); |
position = (alignment == STATEMENT_ALIGNED) ? location.statement_position() |
@@ -1017,7 +920,7 @@ void Debug::ClearBreakPoint(Handle<Object> break_point_object) { |
break_point_info->code_position()->value(); |
BreakLocation location = |
- BreakLocation::FromAddress(debug_info, SOURCE_BREAK_LOCATIONS, pc); |
+ BreakLocation::FromAddress(debug_info, ALL_BREAK_LOCATIONS, pc); |
location.ClearBreakPoint(break_point_object); |
// If there are no more break points left remove the debug info for this |
@@ -1238,27 +1141,7 @@ void Debug::PrepareStep(StepAction step_action, |
BreakLocation location = |
BreakLocation::FromAddress(debug_info, ALL_BREAK_LOCATIONS, call_pc); |
- if (thread_local_.restarter_frame_function_pointer_ == NULL) { |
- if (location.IsCodeTarget()) { |
- Handle<Code> target_code = location.CodeTarget(); |
- |
- // Check if target code is CallFunction stub. |
- Handle<Code> maybe_call_function_stub = target_code; |
- // If there is a breakpoint at this line look at the original code to |
- // check if it is a CallFunction stub. |
- if (location.IsDebugBreak()) { |
- maybe_call_function_stub = location.OriginalCodeTarget(); |
- } |
- if ((maybe_call_function_stub->kind() == Code::STUB && |
- CodeStub::GetMajorKey(*maybe_call_function_stub) == |
- CodeStub::CallFunction) || |
- maybe_call_function_stub->is_call_stub()) { |
- // Save reference to the code as we may need it to find out arguments |
- // count for 'step in' later. |
- call_function_stub = maybe_call_function_stub; |
- } |
- } |
- } else { |
+ if (thread_local_.restarter_frame_function_pointer_ != NULL) { |
is_at_restarted_function = true; |
} |
@@ -1297,24 +1180,7 @@ void Debug::PrepareStep(StepAction step_action, |
Handle<JSFunction> restarted_function( |
JSFunction::cast(*thread_local_.restarter_frame_function_pointer_)); |
FloodWithOneShot(restarted_function); |
- } else if (!call_function_stub.is_null()) { |
- // If it's CallFunction stub ensure target function is compiled and flood |
- // it with one shot breakpoints. |
- bool is_call_ic = call_function_stub->kind() == Code::CALL_IC; |
- |
- // Find out number of arguments from the stub minor key. |
- uint32_t key = call_function_stub->stub_key(); |
- // Argc in the stub is the number of arguments passed - not the |
- // expected arguments of the called function. |
- int call_function_arg_count = is_call_ic |
- ? CallICStub::ExtractArgcFromMinorKey(CodeStub::MinorKeyFromKey(key)) |
- : CallFunctionStub::ExtractArgcFromMinorKey( |
- CodeStub::MinorKeyFromKey(key)); |
- |
- DCHECK(is_call_ic || |
- CodeStub::GetMajorKey(*call_function_stub) == |
- CodeStub::MajorKeyFromKey(key)); |
- |
+ } else if (location.IsCall()) { |
// Find target function on the expression stack. |
// Expression stack looks like this (top to bottom): |
// argN |
@@ -1322,10 +1188,10 @@ void Debug::PrepareStep(StepAction step_action, |
// arg0 |
// Receiver |
// Function to call |
- int expressions_count = frame->ComputeExpressionsCount(); |
- DCHECK(expressions_count - 2 - call_function_arg_count >= 0); |
- Object* fun = frame->GetExpression( |
- expressions_count - 2 - call_function_arg_count); |
+ int num_expressions_without_args = |
+ frame->ComputeExpressionsCount() - location.CallArgumentsCount(); |
+ DCHECK(num_expressions_without_args >= 2); |
+ Object* fun = frame->GetExpression(num_expressions_without_args - 2); |
// Flood the actual target of call/apply. |
if (fun->IsJSFunction()) { |
@@ -1338,10 +1204,9 @@ void Debug::PrepareStep(StepAction step_action, |
while (fun->IsJSFunction()) { |
Code* code = JSFunction::cast(fun)->shared()->code(); |
if (code != apply && code != call) break; |
- DCHECK(expressions_count - i - call_function_arg_count >= 0); |
- fun = frame->GetExpression(expressions_count - i - |
- call_function_arg_count); |
- i -= 1; |
+ DCHECK(num_expressions_without_args >= i); |
+ fun = frame->GetExpression(num_expressions_without_args - i); |
+ i--; |
} |
} |
@@ -2209,27 +2074,6 @@ void Debug::SetAfterBreakTarget(JavaScriptFrame* frame) { |
// Continue just after the slot. |
after_break_target_ = addr + Assembler::kDebugBreakSlotLength; |
- } else { |
- addr = Assembler::target_address_from_return_address(frame->pc()); |
- if (IsDebugBreak(Assembler::target_address_at(addr, *code))) { |
- // We now know that there is still a debug break call at the target |
- // address, so the break point is still there and the original code will |
- // hold the address to jump to in order to complete the call which is |
- // replaced by a call to DebugBreakXXX. |
- |
- // Find the corresponding address in the original code. |
- addr += original_code->instruction_start() - code->instruction_start(); |
- |
- // Install jump to the call address in the original code. This will be the |
- // call which was overwritten by the call to DebugBreakXXX. |
- after_break_target_ = Assembler::target_address_at(addr, *original_code); |
- } else { |
- // There is no longer a break point present. Don't try to look in the |
- // original code as the running code will have the right address. This |
- // takes care of the case where the last break point is removed from the |
- // function and therefore no "original code" is available. |
- after_break_target_ = Assembler::target_address_at(addr, *code); |
- } |
} |
} |