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