OLD | NEW |
1 // Copyright 2006-2008 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2008 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 500 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
511 // Threading support. | 511 // Threading support. |
512 void Debug::ThreadInit() { | 512 void Debug::ThreadInit() { |
513 thread_local_.break_count_ = 0; | 513 thread_local_.break_count_ = 0; |
514 thread_local_.break_id_ = 0; | 514 thread_local_.break_id_ = 0; |
515 thread_local_.break_frame_id_ = StackFrame::NO_ID; | 515 thread_local_.break_frame_id_ = StackFrame::NO_ID; |
516 thread_local_.last_step_action_ = StepNone; | 516 thread_local_.last_step_action_ = StepNone; |
517 thread_local_.last_statement_position_ = RelocInfo::kNoPosition; | 517 thread_local_.last_statement_position_ = RelocInfo::kNoPosition; |
518 thread_local_.step_count_ = 0; | 518 thread_local_.step_count_ = 0; |
519 thread_local_.last_fp_ = 0; | 519 thread_local_.last_fp_ = 0; |
520 thread_local_.step_into_fp_ = 0; | 520 thread_local_.step_into_fp_ = 0; |
| 521 thread_local_.step_out_fp_ = 0; |
521 thread_local_.after_break_target_ = 0; | 522 thread_local_.after_break_target_ = 0; |
522 thread_local_.debugger_entry_ = NULL; | 523 thread_local_.debugger_entry_ = NULL; |
523 thread_local_.pending_interrupts_ = 0; | 524 thread_local_.pending_interrupts_ = 0; |
524 } | 525 } |
525 | 526 |
526 | 527 |
527 JSCallerSavedBuffer Debug::registers_; | 528 JSCallerSavedBuffer Debug::registers_; |
528 Debug::ThreadLocal Debug::thread_local_; | 529 Debug::ThreadLocal Debug::thread_local_; |
529 | 530 |
530 | 531 |
(...skipping 326 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
857 | 858 |
858 // If there is one or more real break points check whether any of these are | 859 // If there is one or more real break points check whether any of these are |
859 // triggered. | 860 // triggered. |
860 Handle<Object> break_points_hit(Heap::undefined_value()); | 861 Handle<Object> break_points_hit(Heap::undefined_value()); |
861 if (break_location_iterator.HasBreakPoint()) { | 862 if (break_location_iterator.HasBreakPoint()) { |
862 Handle<Object> break_point_objects = | 863 Handle<Object> break_point_objects = |
863 Handle<Object>(break_location_iterator.BreakPointObjects()); | 864 Handle<Object>(break_location_iterator.BreakPointObjects()); |
864 break_points_hit = CheckBreakPoints(break_point_objects); | 865 break_points_hit = CheckBreakPoints(break_point_objects); |
865 } | 866 } |
866 | 867 |
867 // Notify debugger if a real break point is triggered or if performing single | 868 // If step out is active skip everything until the frame where we need to step |
868 // stepping with no more steps to perform. Otherwise do another step. | 869 // out to is reached, unless real breakpoint is hit. |
869 if (!break_points_hit->IsUndefined() || | 870 if (Debug::StepOutActive() && frame->fp() != Debug::step_out_fp() && |
870 (thread_local_.last_step_action_ != StepNone && | 871 break_points_hit->IsUndefined() ) { |
871 thread_local_.step_count_ == 0)) { | 872 // Step count should always be 0 for StepOut. |
| 873 ASSERT(thread_local_.step_count_ == 0); |
| 874 } else if (!break_points_hit->IsUndefined() || |
| 875 (thread_local_.last_step_action_ != StepNone && |
| 876 thread_local_.step_count_ == 0)) { |
| 877 // Notify debugger if a real break point is triggered or if performing |
| 878 // single stepping with no more steps to perform. Otherwise do another step. |
| 879 |
872 // Clear all current stepping setup. | 880 // Clear all current stepping setup. |
873 ClearStepping(); | 881 ClearStepping(); |
874 | 882 |
875 // Notify the debug event listeners. | 883 // Notify the debug event listeners. |
876 Debugger::OnDebugBreak(break_points_hit, false); | 884 Debugger::OnDebugBreak(break_points_hit, false); |
877 } else if (thread_local_.last_step_action_ != StepNone) { | 885 } else if (thread_local_.last_step_action_ != StepNone) { |
878 // Hold on to last step action as it is cleared by the call to | 886 // Hold on to last step action as it is cleared by the call to |
879 // ClearStepping. | 887 // ClearStepping. |
880 StepAction step_action = thread_local_.last_step_action_; | 888 StepAction step_action = thread_local_.last_step_action_; |
881 int step_count = thread_local_.step_count_; | 889 int step_count = thread_local_.step_count_; |
(...skipping 215 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1097 } | 1105 } |
1098 } | 1106 } |
1099 | 1107 |
1100 | 1108 |
1101 void Debug::PrepareStep(StepAction step_action, int step_count) { | 1109 void Debug::PrepareStep(StepAction step_action, int step_count) { |
1102 HandleScope scope; | 1110 HandleScope scope; |
1103 ASSERT(Debug::InDebugger()); | 1111 ASSERT(Debug::InDebugger()); |
1104 | 1112 |
1105 // Remember this step action and count. | 1113 // Remember this step action and count. |
1106 thread_local_.last_step_action_ = step_action; | 1114 thread_local_.last_step_action_ = step_action; |
1107 thread_local_.step_count_ = step_count; | 1115 if (step_action == StepOut) { |
| 1116 // For step out target frame will be found on the stack so there is no need |
| 1117 // to set step counter for it. It's expected to always be 0 for StepOut. |
| 1118 thread_local_.step_count_ = 0; |
| 1119 } else { |
| 1120 thread_local_.step_count_ = step_count; |
| 1121 } |
1108 | 1122 |
1109 // Get the frame where the execution has stopped and skip the debug frame if | 1123 // Get the frame where the execution has stopped and skip the debug frame if |
1110 // any. The debug frame will only be present if execution was stopped due to | 1124 // any. The debug frame will only be present if execution was stopped due to |
1111 // hitting a break point. In other situations (e.g. unhandled exception) the | 1125 // hitting a break point. In other situations (e.g. unhandled exception) the |
1112 // debug frame is not present. | 1126 // debug frame is not present. |
1113 StackFrame::Id id = break_frame_id(); | 1127 StackFrame::Id id = break_frame_id(); |
1114 if (id == StackFrame::NO_ID) { | 1128 if (id == StackFrame::NO_ID) { |
1115 // If there is no JavaScript stack don't do anything. | 1129 // If there is no JavaScript stack don't do anything. |
1116 return; | 1130 return; |
1117 } | 1131 } |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1176 if (maybe_call_function_stub->kind() == Code::STUB && | 1190 if (maybe_call_function_stub->kind() == Code::STUB && |
1177 maybe_call_function_stub->major_key() == CodeStub::CallFunction) { | 1191 maybe_call_function_stub->major_key() == CodeStub::CallFunction) { |
1178 // Save reference to the code as we may need it to find out arguments | 1192 // Save reference to the code as we may need it to find out arguments |
1179 // count for 'step in' later. | 1193 // count for 'step in' later. |
1180 call_function_stub = Handle<Code>(maybe_call_function_stub); | 1194 call_function_stub = Handle<Code>(maybe_call_function_stub); |
1181 } | 1195 } |
1182 } | 1196 } |
1183 | 1197 |
1184 // If this is the last break code target step out is the only possibility. | 1198 // If this is the last break code target step out is the only possibility. |
1185 if (it.IsExit() || step_action == StepOut) { | 1199 if (it.IsExit() || step_action == StepOut) { |
| 1200 if (step_action == StepOut) { |
| 1201 // Skip step_count frames starting with the current one. |
| 1202 while(step_count-- > 0 && !frames_it.done()) { |
| 1203 frames_it.Advance(); |
| 1204 } |
| 1205 } else { |
| 1206 ASSERT(it.IsExit()); |
| 1207 frames_it.Advance(); |
| 1208 } |
| 1209 // Skip builtin functions on the stack. |
| 1210 while(!frames_it.done() && |
| 1211 JSFunction::cast(frames_it.frame()->function())->IsBuiltin()) { |
| 1212 frames_it.Advance(); |
| 1213 } |
1186 // Step out: If there is a JavaScript caller frame, we need to | 1214 // Step out: If there is a JavaScript caller frame, we need to |
1187 // flood it with breakpoints. | 1215 // flood it with breakpoints. |
1188 frames_it.Advance(); | |
1189 if (!frames_it.done()) { | 1216 if (!frames_it.done()) { |
1190 // Fill the function to return to with one-shot break points. | 1217 // Fill the function to return to with one-shot break points. |
1191 JSFunction* function = JSFunction::cast(frames_it.frame()->function()); | 1218 JSFunction* function = JSFunction::cast(frames_it.frame()->function()); |
1192 FloodWithOneShot(Handle<SharedFunctionInfo>(function->shared())); | 1219 FloodWithOneShot(Handle<SharedFunctionInfo>(function->shared())); |
| 1220 // Set target frame pointer. |
| 1221 ActivateStepOut(frames_it.frame()); |
1193 } | 1222 } |
1194 } else if (!(is_inline_cache_stub || RelocInfo::IsConstructCall(it.rmode()) || | 1223 } else if (!(is_inline_cache_stub || RelocInfo::IsConstructCall(it.rmode()) || |
1195 !call_function_stub.is_null()) | 1224 !call_function_stub.is_null()) |
1196 || step_action == StepNext || step_action == StepMin) { | 1225 || step_action == StepNext || step_action == StepMin) { |
1197 // Step next or step min. | 1226 // Step next or step min. |
1198 | 1227 |
1199 // Fill the current function with one-shot break points. | 1228 // Fill the current function with one-shot break points. |
1200 FloodWithOneShot(shared); | 1229 FloodWithOneShot(shared); |
1201 | 1230 |
1202 // Remember source position and frame to handle step next. | 1231 // Remember source position and frame to handle step next. |
(...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1438 } | 1467 } |
1439 } | 1468 } |
1440 } | 1469 } |
1441 } | 1470 } |
1442 | 1471 |
1443 | 1472 |
1444 void Debug::ClearStepping() { | 1473 void Debug::ClearStepping() { |
1445 // Clear the various stepping setup. | 1474 // Clear the various stepping setup. |
1446 ClearOneShot(); | 1475 ClearOneShot(); |
1447 ClearStepIn(); | 1476 ClearStepIn(); |
| 1477 ClearStepOut(); |
1448 ClearStepNext(); | 1478 ClearStepNext(); |
1449 | 1479 |
1450 // Clear multiple step counter. | 1480 // Clear multiple step counter. |
1451 thread_local_.step_count_ = 0; | 1481 thread_local_.step_count_ = 0; |
1452 } | 1482 } |
1453 | 1483 |
1454 // Clears all the one-shot break points that are currently set. Normally this | 1484 // Clears all the one-shot break points that are currently set. Normally this |
1455 // function is called each time a break point is hit as one shot break points | 1485 // function is called each time a break point is hit as one shot break points |
1456 // are used to support stepping. | 1486 // are used to support stepping. |
1457 void Debug::ClearOneShot() { | 1487 void Debug::ClearOneShot() { |
1458 // The current implementation just runs through all the breakpoints. When the | 1488 // The current implementation just runs through all the breakpoints. When the |
1459 // last break point for a function is removed that function is automatically | 1489 // last break point for a function is removed that function is automatically |
1460 // removed from the list. | 1490 // removed from the list. |
1461 | 1491 |
1462 DebugInfoListNode* node = debug_info_list_; | 1492 DebugInfoListNode* node = debug_info_list_; |
1463 while (node != NULL) { | 1493 while (node != NULL) { |
1464 BreakLocationIterator it(node->debug_info(), ALL_BREAK_LOCATIONS); | 1494 BreakLocationIterator it(node->debug_info(), ALL_BREAK_LOCATIONS); |
1465 while (!it.Done()) { | 1495 while (!it.Done()) { |
1466 it.ClearOneShot(); | 1496 it.ClearOneShot(); |
1467 it.Next(); | 1497 it.Next(); |
1468 } | 1498 } |
1469 node = node->next(); | 1499 node = node->next(); |
1470 } | 1500 } |
1471 } | 1501 } |
1472 | 1502 |
1473 | 1503 |
1474 void Debug::ActivateStepIn(StackFrame* frame) { | 1504 void Debug::ActivateStepIn(StackFrame* frame) { |
| 1505 ASSERT(!StepOutActive()); |
1475 thread_local_.step_into_fp_ = frame->fp(); | 1506 thread_local_.step_into_fp_ = frame->fp(); |
1476 } | 1507 } |
1477 | 1508 |
1478 | 1509 |
1479 void Debug::ClearStepIn() { | 1510 void Debug::ClearStepIn() { |
1480 thread_local_.step_into_fp_ = 0; | 1511 thread_local_.step_into_fp_ = 0; |
1481 } | 1512 } |
1482 | 1513 |
1483 | 1514 |
| 1515 void Debug::ActivateStepOut(StackFrame* frame) { |
| 1516 ASSERT(!StepInActive()); |
| 1517 thread_local_.step_out_fp_ = frame->fp(); |
| 1518 } |
| 1519 |
| 1520 |
| 1521 void Debug::ClearStepOut() { |
| 1522 thread_local_.step_out_fp_ = 0; |
| 1523 } |
| 1524 |
| 1525 |
1484 void Debug::ClearStepNext() { | 1526 void Debug::ClearStepNext() { |
1485 thread_local_.last_step_action_ = StepNone; | 1527 thread_local_.last_step_action_ = StepNone; |
1486 thread_local_.last_statement_position_ = RelocInfo::kNoPosition; | 1528 thread_local_.last_statement_position_ = RelocInfo::kNoPosition; |
1487 thread_local_.last_fp_ = 0; | 1529 thread_local_.last_fp_ = 0; |
1488 } | 1530 } |
1489 | 1531 |
1490 | 1532 |
1491 bool Debug::EnsureCompiled(Handle<SharedFunctionInfo> shared) { | 1533 bool Debug::EnsureCompiled(Handle<SharedFunctionInfo> shared) { |
1492 if (shared->is_compiled()) return true; | 1534 if (shared->is_compiled()) return true; |
1493 return CompileLazyShared(shared, CLEAR_EXCEPTION, 0); | 1535 return CompileLazyShared(shared, CLEAR_EXCEPTION, 0); |
(...skipping 1186 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2680 | 2722 |
2681 | 2723 |
2682 void LockingCommandMessageQueue::Clear() { | 2724 void LockingCommandMessageQueue::Clear() { |
2683 ScopedLock sl(lock_); | 2725 ScopedLock sl(lock_); |
2684 queue_.Clear(); | 2726 queue_.Clear(); |
2685 } | 2727 } |
2686 | 2728 |
2687 #endif // ENABLE_DEBUGGER_SUPPORT | 2729 #endif // ENABLE_DEBUGGER_SUPPORT |
2688 | 2730 |
2689 } } // namespace v8::internal | 2731 } } // namespace v8::internal |
OLD | NEW |