| 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 |