| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 1577 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1588 } | 1588 } |
| 1589 | 1589 |
| 1590 return NULL; | 1590 return NULL; |
| 1591 } | 1591 } |
| 1592 | 1592 |
| 1593 | 1593 |
| 1594 static bool IsDropableFrame(StackFrame* frame) { | 1594 static bool IsDropableFrame(StackFrame* frame) { |
| 1595 return !frame->is_exit(); | 1595 return !frame->is_exit(); |
| 1596 } | 1596 } |
| 1597 | 1597 |
| 1598 // Fills result array with statuses of functions. Modifies the stack | 1598 |
| 1599 // removing all listed function if possible and if do_drop is true. | 1599 // Describes a set of call frames that execute any of listed functions. |
| 1600 static const char* DropActivationsInActiveThread( | 1600 // Finding no such frames does not mean error. |
| 1601 Handle<JSArray> shared_info_array, Handle<JSArray> result, bool do_drop, | 1601 class MultipleFunctionTarget { |
| 1602 Zone* zone) { | 1602 public: |
| 1603 MultipleFunctionTarget(Handle<JSArray> shared_info_array, |
| 1604 Handle<JSArray> result) |
| 1605 : m_shared_info_array(shared_info_array), |
| 1606 m_result(result) {} |
| 1607 bool MatchActivation(StackFrame* frame, |
| 1608 LiveEdit::FunctionPatchabilityStatus status) { |
| 1609 return CheckActivation(m_shared_info_array, m_result, frame, status); |
| 1610 } |
| 1611 const char* GetNotFoundMessage() { |
| 1612 return NULL; |
| 1613 } |
| 1614 private: |
| 1615 Handle<JSArray> m_shared_info_array; |
| 1616 Handle<JSArray> m_result; |
| 1617 }; |
| 1618 |
| 1619 // Drops all call frame matched by target and all frames above them. |
| 1620 template<typename TARGET> |
| 1621 static const char* DropActivationsInActiveThreadImpl( |
| 1622 TARGET& target, bool do_drop, Zone* zone) { |
| 1603 Isolate* isolate = Isolate::Current(); | 1623 Isolate* isolate = Isolate::Current(); |
| 1604 Debug* debug = isolate->debug(); | 1624 Debug* debug = isolate->debug(); |
| 1605 ZoneScope scope(isolate, DELETE_ON_EXIT); | 1625 ZoneScope scope(isolate, DELETE_ON_EXIT); |
| 1606 Vector<StackFrame*> frames = CreateStackMap(zone); | 1626 Vector<StackFrame*> frames = CreateStackMap(zone); |
| 1607 | 1627 |
| 1608 int array_len = Smi::cast(shared_info_array->length())->value(); | |
| 1609 | 1628 |
| 1610 int top_frame_index = -1; | 1629 int top_frame_index = -1; |
| 1611 int frame_index = 0; | 1630 int frame_index = 0; |
| 1612 for (; frame_index < frames.length(); frame_index++) { | 1631 for (; frame_index < frames.length(); frame_index++) { |
| 1613 StackFrame* frame = frames[frame_index]; | 1632 StackFrame* frame = frames[frame_index]; |
| 1614 if (frame->id() == debug->break_frame_id()) { | 1633 if (frame->id() == debug->break_frame_id()) { |
| 1615 top_frame_index = frame_index; | 1634 top_frame_index = frame_index; |
| 1616 break; | 1635 break; |
| 1617 } | 1636 } |
| 1618 if (CheckActivation(shared_info_array, result, frame, | 1637 if (target.MatchActivation( |
| 1619 LiveEdit::FUNCTION_BLOCKED_UNDER_NATIVE_CODE)) { | 1638 frame, LiveEdit::FUNCTION_BLOCKED_UNDER_NATIVE_CODE)) { |
| 1620 // We are still above break_frame. It is not a target frame, | 1639 // We are still above break_frame. It is not a target frame, |
| 1621 // it is a problem. | 1640 // it is a problem. |
| 1622 return "Debugger mark-up on stack is not found"; | 1641 return "Debugger mark-up on stack is not found"; |
| 1623 } | 1642 } |
| 1624 } | 1643 } |
| 1625 | 1644 |
| 1626 if (top_frame_index == -1) { | 1645 if (top_frame_index == -1) { |
| 1627 // We haven't found break frame, but no function is blocking us anyway. | 1646 // We haven't found break frame, but no function is blocking us anyway. |
| 1628 return NULL; | 1647 return target.GetNotFoundMessage(); |
| 1629 } | 1648 } |
| 1630 | 1649 |
| 1631 bool target_frame_found = false; | 1650 bool target_frame_found = false; |
| 1632 int bottom_js_frame_index = top_frame_index; | 1651 int bottom_js_frame_index = top_frame_index; |
| 1633 bool c_code_found = false; | 1652 bool c_code_found = false; |
| 1634 | 1653 |
| 1635 for (; frame_index < frames.length(); frame_index++) { | 1654 for (; frame_index < frames.length(); frame_index++) { |
| 1636 StackFrame* frame = frames[frame_index]; | 1655 StackFrame* frame = frames[frame_index]; |
| 1637 if (!IsDropableFrame(frame)) { | 1656 if (!IsDropableFrame(frame)) { |
| 1638 c_code_found = true; | 1657 c_code_found = true; |
| 1639 break; | 1658 break; |
| 1640 } | 1659 } |
| 1641 if (CheckActivation(shared_info_array, result, frame, | 1660 if (target.MatchActivation( |
| 1642 LiveEdit::FUNCTION_BLOCKED_ON_ACTIVE_STACK)) { | 1661 frame, LiveEdit::FUNCTION_BLOCKED_ON_ACTIVE_STACK)) { |
| 1643 target_frame_found = true; | 1662 target_frame_found = true; |
| 1644 bottom_js_frame_index = frame_index; | 1663 bottom_js_frame_index = frame_index; |
| 1645 } | 1664 } |
| 1646 } | 1665 } |
| 1647 | 1666 |
| 1648 if (c_code_found) { | 1667 if (c_code_found) { |
| 1649 // There is a C frames on stack. Check that there are no target frames | 1668 // There is a C frames on stack. Check that there are no target frames |
| 1650 // below them. | 1669 // below them. |
| 1651 for (; frame_index < frames.length(); frame_index++) { | 1670 for (; frame_index < frames.length(); frame_index++) { |
| 1652 StackFrame* frame = frames[frame_index]; | 1671 StackFrame* frame = frames[frame_index]; |
| 1653 if (frame->is_java_script()) { | 1672 if (frame->is_java_script()) { |
| 1654 if (CheckActivation(shared_info_array, result, frame, | 1673 if (target.MatchActivation( |
| 1655 LiveEdit::FUNCTION_BLOCKED_UNDER_NATIVE_CODE)) { | 1674 frame, LiveEdit::FUNCTION_BLOCKED_UNDER_NATIVE_CODE)) { |
| 1656 // Cannot drop frame under C frames. | 1675 // Cannot drop frame under C frames. |
| 1657 return NULL; | 1676 return NULL; |
| 1658 } | 1677 } |
| 1659 } | 1678 } |
| 1660 } | 1679 } |
| 1661 } | 1680 } |
| 1662 | 1681 |
| 1663 if (!do_drop) { | 1682 if (!do_drop) { |
| 1664 // We are in check-only mode. | 1683 // We are in check-only mode. |
| 1665 return NULL; | 1684 return NULL; |
| 1666 } | 1685 } |
| 1667 | 1686 |
| 1668 if (!target_frame_found) { | 1687 if (!target_frame_found) { |
| 1669 // Nothing to drop. | 1688 // Nothing to drop. |
| 1670 return NULL; | 1689 return target.GetNotFoundMessage(); |
| 1671 } | 1690 } |
| 1672 | 1691 |
| 1673 Debug::FrameDropMode drop_mode = Debug::FRAMES_UNTOUCHED; | 1692 Debug::FrameDropMode drop_mode = Debug::FRAMES_UNTOUCHED; |
| 1674 Object** restarter_frame_function_pointer = NULL; | 1693 Object** restarter_frame_function_pointer = NULL; |
| 1675 const char* error_message = DropFrames(frames, top_frame_index, | 1694 const char* error_message = DropFrames(frames, top_frame_index, |
| 1676 bottom_js_frame_index, &drop_mode, | 1695 bottom_js_frame_index, &drop_mode, |
| 1677 &restarter_frame_function_pointer); | 1696 &restarter_frame_function_pointer); |
| 1678 | 1697 |
| 1679 if (error_message != NULL) { | 1698 if (error_message != NULL) { |
| 1680 return error_message; | 1699 return error_message; |
| 1681 } | 1700 } |
| 1682 | 1701 |
| 1683 // Adjust break_frame after some frames has been dropped. | 1702 // Adjust break_frame after some frames has been dropped. |
| 1684 StackFrame::Id new_id = StackFrame::NO_ID; | 1703 StackFrame::Id new_id = StackFrame::NO_ID; |
| 1685 for (int i = bottom_js_frame_index + 1; i < frames.length(); i++) { | 1704 for (int i = bottom_js_frame_index + 1; i < frames.length(); i++) { |
| 1686 if (frames[i]->type() == StackFrame::JAVA_SCRIPT) { | 1705 if (frames[i]->type() == StackFrame::JAVA_SCRIPT) { |
| 1687 new_id = frames[i]->id(); | 1706 new_id = frames[i]->id(); |
| 1688 break; | 1707 break; |
| 1689 } | 1708 } |
| 1690 } | 1709 } |
| 1691 debug->FramesHaveBeenDropped(new_id, drop_mode, | 1710 debug->FramesHaveBeenDropped(new_id, drop_mode, |
| 1692 restarter_frame_function_pointer); | 1711 restarter_frame_function_pointer); |
| 1712 return NULL; |
| 1713 } |
| 1714 |
| 1715 // Fills result array with statuses of functions. Modifies the stack |
| 1716 // removing all listed function if possible and if do_drop is true. |
| 1717 static const char* DropActivationsInActiveThread( |
| 1718 Handle<JSArray> shared_info_array, Handle<JSArray> result, bool do_drop, |
| 1719 Zone* zone) { |
| 1720 MultipleFunctionTarget target(shared_info_array, result); |
| 1721 |
| 1722 const char* message = |
| 1723 DropActivationsInActiveThreadImpl(target, do_drop, zone); |
| 1724 if (message) { |
| 1725 return message; |
| 1726 } |
| 1727 |
| 1728 int array_len = Smi::cast(shared_info_array->length())->value(); |
| 1693 | 1729 |
| 1694 // Replace "blocked on active" with "replaced on active" status. | 1730 // Replace "blocked on active" with "replaced on active" status. |
| 1695 for (int i = 0; i < array_len; i++) { | 1731 for (int i = 0; i < array_len; i++) { |
| 1696 if (result->GetElement(i) == | 1732 if (result->GetElement(i) == |
| 1697 Smi::FromInt(LiveEdit::FUNCTION_BLOCKED_ON_ACTIVE_STACK)) { | 1733 Smi::FromInt(LiveEdit::FUNCTION_BLOCKED_ON_ACTIVE_STACK)) { |
| 1698 Handle<Object> replaced( | 1734 Handle<Object> replaced( |
| 1699 Smi::FromInt(LiveEdit::FUNCTION_REPLACED_ON_ACTIVE_STACK)); | 1735 Smi::FromInt(LiveEdit::FUNCTION_REPLACED_ON_ACTIVE_STACK)); |
| 1700 SetElementNonStrict(result, i, replaced); | 1736 SetElementNonStrict(result, i, replaced); |
| 1701 } | 1737 } |
| 1702 } | 1738 } |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1759 if (error_message != NULL) { | 1795 if (error_message != NULL) { |
| 1760 // Add error message as an array extra element. | 1796 // Add error message as an array extra element. |
| 1761 Vector<const char> vector_message(error_message, StrLength(error_message)); | 1797 Vector<const char> vector_message(error_message, StrLength(error_message)); |
| 1762 Handle<String> str = FACTORY->NewStringFromAscii(vector_message); | 1798 Handle<String> str = FACTORY->NewStringFromAscii(vector_message); |
| 1763 SetElementNonStrict(result, len, str); | 1799 SetElementNonStrict(result, len, str); |
| 1764 } | 1800 } |
| 1765 return result; | 1801 return result; |
| 1766 } | 1802 } |
| 1767 | 1803 |
| 1768 | 1804 |
| 1805 // Describes a single callframe a target. Not finding this frame |
| 1806 // means an error. |
| 1807 class SingleFrameTarget { |
| 1808 public: |
| 1809 explicit SingleFrameTarget(JavaScriptFrame* frame) : m_frame(frame) {} |
| 1810 |
| 1811 bool MatchActivation(StackFrame* frame, |
| 1812 LiveEdit::FunctionPatchabilityStatus status) { |
| 1813 if (frame->fp() == m_frame->fp()) { |
| 1814 m_saved_status = status; |
| 1815 return true; |
| 1816 } |
| 1817 return false; |
| 1818 } |
| 1819 const char* GetNotFoundMessage() { |
| 1820 return "Failed to found requested frame"; |
| 1821 } |
| 1822 LiveEdit::FunctionPatchabilityStatus saved_status() { |
| 1823 return m_saved_status; |
| 1824 } |
| 1825 private: |
| 1826 JavaScriptFrame* m_frame; |
| 1827 LiveEdit::FunctionPatchabilityStatus m_saved_status; |
| 1828 }; |
| 1829 |
| 1830 |
| 1831 // Finds a drops required frame and all frames above. |
| 1832 // Returns error message or NULL. |
| 1833 const char* LiveEdit::RestartFrame(JavaScriptFrame* frame, Zone* zone) { |
| 1834 SingleFrameTarget target(frame); |
| 1835 |
| 1836 return DropActivationsInActiveThreadImpl(target, true, zone); |
| 1837 } |
| 1838 |
| 1839 |
| 1769 LiveEditFunctionTracker::LiveEditFunctionTracker(Isolate* isolate, | 1840 LiveEditFunctionTracker::LiveEditFunctionTracker(Isolate* isolate, |
| 1770 FunctionLiteral* fun) | 1841 FunctionLiteral* fun) |
| 1771 : isolate_(isolate) { | 1842 : isolate_(isolate) { |
| 1772 if (isolate_->active_function_info_listener() != NULL) { | 1843 if (isolate_->active_function_info_listener() != NULL) { |
| 1773 isolate_->active_function_info_listener()->FunctionStarted(fun); | 1844 isolate_->active_function_info_listener()->FunctionStarted(fun); |
| 1774 } | 1845 } |
| 1775 } | 1846 } |
| 1776 | 1847 |
| 1777 | 1848 |
| 1778 LiveEditFunctionTracker::~LiveEditFunctionTracker() { | 1849 LiveEditFunctionTracker::~LiveEditFunctionTracker() { |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1826 | 1897 |
| 1827 bool LiveEditFunctionTracker::IsActive(Isolate* isolate) { | 1898 bool LiveEditFunctionTracker::IsActive(Isolate* isolate) { |
| 1828 return false; | 1899 return false; |
| 1829 } | 1900 } |
| 1830 | 1901 |
| 1831 #endif // ENABLE_DEBUGGER_SUPPORT | 1902 #endif // ENABLE_DEBUGGER_SUPPORT |
| 1832 | 1903 |
| 1833 | 1904 |
| 1834 | 1905 |
| 1835 } } // namespace v8::internal | 1906 } } // namespace v8::internal |
| OLD | NEW |