Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(289)

Side by Side Diff: src/debug.cc

Issue 2693002: More precise break points and stepping when debugging... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 10 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/debug.h ('k') | src/flag-definitions.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 111 matching lines...) Expand 10 before | Expand all | Expand 10 after
122 rinfo()->data() - debug_info_->shared()->start_position()); 122 rinfo()->data() - debug_info_->shared()->start_position());
123 } 123 }
124 // Always update the position as we don't want that to be before the 124 // Always update the position as we don't want that to be before the
125 // statement position. 125 // statement position.
126 position_ = static_cast<int>( 126 position_ = static_cast<int>(
127 rinfo()->data() - debug_info_->shared()->start_position()); 127 rinfo()->data() - debug_info_->shared()->start_position());
128 ASSERT(position_ >= 0); 128 ASSERT(position_ >= 0);
129 ASSERT(statement_position_ >= 0); 129 ASSERT(statement_position_ >= 0);
130 } 130 }
131 131
132 // Check for breakable code target. Look in the original code as setting 132 if (IsDebugBreakSlot()) {
133 // break points can cause the code targets in the running (debugged) code to 133 // There is always a possible break point at a debug break slot.
134 // be of a different kind than in the original code. 134 break_point_++;
135 if (RelocInfo::IsCodeTarget(rmode())) { 135 return;
136 } else if (RelocInfo::IsCodeTarget(rmode())) {
137 // Check for breakable code target. Look in the original code as setting
138 // break points can cause the code targets in the running (debugged) code
139 // to be of a different kind than in the original code.
136 Address target = original_rinfo()->target_address(); 140 Address target = original_rinfo()->target_address();
137 Code* code = Code::GetCodeFromTargetAddress(target); 141 Code* code = Code::GetCodeFromTargetAddress(target);
138 if ((code->is_inline_cache_stub() && 142 if ((code->is_inline_cache_stub() &&
139 code->kind() != Code::BINARY_OP_IC) || 143 code->kind() != Code::BINARY_OP_IC) ||
140 RelocInfo::IsConstructCall(rmode())) { 144 RelocInfo::IsConstructCall(rmode())) {
141 break_point_++; 145 break_point_++;
142 return; 146 return;
143 } 147 }
144 if (code->kind() == Code::STUB) { 148 if (code->kind() == Code::STUB) {
145 if (IsDebuggerStatement()) { 149 if (IsDebuggerStatement()) {
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after
322 // the same code is flooded with break points twice. Flooding the same 326 // the same code is flooded with break points twice. Flooding the same
323 // function twice might happen when stepping in a function with an exception 327 // function twice might happen when stepping in a function with an exception
324 // handler as the handler and the function is the same. 328 // handler as the handler and the function is the same.
325 if (IsDebugBreak()) { 329 if (IsDebugBreak()) {
326 return; 330 return;
327 } 331 }
328 332
329 if (RelocInfo::IsJSReturn(rmode())) { 333 if (RelocInfo::IsJSReturn(rmode())) {
330 // Patch the frame exit code with a break point. 334 // Patch the frame exit code with a break point.
331 SetDebugBreakAtReturn(); 335 SetDebugBreakAtReturn();
336 } else if (IsDebugBreakSlot()) {
337 // Patch the code in the break slot.
338 SetDebugBreakAtSlot();
332 } else { 339 } else {
333 // Patch the IC call. 340 // Patch the IC call.
334 SetDebugBreakAtIC(); 341 SetDebugBreakAtIC();
335 } 342 }
336 ASSERT(IsDebugBreak()); 343 ASSERT(IsDebugBreak());
337 } 344 }
338 345
339 346
340 void BreakLocationIterator::ClearDebugBreak() { 347 void BreakLocationIterator::ClearDebugBreak() {
341 // Debugger statement always calls debugger. No need to modify it. 348 // Debugger statement always calls debugger. No need to modify it.
342 if (IsDebuggerStatement()) { 349 if (IsDebuggerStatement()) {
343 return; 350 return;
344 } 351 }
345 352
346 if (RelocInfo::IsJSReturn(rmode())) { 353 if (RelocInfo::IsJSReturn(rmode())) {
347 // Restore the frame exit code. 354 // Restore the frame exit code.
348 ClearDebugBreakAtReturn(); 355 ClearDebugBreakAtReturn();
356 } else if (IsDebugBreakSlot()) {
357 // Restore the code in the break slot.
358 ClearDebugBreakAtSlot();
349 } else { 359 } else {
350 // Patch the IC call. 360 // Patch the IC call.
351 ClearDebugBreakAtIC(); 361 ClearDebugBreakAtIC();
352 } 362 }
353 ASSERT(!IsDebugBreak()); 363 ASSERT(!IsDebugBreak());
354 } 364 }
355 365
356 366
357 void BreakLocationIterator::PrepareStepIn() { 367 void BreakLocationIterator::PrepareStepIn() {
358 HandleScope scope; 368 HandleScope scope;
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
410 420
411 bool BreakLocationIterator::HasBreakPoint() { 421 bool BreakLocationIterator::HasBreakPoint() {
412 return debug_info_->HasBreakPoint(code_position()); 422 return debug_info_->HasBreakPoint(code_position());
413 } 423 }
414 424
415 425
416 // Check whether there is a debug break at the current position. 426 // Check whether there is a debug break at the current position.
417 bool BreakLocationIterator::IsDebugBreak() { 427 bool BreakLocationIterator::IsDebugBreak() {
418 if (RelocInfo::IsJSReturn(rmode())) { 428 if (RelocInfo::IsJSReturn(rmode())) {
419 return IsDebugBreakAtReturn(); 429 return IsDebugBreakAtReturn();
430 } else if (IsDebugBreakSlot()) {
431 return IsDebugBreakAtSlot();
420 } else { 432 } else {
421 return Debug::IsDebugBreak(rinfo()->target_address()); 433 return Debug::IsDebugBreak(rinfo()->target_address());
422 } 434 }
423 } 435 }
424 436
425 437
426 void BreakLocationIterator::SetDebugBreakAtIC() { 438 void BreakLocationIterator::SetDebugBreakAtIC() {
427 // Patch the original code with the current address as the current address 439 // Patch the original code with the current address as the current address
428 // might have changed by the inline caching since the code was copied. 440 // might have changed by the inline caching since the code was copied.
429 original_rinfo()->set_target_address(rinfo()->target_address()); 441 original_rinfo()->set_target_address(rinfo()->target_address());
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
471 if (code->is_keyed_store_stub()) KeyedStoreIC::RestoreInlinedVersion(pc()); 483 if (code->is_keyed_store_stub()) KeyedStoreIC::RestoreInlinedVersion(pc());
472 } 484 }
473 } 485 }
474 486
475 487
476 bool BreakLocationIterator::IsDebuggerStatement() { 488 bool BreakLocationIterator::IsDebuggerStatement() {
477 return RelocInfo::DEBUG_BREAK == rmode(); 489 return RelocInfo::DEBUG_BREAK == rmode();
478 } 490 }
479 491
480 492
493 bool BreakLocationIterator::IsDebugBreakSlot() {
494 return RelocInfo::DEBUG_BREAK_SLOT == rmode();
495 }
496
497
481 Object* BreakLocationIterator::BreakPointObjects() { 498 Object* BreakLocationIterator::BreakPointObjects() {
482 return debug_info_->GetBreakPointObjects(code_position()); 499 return debug_info_->GetBreakPointObjects(code_position());
483 } 500 }
484 501
485 502
486 // Clear out all the debug break code. This is ONLY supposed to be used when 503 // Clear out all the debug break code. This is ONLY supposed to be used when
487 // shutting down the debugger as it will leave the break point information in 504 // shutting down the debugger as it will leave the break point information in
488 // DebugInfo even though the code is patched back to the non break point state. 505 // DebugInfo even though the code is patched back to the non break point state.
489 void BreakLocationIterator::ClearAllDebugBreak() { 506 void BreakLocationIterator::ClearAllDebugBreak() {
490 while (!Done()) { 507 while (!Done()) {
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
566 583
567 // Default break enabled. 584 // Default break enabled.
568 bool Debug::disable_break_ = false; 585 bool Debug::disable_break_ = false;
569 586
570 // Default call debugger on uncaught exception. 587 // Default call debugger on uncaught exception.
571 bool Debug::break_on_exception_ = false; 588 bool Debug::break_on_exception_ = false;
572 bool Debug::break_on_uncaught_exception_ = true; 589 bool Debug::break_on_uncaught_exception_ = true;
573 590
574 Handle<Context> Debug::debug_context_ = Handle<Context>(); 591 Handle<Context> Debug::debug_context_ = Handle<Context>();
575 Code* Debug::debug_break_return_ = NULL; 592 Code* Debug::debug_break_return_ = NULL;
593 Code* Debug::debug_break_slot_ = NULL;
576 594
577 595
578 void ScriptCache::Add(Handle<Script> script) { 596 void ScriptCache::Add(Handle<Script> script) {
579 // Create an entry in the hash map for the script. 597 // Create an entry in the hash map for the script.
580 int id = Smi::cast(script->id())->value(); 598 int id = Smi::cast(script->id())->value();
581 HashMap::Entry* entry = 599 HashMap::Entry* entry =
582 HashMap::Lookup(reinterpret_cast<void*>(id), Hash(id), true); 600 HashMap::Lookup(reinterpret_cast<void*>(id), Hash(id), true);
583 if (entry->value != NULL) { 601 if (entry->value != NULL) {
584 ASSERT(*script == *reinterpret_cast<Script**>(entry->value)); 602 ASSERT(*script == *reinterpret_cast<Script**>(entry->value));
585 return; 603 return;
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
649 } 667 }
650 668
651 669
652 void Debug::Setup(bool create_heap_objects) { 670 void Debug::Setup(bool create_heap_objects) {
653 ThreadInit(); 671 ThreadInit();
654 if (create_heap_objects) { 672 if (create_heap_objects) {
655 // Get code to handle debug break on return. 673 // Get code to handle debug break on return.
656 debug_break_return_ = 674 debug_break_return_ =
657 Builtins::builtin(Builtins::Return_DebugBreak); 675 Builtins::builtin(Builtins::Return_DebugBreak);
658 ASSERT(debug_break_return_->IsCode()); 676 ASSERT(debug_break_return_->IsCode());
677 // Get code to handle debug break in debug break slots.
678 debug_break_slot_ =
679 Builtins::builtin(Builtins::Slot_DebugBreak);
680 ASSERT(debug_break_slot_->IsCode());
659 } 681 }
660 } 682 }
661 683
662 684
663 void Debug::HandleWeakDebugInfo(v8::Persistent<v8::Value> obj, void* data) { 685 void Debug::HandleWeakDebugInfo(v8::Persistent<v8::Value> obj, void* data) {
664 DebugInfoListNode* node = reinterpret_cast<DebugInfoListNode*>(data); 686 DebugInfoListNode* node = reinterpret_cast<DebugInfoListNode*>(data);
665 RemoveDebugInfo(node->debug_info()); 687 RemoveDebugInfo(node->debug_info());
666 #ifdef DEBUG 688 #ifdef DEBUG
667 node = Debug::debug_info_list_; 689 node = Debug::debug_info_list_;
668 while (node != NULL) { 690 while (node != NULL) {
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after
817 839
818 // Set the flag indicating that preemption happened during debugging. 840 // Set the flag indicating that preemption happened during debugging.
819 void Debug::PreemptionWhileInDebugger() { 841 void Debug::PreemptionWhileInDebugger() {
820 ASSERT(InDebugger()); 842 ASSERT(InDebugger());
821 Debug::set_interrupts_pending(PREEMPT); 843 Debug::set_interrupts_pending(PREEMPT);
822 } 844 }
823 845
824 846
825 void Debug::Iterate(ObjectVisitor* v) { 847 void Debug::Iterate(ObjectVisitor* v) {
826 v->VisitPointer(BitCast<Object**, Code**>(&(debug_break_return_))); 848 v->VisitPointer(BitCast<Object**, Code**>(&(debug_break_return_)));
849 v->VisitPointer(BitCast<Object**, Code**>(&(debug_break_slot_)));
827 } 850 }
828 851
829 852
830 Object* Debug::Break(Arguments args) { 853 Object* Debug::Break(Arguments args) {
831 HandleScope scope; 854 HandleScope scope;
832 ASSERT(args.length() == 0); 855 ASSERT(args.length() == 0);
833 856
834 thread_local_.frames_are_dropped_ = false; 857 thread_local_.frames_are_dropped_ = false;
835 858
836 // Get the top-most JavaScript frame. 859 // Get the top-most JavaScript frame.
(...skipping 787 matching lines...) Expand 10 before | Expand all | Expand 10 after
1624 // Get the code which is actually executing. 1647 // Get the code which is actually executing.
1625 Handle<Code> frame_code(frame->code()); 1648 Handle<Code> frame_code(frame->code());
1626 ASSERT(frame_code.is_identical_to(code)); 1649 ASSERT(frame_code.is_identical_to(code));
1627 #endif 1650 #endif
1628 1651
1629 // Find the call address in the running code. This address holds the call to 1652 // Find the call address in the running code. This address holds the call to
1630 // either a DebugBreakXXX or to the debug break return entry code if the 1653 // either a DebugBreakXXX or to the debug break return entry code if the
1631 // break point is still active after processing the break point. 1654 // break point is still active after processing the break point.
1632 Address addr = frame->pc() - Assembler::kCallTargetAddressOffset; 1655 Address addr = frame->pc() - Assembler::kCallTargetAddressOffset;
1633 1656
1634 // Check if the location is at JS exit. 1657 // Check if the location is at JS exit or debug break slot.
1635 bool at_js_return = false; 1658 bool at_js_return = false;
1636 bool break_at_js_return_active = false; 1659 bool break_at_js_return_active = false;
1660 bool at_debug_break_slot = false;
1637 RelocIterator it(debug_info->code()); 1661 RelocIterator it(debug_info->code());
1638 while (!it.done()) { 1662 while (!it.done() && !at_js_return && !at_debug_break_slot) {
1639 if (RelocInfo::IsJSReturn(it.rinfo()->rmode())) { 1663 if (RelocInfo::IsJSReturn(it.rinfo()->rmode())) {
1640 at_js_return = (it.rinfo()->pc() == 1664 at_js_return = (it.rinfo()->pc() ==
1641 addr - Assembler::kPatchReturnSequenceAddressOffset); 1665 addr - Assembler::kPatchReturnSequenceAddressOffset);
1642 break_at_js_return_active = it.rinfo()->IsPatchedReturnSequence(); 1666 break_at_js_return_active = it.rinfo()->IsPatchedReturnSequence();
1643 } 1667 }
1668 if (RelocInfo::IsDebugBreakSlot(it.rinfo()->rmode())) {
1669 at_debug_break_slot = (it.rinfo()->pc() ==
1670 addr - Assembler::kPatchDebugBreakSlotAddressOffset);
1671 }
1644 it.next(); 1672 it.next();
1645 } 1673 }
1646 1674
1647 // Handle the jump to continue execution after break point depending on the 1675 // Handle the jump to continue execution after break point depending on the
1648 // break location. 1676 // break location.
1649 if (at_js_return) { 1677 if (at_js_return) {
1650 // If the break point as return is still active jump to the corresponding 1678 // If the break point as return is still active jump to the corresponding
1651 // place in the original code. If not the break point was removed during 1679 // place in the original code. If not the break point was removed during
1652 // break point processing. 1680 // break point processing.
1653 if (break_at_js_return_active) { 1681 if (break_at_js_return_active) {
1654 addr += original_code->instruction_start() - code->instruction_start(); 1682 addr += original_code->instruction_start() - code->instruction_start();
1655 } 1683 }
1656 1684
1657 // Move back to where the call instruction sequence started. 1685 // Move back to where the call instruction sequence started.
1658 thread_local_.after_break_target_ = 1686 thread_local_.after_break_target_ =
1659 addr - Assembler::kPatchReturnSequenceAddressOffset; 1687 addr - Assembler::kPatchReturnSequenceAddressOffset;
1660 } else { 1688 } else if (at_debug_break_slot) {
1661 // Check if there still is a debug break call at the target address. If the 1689 // Address of where the debug break slot starts.
1662 // break point has been removed it will have disappeared. If it have 1690 addr = addr - Assembler::kPatchDebugBreakSlotAddressOffset;
1663 // disappeared don't try to look in the original code as the running code
1664 // will have the right address. This takes care of the case where the last
1665 // break point is removed from the function and therefore no "original code"
1666 // is available. If the debug break call is still there find the address in
1667 // the original code.
1668 if (IsDebugBreak(Assembler::target_address_at(addr))) {
1669 // If the break point is still there find the call address which was
1670 // overwritten in the original code by the call to DebugBreakXXX.
1671 1691
1672 // Find the corresponding address in the original code. 1692 // Continue just after the slot.
1673 addr += original_code->instruction_start() - code->instruction_start(); 1693 thread_local_.after_break_target_ = addr + Assembler::kDebugBreakSlotLength;
1674 } 1694 } else if (IsDebugBreak(Assembler::target_address_at(addr))) {
1695 // We now know that there is still a debug break call at the target address,
1696 // so the break point is still there and the original code will hold the
1697 // address to jump to in order to complete the call which is replaced by a
1698 // call to DebugBreakXXX.
1699
1700 // Find the corresponding address in the original code.
1701 addr += original_code->instruction_start() - code->instruction_start();
1675 1702
1676 // Install jump to the call address in the original code. This will be the 1703 // Install jump to the call address in the original code. This will be the
1677 // call which was overwritten by the call to DebugBreakXXX. 1704 // call which was overwritten by the call to DebugBreakXXX.
1678 thread_local_.after_break_target_ = Assembler::target_address_at(addr); 1705 thread_local_.after_break_target_ = Assembler::target_address_at(addr);
1706 } else {
1707 // There is no longer a break point present. Don't try to look in the
1708 // original code as the running code will have the right address. This takes
1709 // care of the case where the last break point is removed from the function
1710 // and therefore no "original code" is available.
1711 thread_local_.after_break_target_ = Assembler::target_address_at(addr);
1679 } 1712 }
1680 } 1713 }
1681 1714
1682 1715
1683 void Debug::FramesHaveBeenDropped(StackFrame::Id new_break_frame_id) { 1716 void Debug::FramesHaveBeenDropped(StackFrame::Id new_break_frame_id) {
1684 thread_local_.frames_are_dropped_ = true; 1717 thread_local_.frames_are_dropped_ = true;
1685 thread_local_.break_frame_id_ = new_break_frame_id; 1718 thread_local_.break_frame_id_ = new_break_frame_id;
1686 } 1719 }
1687 1720
1688 1721
(...skipping 1164 matching lines...) Expand 10 before | Expand all | Expand 10 after
2853 { 2886 {
2854 Locker locker; 2887 Locker locker;
2855 Debugger::CallMessageDispatchHandler(); 2888 Debugger::CallMessageDispatchHandler();
2856 } 2889 }
2857 } 2890 }
2858 } 2891 }
2859 2892
2860 #endif // ENABLE_DEBUGGER_SUPPORT 2893 #endif // ENABLE_DEBUGGER_SUPPORT
2861 2894
2862 } } // namespace v8::internal 2895 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/debug.h ('k') | src/flag-definitions.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698