| Index: src/debug.cc
|
| diff --git a/src/debug.cc b/src/debug.cc
|
| index 841b6cfa8ea69a832fec143bf5714ab31fcc3dbd..7fe9064e989a1e0bd44c1102ea2b8b5025f5dc91 100644
|
| --- a/src/debug.cc
|
| +++ b/src/debug.cc
|
| @@ -120,21 +120,37 @@ void BreakLocationIterator::Next() {
|
| DCHECK(statement_position_ >= 0);
|
| }
|
|
|
| - if (IsDebugBreakSlot()) {
|
| - // There is always a possible break point at a debug break slot.
|
| + // Check for break at return.
|
| + if (RelocInfo::IsJSReturn(rmode())) {
|
| + // Set the positions to the end of the function.
|
| + if (debug_info_->shared()->HasSourceCode()) {
|
| + position_ = debug_info_->shared()->end_position() -
|
| + debug_info_->shared()->start_position() - 1;
|
| + } else {
|
| + position_ = 0;
|
| + }
|
| + statement_position_ = position_;
|
| break_point_++;
|
| return;
|
| - } else if (RelocInfo::IsCodeTarget(rmode())) {
|
| + }
|
| +
|
| + 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 ((code->is_inline_cache_stub() &&
|
| - !code->is_binary_op_stub() &&
|
| - !code->is_compare_ic_stub() &&
|
| - !code->is_to_boolean_ic_stub()) ||
|
| - RelocInfo::IsConstructCall(rmode())) {
|
| +
|
| + if (RelocInfo::IsConstructCall(rmode()) || code->is_call_stub()) {
|
| + break_point_++;
|
| + return;
|
| + }
|
| +
|
| + // Skip below if we only want locations for calls and returns.
|
| + if (type_ == CALLS_AND_RETURNS) continue;
|
| +
|
| + if ((code->is_inline_cache_stub() && !code->is_binary_op_stub() &&
|
| + !code->is_compare_ic_stub() && !code->is_to_boolean_ic_stub())) {
|
| break_point_++;
|
| return;
|
| }
|
| @@ -157,16 +173,8 @@ void BreakLocationIterator::Next() {
|
| }
|
| }
|
|
|
| - // Check for break at return.
|
| - if (RelocInfo::IsJSReturn(rmode())) {
|
| - // Set the positions to the end of the function.
|
| - if (debug_info_->shared()->HasSourceCode()) {
|
| - position_ = debug_info_->shared()->end_position() -
|
| - debug_info_->shared()->start_position() - 1;
|
| - } else {
|
| - position_ = 0;
|
| - }
|
| - statement_position_ = position_;
|
| + if (IsDebugBreakSlot() && type_ != CALLS_AND_RETURNS) {
|
| + // There is always a possible break point at a debug break slot.
|
| break_point_++;
|
| return;
|
| }
|
| @@ -1189,7 +1197,8 @@ void Debug::ClearAllBreakPoints() {
|
| }
|
|
|
|
|
| -void Debug::FloodWithOneShot(Handle<JSFunction> function) {
|
| +void Debug::FloodWithOneShot(Handle<JSFunction> function,
|
| + BreakLocatorType type) {
|
| PrepareForBreakPoints();
|
|
|
| // Make sure the function is compiled and has set up the debug info.
|
| @@ -1200,7 +1209,7 @@ void Debug::FloodWithOneShot(Handle<JSFunction> function) {
|
| }
|
|
|
| // Flood the function with break points.
|
| - BreakLocationIterator it(GetDebugInfo(shared), ALL_BREAK_LOCATIONS);
|
| + BreakLocationIterator it(GetDebugInfo(shared), type);
|
| while (!it.Done()) {
|
| it.SetOneShot();
|
| it.Next();
|
| @@ -1216,7 +1225,7 @@ void Debug::FloodBoundFunctionWithOneShot(Handle<JSFunction> function) {
|
| if (!bindee.is_null() && bindee->IsJSFunction() &&
|
| !JSFunction::cast(*bindee)->IsFromNativeScript()) {
|
| Handle<JSFunction> bindee_function(JSFunction::cast(*bindee));
|
| - Debug::FloodWithOneShot(bindee_function);
|
| + FloodWithOneShot(bindee_function);
|
| }
|
| }
|
|
|
| @@ -1296,7 +1305,7 @@ void Debug::PrepareStep(StepAction step_action,
|
| FloodHandlerWithOneShot();
|
|
|
| // If the function on the top frame is unresolved perform step out. This will
|
| - // be the case when calling unknown functions and having the debugger stopped
|
| + // be the case when calling unknown function and having the debugger stopped
|
| // in an unhandled exception.
|
| if (!frame->function()->IsJSFunction()) {
|
| // Step out: Find the calling JavaScript frame and flood it with
|
| @@ -1354,7 +1363,7 @@ void Debug::PrepareStep(StepAction step_action,
|
| if ((maybe_call_function_stub->kind() == Code::STUB &&
|
| CodeStub::GetMajorKey(maybe_call_function_stub) ==
|
| CodeStub::CallFunction) ||
|
| - maybe_call_function_stub->kind() == Code::CALL_IC) {
|
| + 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);
|
| @@ -1395,7 +1404,9 @@ void Debug::PrepareStep(StepAction step_action,
|
| // Step next or step min.
|
|
|
| // Fill the current function with one-shot break points.
|
| - FloodWithOneShot(function);
|
| + // If we are stepping into another frame, only fill calls and returns.
|
| + FloodWithOneShot(function, step_action == StepFrame ? CALLS_AND_RETURNS
|
| + : ALL_BREAK_LOCATIONS);
|
|
|
| // Remember source position and frame to handle step next.
|
| thread_local_.last_statement_position_ =
|
| @@ -1454,7 +1465,7 @@ void Debug::PrepareStep(StepAction step_action,
|
| if (fun->IsJSFunction()) {
|
| Handle<JSFunction> js_function(JSFunction::cast(fun));
|
| if (js_function->shared()->bound()) {
|
| - Debug::FloodBoundFunctionWithOneShot(js_function);
|
| + FloodBoundFunctionWithOneShot(js_function);
|
| } else if (!js_function->IsFromNativeScript()) {
|
| // Don't step into builtins.
|
| // It will also compile target function if it's not compiled yet.
|
| @@ -1467,7 +1478,9 @@ void Debug::PrepareStep(StepAction step_action,
|
| // a call target as the function called might be a native function for
|
| // which step in will not stop. It also prepares for stepping in
|
| // getters/setters.
|
| - FloodWithOneShot(function);
|
| + // If we are stepping into another frame, only fill calls and returns.
|
| + FloodWithOneShot(function, step_action == StepFrame ? CALLS_AND_RETURNS
|
| + : ALL_BREAK_LOCATIONS);
|
|
|
| if (is_load_or_store) {
|
| // Remember source position and frame to handle step in getter/setter. If
|
| @@ -1496,15 +1509,20 @@ bool Debug::StepNextContinue(BreakLocationIterator* break_location_iterator,
|
| JavaScriptFrame* frame) {
|
| // StepNext and StepOut shouldn't bring us deeper in code, so last frame
|
| // shouldn't be a parent of current frame.
|
| - if (thread_local_.last_step_action_ == StepNext ||
|
| - thread_local_.last_step_action_ == StepOut) {
|
| + StepAction step_action = thread_local_.last_step_action_;
|
| +
|
| + if (step_action == StepNext || step_action == StepOut) {
|
| if (frame->fp() < thread_local_.last_fp_) return true;
|
| }
|
|
|
| + // We stepped into a new frame if the frame pointer changed.
|
| + if (step_action == StepFrame) {
|
| + return frame->UnpaddedFP() == thread_local_.last_fp_;
|
| + }
|
| +
|
| // If the step last action was step next or step in make sure that a new
|
| // statement is hit.
|
| - if (thread_local_.last_step_action_ == StepNext ||
|
| - thread_local_.last_step_action_ == StepIn) {
|
| + if (step_action == StepNext || step_action == StepIn) {
|
| // Never continue if returning from function.
|
| if (break_location_iterator->IsExit()) return false;
|
|
|
| @@ -1571,10 +1589,13 @@ Handle<Object> Debug::GetSourceBreakLocations(
|
|
|
|
|
| // Handle stepping into a function.
|
| -void Debug::HandleStepIn(Handle<JSFunction> function,
|
| - Handle<Object> holder,
|
| - Address fp,
|
| - bool is_constructor) {
|
| +void Debug::HandleStepIn(Handle<Object> function_obj, Handle<Object> holder,
|
| + Address fp, bool is_constructor) {
|
| + // Flood getter/setter if we either step in or step to another frame.
|
| + bool step_frame = thread_local_.last_step_action_ == StepFrame;
|
| + if (!StepInActive() && !step_frame) return;
|
| + if (!function_obj->IsJSFunction()) return;
|
| + Handle<JSFunction> function = Handle<JSFunction>::cast(function_obj);
|
| Isolate* isolate = function->GetIsolate();
|
| // If the frame pointer is not supplied by the caller find it.
|
| if (fp == 0) {
|
| @@ -1589,11 +1610,11 @@ void Debug::HandleStepIn(Handle<JSFunction> function,
|
| }
|
|
|
| // Flood the function with one-shot break points if it is called from where
|
| - // step into was requested.
|
| - if (fp == thread_local_.step_into_fp_) {
|
| + // step into was requested, or when stepping into a new frame.
|
| + if (fp == thread_local_.step_into_fp_ || step_frame) {
|
| if (function->shared()->bound()) {
|
| // Handle Function.prototype.bind
|
| - Debug::FloodBoundFunctionWithOneShot(function);
|
| + FloodBoundFunctionWithOneShot(function);
|
| } else if (!function->IsFromNativeScript()) {
|
| // Don't allow step into functions in the native context.
|
| if (function->shared()->code() ==
|
| @@ -1607,14 +1628,14 @@ void Debug::HandleStepIn(Handle<JSFunction> function,
|
| if (!holder.is_null() && holder->IsJSFunction()) {
|
| Handle<JSFunction> js_function = Handle<JSFunction>::cast(holder);
|
| if (!js_function->IsFromNativeScript()) {
|
| - Debug::FloodWithOneShot(js_function);
|
| + FloodWithOneShot(js_function);
|
| } else if (js_function->shared()->bound()) {
|
| // Handle Function.prototype.bind
|
| - Debug::FloodBoundFunctionWithOneShot(js_function);
|
| + FloodBoundFunctionWithOneShot(js_function);
|
| }
|
| }
|
| } else {
|
| - Debug::FloodWithOneShot(function);
|
| + FloodWithOneShot(function);
|
| }
|
| }
|
| }
|
|
|