| Index: src/debug.cc
|
| diff --git a/src/debug.cc b/src/debug.cc
|
| index 324d96f333fa21141415041c3640fb8af6957064..46c9e1ebdef10dfb71204d89384a06b7a6eec807 100644
|
| --- a/src/debug.cc
|
| +++ b/src/debug.cc
|
| @@ -387,40 +387,6 @@ bool BreakLocationIterator::IsStepInLocation(Isolate* isolate) {
|
| }
|
|
|
|
|
| -void BreakLocationIterator::PrepareStepIn(Isolate* isolate) {
|
| -#ifdef DEBUG
|
| - HandleScope scope(isolate);
|
| - // Step in can only be prepared if currently positioned on an IC call,
|
| - // construct call or CallFunction stub call.
|
| - Address target = rinfo()->target_address();
|
| - Handle<Code> target_code(Code::GetCodeFromTargetAddress(target));
|
| - // All the following stuff is needed only for assertion checks so the code
|
| - // is wrapped in ifdef.
|
| - Handle<Code> maybe_call_function_stub = target_code;
|
| - if (IsDebugBreak()) {
|
| - Address original_target = original_rinfo()->target_address();
|
| - maybe_call_function_stub =
|
| - Handle<Code>(Code::GetCodeFromTargetAddress(original_target));
|
| - }
|
| - bool is_call_function_stub =
|
| - (maybe_call_function_stub->kind() == Code::STUB &&
|
| - CodeStub::GetMajorKey(*maybe_call_function_stub) ==
|
| - CodeStub::CallFunction);
|
| -
|
| - // Step in through construct call requires no changes to the running code.
|
| - // Step in through getters/setters should already be prepared as well
|
| - // because caller of this function (Debug::PrepareStep) is expected to
|
| - // flood the top frame's function with one shot breakpoints.
|
| - // Step in through CallFunction stub should also be prepared by caller of
|
| - // this function (Debug::PrepareStep) which should flood target function
|
| - // with breakpoints.
|
| - DCHECK(RelocInfo::IsConstructCall(rmode()) ||
|
| - target_code->is_inline_cache_stub() ||
|
| - is_call_function_stub);
|
| -#endif
|
| -}
|
| -
|
| -
|
| // Check whether the break point is at a position which will exit the function.
|
| bool BreakLocationIterator::IsExit() const {
|
| return (RelocInfo::IsJSReturn(rmode()));
|
| @@ -1371,62 +1337,68 @@ void Debug::PrepareStep(StepAction step_action,
|
| }
|
| Handle<DebugInfo> debug_info = GetDebugInfo(shared);
|
|
|
| - // Find the break location where execution has stopped.
|
| - BreakLocationIterator it(debug_info, ALL_BREAK_LOCATIONS);
|
| - // pc points to the instruction after the current one, possibly a break
|
| - // location as well. So the "- 1" to exclude it from the search.
|
| - it.FindBreakLocationFromAddress(frame->pc() - 1);
|
| -
|
| // Compute whether or not the target is a call target.
|
| bool is_load_or_store = false;
|
| bool is_inline_cache_stub = false;
|
| bool is_at_restarted_function = false;
|
| + bool is_exit = false;
|
| + bool is_construct_call = false;
|
| Handle<Code> call_function_stub;
|
|
|
| - if (thread_local_.restarter_frame_function_pointer_ == NULL) {
|
| - if (RelocInfo::IsCodeTarget(it.rinfo()->rmode())) {
|
| - bool is_call_target = false;
|
| - Address target = it.rinfo()->target_address();
|
| - Code* code = Code::GetCodeFromTargetAddress(target);
|
| - if (code->is_call_stub()) {
|
| - is_call_target = true;
|
| - }
|
| - if (code->is_inline_cache_stub()) {
|
| - is_inline_cache_stub = true;
|
| - is_load_or_store = !is_call_target;
|
| - }
|
| -
|
| - // Check if target code is CallFunction stub.
|
| - Code* maybe_call_function_stub = code;
|
| - // If there is a breakpoint at this line look at the original code to
|
| - // check if it is a CallFunction stub.
|
| - if (it.IsDebugBreak()) {
|
| - Address original_target = it.original_rinfo()->target_address();
|
| - maybe_call_function_stub =
|
| - Code::GetCodeFromTargetAddress(original_target);
|
| - }
|
| - 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 = Handle<Code>(maybe_call_function_stub);
|
| + {
|
| + // Find the break location where execution has stopped.
|
| + DisallowHeapAllocation no_gc;
|
| + BreakLocationIterator it(debug_info, ALL_BREAK_LOCATIONS);
|
| +
|
| + // pc points to the instruction after the current one, possibly a break
|
| + // location as well. So the "- 1" to exclude it from the search.
|
| + it.FindBreakLocationFromAddress(frame->pc() - 1);
|
| +
|
| + is_exit = it.IsExit();
|
| +
|
| + if (thread_local_.restarter_frame_function_pointer_ == NULL) {
|
| + if (RelocInfo::IsCodeTarget(it.rinfo()->rmode())) {
|
| + bool is_call_target = false;
|
| + Address target = it.rinfo()->target_address();
|
| + Code* code = Code::GetCodeFromTargetAddress(target);
|
| +
|
| + is_call_target = code->is_call_stub();
|
| + is_construct_call = RelocInfo::IsConstructCall(it.rmode());
|
| + is_inline_cache_stub = code->is_inline_cache_stub();
|
| + is_load_or_store = is_inline_cache_stub && !is_call_target;
|
| +
|
| + // Check if target code is CallFunction stub.
|
| + Code* maybe_call_function_stub = code;
|
| + // If there is a breakpoint at this line look at the original code to
|
| + // check if it is a CallFunction stub.
|
| + if (it.IsDebugBreak()) {
|
| + Address original_target = it.original_rinfo()->target_address();
|
| + maybe_call_function_stub =
|
| + Code::GetCodeFromTargetAddress(original_target);
|
| + }
|
| + 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 = Handle<Code>(maybe_call_function_stub);
|
| + }
|
| }
|
| + } else {
|
| + is_at_restarted_function = true;
|
| }
|
| - } else {
|
| - is_at_restarted_function = true;
|
| }
|
|
|
| // If this is the last break code target step out is the only possibility.
|
| - if (it.IsExit() || step_action == StepOut) {
|
| + if (is_exit || step_action == StepOut) {
|
| if (step_action == StepOut) {
|
| // Skip step_count frames starting with the current one.
|
| while (step_count-- > 0 && !frames_it.done()) {
|
| frames_it.Advance();
|
| }
|
| } else {
|
| - DCHECK(it.IsExit());
|
| + DCHECK(is_exit);
|
| frames_it.Advance();
|
| }
|
| // Skip builtin functions on the stack.
|
| @@ -1443,9 +1415,9 @@ void Debug::PrepareStep(StepAction step_action,
|
| // Set target frame pointer.
|
| ActivateStepOut(frames_it.frame());
|
| }
|
| - } else if (!(is_inline_cache_stub || RelocInfo::IsConstructCall(it.rmode()) ||
|
| - !call_function_stub.is_null() || is_at_restarted_function)
|
| - || step_action == StepNext || step_action == StepMin) {
|
| + } else if (!(is_inline_cache_stub || is_construct_call ||
|
| + !call_function_stub.is_null() || is_at_restarted_function) ||
|
| + step_action == StepNext || step_action == StepMin) {
|
| // Step next or step min.
|
|
|
| // Fill the current function with one-shot break points.
|
| @@ -1532,7 +1504,15 @@ void Debug::PrepareStep(StepAction step_action,
|
| }
|
|
|
| // Step in or Step in min
|
| - it.PrepareStepIn(isolate_);
|
| + // Step in through construct call requires no changes to the running code.
|
| + // Step in through getters/setters should already be prepared as well
|
| + // because caller of this function (Debug::PrepareStep) is expected to
|
| + // flood the top frame's function with one shot breakpoints.
|
| + // Step in through CallFunction stub should also be prepared by caller of
|
| + // this function (Debug::PrepareStep) which should flood target function
|
| + // with breakpoints.
|
| + DCHECK(is_construct_call || is_inline_cache_stub ||
|
| + !call_function_stub.is_null());
|
| ActivateStepIn(frame);
|
| }
|
| }
|
|
|