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

Side by Side Diff: src/debug/liveedit.cc

Issue 1492393003: Reland of [debugger] do not restart frames that reference new.target for liveedit. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 5 years 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
« no previous file with comments | « src/debug/liveedit.h ('k') | src/debug/liveedit.js » ('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 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/debug/liveedit.h" 5 #include "src/debug/liveedit.h"
6 6
7 #include "src/ast/scopeinfo.h" 7 #include "src/ast/scopeinfo.h"
8 #include "src/ast/scopes.h" 8 #include "src/ast/scopes.h"
9 #include "src/code-stubs.h" 9 #include "src/code-stubs.h"
10 #include "src/compilation-cache.h" 10 #include "src/compilation-cache.h"
(...skipping 1642 matching lines...) Expand 10 before | Expand all | Expand 10 after
1653 } 1653 }
1654 1654
1655 return NULL; 1655 return NULL;
1656 } 1656 }
1657 1657
1658 1658
1659 // Describes a set of call frames that execute any of listed functions. 1659 // Describes a set of call frames that execute any of listed functions.
1660 // Finding no such frames does not mean error. 1660 // Finding no such frames does not mean error.
1661 class MultipleFunctionTarget { 1661 class MultipleFunctionTarget {
1662 public: 1662 public:
1663 MultipleFunctionTarget(Handle<JSArray> shared_info_array, 1663 MultipleFunctionTarget(Handle<JSArray> old_shared_array,
1664 Handle<JSArray> result) 1664 Handle<JSArray> new_shared_array,
1665 : m_shared_info_array(shared_info_array), 1665 Handle<JSArray> result)
1666 m_result(result) {} 1666 : old_shared_array_(old_shared_array),
1667 new_shared_array_(new_shared_array),
1668 result_(result) {}
1667 bool MatchActivation(StackFrame* frame, 1669 bool MatchActivation(StackFrame* frame,
1668 LiveEdit::FunctionPatchabilityStatus status) { 1670 LiveEdit::FunctionPatchabilityStatus status) {
1669 return CheckActivation(m_shared_info_array, m_result, frame, status); 1671 return CheckActivation(old_shared_array_, result_, frame, status);
1670 } 1672 }
1671 const char* GetNotFoundMessage() const { 1673 const char* GetNotFoundMessage() const {
1672 return NULL; 1674 return NULL;
1673 } 1675 }
1676 bool FrameUsesNewTarget(StackFrame* frame) {
1677 if (!frame->is_java_script()) return false;
1678 JavaScriptFrame* jsframe = JavaScriptFrame::cast(frame);
1679 Handle<SharedFunctionInfo> old_shared(jsframe->function()->shared());
1680 Isolate* isolate = old_shared->GetIsolate();
1681 int len = GetArrayLength(old_shared_array_);
1682 // Find corresponding new shared function info and return whether it
1683 // references new.target.
1684 for (int i = 0; i < len; i++) {
1685 HandleScope scope(isolate);
1686 Handle<Object> old_element =
1687 Object::GetElement(isolate, old_shared_array_, i).ToHandleChecked();
1688 if (!old_shared.is_identical_to(UnwrapSharedFunctionInfoFromJSValue(
1689 Handle<JSValue>::cast(old_element)))) {
1690 continue;
1691 }
1692
1693 Handle<Object> new_element =
1694 Object::GetElement(isolate, new_shared_array_, i).ToHandleChecked();
1695 if (new_element->IsUndefined()) return false;
1696 Handle<SharedFunctionInfo> new_shared =
1697 UnwrapSharedFunctionInfoFromJSValue(
1698 Handle<JSValue>::cast(new_element));
1699 if (new_shared->scope_info()->HasNewTarget()) {
1700 SetElementSloppy(
1701 result_, i,
1702 Handle<Smi>(
1703 Smi::FromInt(
1704 LiveEdit::FUNCTION_BLOCKED_NO_NEW_TARGET_ON_RESTART),
1705 isolate));
1706 return true;
1707 }
1708 return false;
1709 }
1710 return false;
1711 }
1712
1674 private: 1713 private:
1675 Handle<JSArray> m_shared_info_array; 1714 Handle<JSArray> old_shared_array_;
1676 Handle<JSArray> m_result; 1715 Handle<JSArray> new_shared_array_;
1716 Handle<JSArray> result_;
1677 }; 1717 };
1678 1718
1679 1719
1680 // Drops all call frame matched by target and all frames above them. 1720 // Drops all call frame matched by target and all frames above them.
1681 template <typename TARGET> 1721 template <typename TARGET>
1682 static const char* DropActivationsInActiveThreadImpl(Isolate* isolate, 1722 static const char* DropActivationsInActiveThreadImpl(Isolate* isolate,
1683 TARGET& target, // NOLINT 1723 TARGET& target, // NOLINT
1684 bool do_drop) { 1724 bool do_drop) {
1685 Debug* debug = isolate->debug(); 1725 Debug* debug = isolate->debug();
1686 Zone zone; 1726 Zone zone;
(...skipping 26 matching lines...) Expand all
1713 bool non_droppable_frame_found = false; 1753 bool non_droppable_frame_found = false;
1714 LiveEdit::FunctionPatchabilityStatus non_droppable_reason; 1754 LiveEdit::FunctionPatchabilityStatus non_droppable_reason;
1715 1755
1716 for (; frame_index < frames.length(); frame_index++) { 1756 for (; frame_index < frames.length(); frame_index++) {
1717 StackFrame* frame = frames[frame_index]; 1757 StackFrame* frame = frames[frame_index];
1718 if (frame->is_exit()) { 1758 if (frame->is_exit()) {
1719 non_droppable_frame_found = true; 1759 non_droppable_frame_found = true;
1720 non_droppable_reason = LiveEdit::FUNCTION_BLOCKED_UNDER_NATIVE_CODE; 1760 non_droppable_reason = LiveEdit::FUNCTION_BLOCKED_UNDER_NATIVE_CODE;
1721 break; 1761 break;
1722 } 1762 }
1723 if (frame->is_java_script() && 1763 if (frame->is_java_script()) {
1724 JavaScriptFrame::cast(frame)->function()->shared()->is_generator()) { 1764 SharedFunctionInfo* shared =
1725 non_droppable_frame_found = true; 1765 JavaScriptFrame::cast(frame)->function()->shared();
1726 non_droppable_reason = LiveEdit::FUNCTION_BLOCKED_UNDER_GENERATOR; 1766 if (shared->is_generator()) {
1727 break; 1767 non_droppable_frame_found = true;
1768 non_droppable_reason = LiveEdit::FUNCTION_BLOCKED_UNDER_GENERATOR;
1769 break;
1770 }
1728 } 1771 }
1729 if (target.MatchActivation( 1772 if (target.MatchActivation(
1730 frame, LiveEdit::FUNCTION_BLOCKED_ON_ACTIVE_STACK)) { 1773 frame, LiveEdit::FUNCTION_BLOCKED_ON_ACTIVE_STACK)) {
1731 target_frame_found = true; 1774 target_frame_found = true;
1732 bottom_js_frame_index = frame_index; 1775 bottom_js_frame_index = frame_index;
1733 } 1776 }
1734 } 1777 }
1735 1778
1736 if (non_droppable_frame_found) { 1779 if (non_droppable_frame_found) {
1737 // There is a C or generator frame on stack. We can't drop C frames, and we 1780 // There is a C or generator frame on stack. We can't drop C frames, and we
1738 // can't restart generators. Check that there are no target frames below 1781 // can't restart generators. Check that there are no target frames below
1739 // them. 1782 // them.
1740 for (; frame_index < frames.length(); frame_index++) { 1783 for (; frame_index < frames.length(); frame_index++) {
1741 StackFrame* frame = frames[frame_index]; 1784 StackFrame* frame = frames[frame_index];
1742 if (frame->is_java_script()) { 1785 if (frame->is_java_script()) {
1743 if (target.MatchActivation(frame, non_droppable_reason)) { 1786 if (target.MatchActivation(frame, non_droppable_reason)) {
1744 // Fail. 1787 // Fail.
1745 return NULL; 1788 return NULL;
1746 } 1789 }
1747 } 1790 }
1748 } 1791 }
1749 } 1792 }
1750 1793
1794 // We cannot restart a frame that uses new.target.
1795 if (target.FrameUsesNewTarget(frames[bottom_js_frame_index])) return NULL;
1796
1751 if (!do_drop) { 1797 if (!do_drop) {
1752 // We are in check-only mode. 1798 // We are in check-only mode.
1753 return NULL; 1799 return NULL;
1754 } 1800 }
1755 1801
1756 if (!target_frame_found) { 1802 if (!target_frame_found) {
1757 // Nothing to drop. 1803 // Nothing to drop.
1758 return target.GetNotFoundMessage(); 1804 return target.GetNotFoundMessage();
1759 } 1805 }
1760 1806
(...skipping 17 matching lines...) Expand all
1778 } 1824 }
1779 debug->FramesHaveBeenDropped( 1825 debug->FramesHaveBeenDropped(
1780 new_id, drop_mode, restarter_frame_function_pointer); 1826 new_id, drop_mode, restarter_frame_function_pointer);
1781 return NULL; 1827 return NULL;
1782 } 1828 }
1783 1829
1784 1830
1785 // Fills result array with statuses of functions. Modifies the stack 1831 // Fills result array with statuses of functions. Modifies the stack
1786 // removing all listed function if possible and if do_drop is true. 1832 // removing all listed function if possible and if do_drop is true.
1787 static const char* DropActivationsInActiveThread( 1833 static const char* DropActivationsInActiveThread(
1788 Handle<JSArray> shared_info_array, Handle<JSArray> result, bool do_drop) { 1834 Handle<JSArray> old_shared_array, Handle<JSArray> new_shared_array,
1789 MultipleFunctionTarget target(shared_info_array, result); 1835 Handle<JSArray> result, bool do_drop) {
1790 Isolate* isolate = shared_info_array->GetIsolate(); 1836 MultipleFunctionTarget target(old_shared_array, new_shared_array, result);
1837 Isolate* isolate = old_shared_array->GetIsolate();
1791 1838
1792 const char* message = 1839 const char* message =
1793 DropActivationsInActiveThreadImpl(isolate, target, do_drop); 1840 DropActivationsInActiveThreadImpl(isolate, target, do_drop);
1794 if (message) { 1841 if (message) {
1795 return message; 1842 return message;
1796 } 1843 }
1797 1844
1798 int array_len = GetArrayLength(shared_info_array); 1845 int array_len = GetArrayLength(old_shared_array);
1799 1846
1800 // Replace "blocked on active" with "replaced on active" status. 1847 // Replace "blocked on active" with "replaced on active" status.
1801 for (int i = 0; i < array_len; i++) { 1848 for (int i = 0; i < array_len; i++) {
1802 Handle<Object> obj = 1849 Handle<Object> obj =
1803 Object::GetElement(isolate, result, i).ToHandleChecked(); 1850 Object::GetElement(isolate, result, i).ToHandleChecked();
1804 if (*obj == Smi::FromInt(LiveEdit::FUNCTION_BLOCKED_ON_ACTIVE_STACK)) { 1851 if (*obj == Smi::FromInt(LiveEdit::FUNCTION_BLOCKED_ON_ACTIVE_STACK)) {
1805 Handle<Object> replaced( 1852 Handle<Object> replaced(
1806 Smi::FromInt(LiveEdit::FUNCTION_REPLACED_ON_ACTIVE_STACK), isolate); 1853 Smi::FromInt(LiveEdit::FUNCTION_REPLACED_ON_ACTIVE_STACK), isolate);
1807 SetElementSloppy(result, i, replaced); 1854 SetElementSloppy(result, i, replaced);
1808 } 1855 }
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
1844 } 1891 }
1845 } 1892 }
1846 } 1893 }
1847 1894
1848 return found_suspended_activations; 1895 return found_suspended_activations;
1849 } 1896 }
1850 1897
1851 1898
1852 class InactiveThreadActivationsChecker : public ThreadVisitor { 1899 class InactiveThreadActivationsChecker : public ThreadVisitor {
1853 public: 1900 public:
1854 InactiveThreadActivationsChecker(Handle<JSArray> shared_info_array, 1901 InactiveThreadActivationsChecker(Handle<JSArray> old_shared_array,
1855 Handle<JSArray> result) 1902 Handle<JSArray> result)
1856 : shared_info_array_(shared_info_array), result_(result), 1903 : old_shared_array_(old_shared_array),
1857 has_blocked_functions_(false) { 1904 result_(result),
1858 } 1905 has_blocked_functions_(false) {}
1859 void VisitThread(Isolate* isolate, ThreadLocalTop* top) { 1906 void VisitThread(Isolate* isolate, ThreadLocalTop* top) {
1860 for (StackFrameIterator it(isolate, top); !it.done(); it.Advance()) { 1907 for (StackFrameIterator it(isolate, top); !it.done(); it.Advance()) {
1861 has_blocked_functions_ |= CheckActivation( 1908 has_blocked_functions_ |=
1862 shared_info_array_, result_, it.frame(), 1909 CheckActivation(old_shared_array_, result_, it.frame(),
1863 LiveEdit::FUNCTION_BLOCKED_ON_OTHER_STACK); 1910 LiveEdit::FUNCTION_BLOCKED_ON_OTHER_STACK);
1864 } 1911 }
1865 } 1912 }
1866 bool HasBlockedFunctions() { 1913 bool HasBlockedFunctions() {
1867 return has_blocked_functions_; 1914 return has_blocked_functions_;
1868 } 1915 }
1869 1916
1870 private: 1917 private:
1871 Handle<JSArray> shared_info_array_; 1918 Handle<JSArray> old_shared_array_;
1872 Handle<JSArray> result_; 1919 Handle<JSArray> result_;
1873 bool has_blocked_functions_; 1920 bool has_blocked_functions_;
1874 }; 1921 };
1875 1922
1876 1923
1877 Handle<JSArray> LiveEdit::CheckAndDropActivations( 1924 Handle<JSArray> LiveEdit::CheckAndDropActivations(
1878 Handle<JSArray> shared_info_array, bool do_drop) { 1925 Handle<JSArray> old_shared_array, Handle<JSArray> new_shared_array,
1879 Isolate* isolate = shared_info_array->GetIsolate(); 1926 bool do_drop) {
1880 int len = GetArrayLength(shared_info_array); 1927 Isolate* isolate = old_shared_array->GetIsolate();
1928 int len = GetArrayLength(old_shared_array);
1881 1929
1882 DCHECK(shared_info_array->HasFastElements()); 1930 DCHECK(old_shared_array->HasFastElements());
1883 Handle<FixedArray> shared_info_array_elements( 1931 Handle<FixedArray> old_shared_array_elements(
1884 FixedArray::cast(shared_info_array->elements())); 1932 FixedArray::cast(old_shared_array->elements()));
1885 1933
1886 Handle<JSArray> result = isolate->factory()->NewJSArray(len); 1934 Handle<JSArray> result = isolate->factory()->NewJSArray(len);
1887 Handle<FixedArray> result_elements = 1935 Handle<FixedArray> result_elements =
1888 JSObject::EnsureWritableFastElements(result); 1936 JSObject::EnsureWritableFastElements(result);
1889 1937
1890 // Fill the default values. 1938 // Fill the default values.
1891 for (int i = 0; i < len; i++) { 1939 for (int i = 0; i < len; i++) {
1892 FunctionPatchabilityStatus status = FUNCTION_AVAILABLE_FOR_PATCH; 1940 FunctionPatchabilityStatus status = FUNCTION_AVAILABLE_FOR_PATCH;
1893 result_elements->set(i, Smi::FromInt(status)); 1941 result_elements->set(i, Smi::FromInt(status));
1894 } 1942 }
1895 1943
1896 // Scan the heap for active generators -- those that are either currently 1944 // Scan the heap for active generators -- those that are either currently
1897 // running (as we wouldn't want to restart them, because we don't know where 1945 // running (as we wouldn't want to restart them, because we don't know where
1898 // to restart them from) or suspended. Fail if any one corresponds to the set 1946 // to restart them from) or suspended. Fail if any one corresponds to the set
1899 // of functions being edited. 1947 // of functions being edited.
1900 if (FindActiveGenerators(shared_info_array_elements, result_elements, len)) { 1948 if (FindActiveGenerators(old_shared_array_elements, result_elements, len)) {
1901 return result; 1949 return result;
1902 } 1950 }
1903 1951
1904 // Check inactive threads. Fail if some functions are blocked there. 1952 // Check inactive threads. Fail if some functions are blocked there.
1905 InactiveThreadActivationsChecker inactive_threads_checker(shared_info_array, 1953 InactiveThreadActivationsChecker inactive_threads_checker(old_shared_array,
1906 result); 1954 result);
1907 isolate->thread_manager()->IterateArchivedThreads( 1955 isolate->thread_manager()->IterateArchivedThreads(
1908 &inactive_threads_checker); 1956 &inactive_threads_checker);
1909 if (inactive_threads_checker.HasBlockedFunctions()) { 1957 if (inactive_threads_checker.HasBlockedFunctions()) {
1910 return result; 1958 return result;
1911 } 1959 }
1912 1960
1913 // Try to drop activations from the current stack. 1961 // Try to drop activations from the current stack.
1914 const char* error_message = 1962 const char* error_message = DropActivationsInActiveThread(
1915 DropActivationsInActiveThread(shared_info_array, result, do_drop); 1963 old_shared_array, new_shared_array, result, do_drop);
1916 if (error_message != NULL) { 1964 if (error_message != NULL) {
1917 // Add error message as an array extra element. 1965 // Add error message as an array extra element.
1918 Handle<String> str = 1966 Handle<String> str =
1919 isolate->factory()->NewStringFromAsciiChecked(error_message); 1967 isolate->factory()->NewStringFromAsciiChecked(error_message);
1920 SetElementSloppy(result, len, str); 1968 SetElementSloppy(result, len, str);
1921 } 1969 }
1922 return result; 1970 return result;
1923 } 1971 }
1924 1972
1925 1973
(...skipping 12 matching lines...) Expand all
1938 return true; 1986 return true;
1939 } 1987 }
1940 return false; 1988 return false;
1941 } 1989 }
1942 const char* GetNotFoundMessage() const { 1990 const char* GetNotFoundMessage() const {
1943 return "Failed to found requested frame"; 1991 return "Failed to found requested frame";
1944 } 1992 }
1945 LiveEdit::FunctionPatchabilityStatus saved_status() { 1993 LiveEdit::FunctionPatchabilityStatus saved_status() {
1946 return m_saved_status; 1994 return m_saved_status;
1947 } 1995 }
1996 void set_status(LiveEdit::FunctionPatchabilityStatus status) {
1997 m_saved_status = status;
1998 }
1999
2000 bool FrameUsesNewTarget(StackFrame* frame) {
2001 if (!frame->is_java_script()) return false;
2002 JavaScriptFrame* jsframe = JavaScriptFrame::cast(frame);
2003 Handle<SharedFunctionInfo> shared(jsframe->function()->shared());
2004 return shared->scope_info()->HasNewTarget();
2005 }
2006
1948 private: 2007 private:
1949 JavaScriptFrame* m_frame; 2008 JavaScriptFrame* m_frame;
1950 LiveEdit::FunctionPatchabilityStatus m_saved_status; 2009 LiveEdit::FunctionPatchabilityStatus m_saved_status;
1951 }; 2010 };
1952 2011
1953 2012
1954 // Finds a drops required frame and all frames above. 2013 // Finds a drops required frame and all frames above.
1955 // Returns error message or NULL. 2014 // Returns error message or NULL.
1956 const char* LiveEdit::RestartFrame(JavaScriptFrame* frame) { 2015 const char* LiveEdit::RestartFrame(JavaScriptFrame* frame) {
1957 SingleFrameTarget target(frame); 2016 SingleFrameTarget target(frame);
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
2001 isolate_->active_function_info_listener()->FunctionCode(code); 2060 isolate_->active_function_info_listener()->FunctionCode(code);
2002 } 2061 }
2003 2062
2004 2063
2005 bool LiveEditFunctionTracker::IsActive(Isolate* isolate) { 2064 bool LiveEditFunctionTracker::IsActive(Isolate* isolate) {
2006 return isolate->active_function_info_listener() != NULL; 2065 return isolate->active_function_info_listener() != NULL;
2007 } 2066 }
2008 2067
2009 } // namespace internal 2068 } // namespace internal
2010 } // namespace v8 2069 } // namespace v8
OLDNEW
« no previous file with comments | « src/debug/liveedit.h ('k') | src/debug/liveedit.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698