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 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |