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

Side by Side Diff: src/liveedit.cc

Issue 270283002: Reland "Prevent liveedit on or under generators with open activations" (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 6 years, 7 months 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 | Annotate | Revision Log
« no previous file with comments | « src/liveedit.h ('k') | src/liveedit-debugger.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 5
6 #include "v8.h" 6 #include "v8.h"
7 7
8 #include "liveedit.h" 8 #include "liveedit.h"
9 9
10 #include "code-stubs.h" 10 #include "code-stubs.h"
(...skipping 1664 matching lines...) Expand 10 before | Expand all | Expand 10 after
1675 for (Address a = unused_stack_top; 1675 for (Address a = unused_stack_top;
1676 a < unused_stack_bottom; 1676 a < unused_stack_bottom;
1677 a += kPointerSize) { 1677 a += kPointerSize) {
1678 Memory::Object_at(a) = Smi::FromInt(0); 1678 Memory::Object_at(a) = Smi::FromInt(0);
1679 } 1679 }
1680 1680
1681 return NULL; 1681 return NULL;
1682 } 1682 }
1683 1683
1684 1684
1685 static bool IsDropableFrame(StackFrame* frame) {
1686 return !frame->is_exit();
1687 }
1688
1689
1690 // Describes a set of call frames that execute any of listed functions. 1685 // Describes a set of call frames that execute any of listed functions.
1691 // Finding no such frames does not mean error. 1686 // Finding no such frames does not mean error.
1692 class MultipleFunctionTarget { 1687 class MultipleFunctionTarget {
1693 public: 1688 public:
1694 MultipleFunctionTarget(Handle<JSArray> shared_info_array, 1689 MultipleFunctionTarget(Handle<JSArray> shared_info_array,
1695 Handle<JSArray> result) 1690 Handle<JSArray> result)
1696 : m_shared_info_array(shared_info_array), 1691 : m_shared_info_array(shared_info_array),
1697 m_result(result) {} 1692 m_result(result) {}
1698 bool MatchActivation(StackFrame* frame, 1693 bool MatchActivation(StackFrame* frame,
1699 LiveEdit::FunctionPatchabilityStatus status) { 1694 LiveEdit::FunctionPatchabilityStatus status) {
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
1733 } 1728 }
1734 } 1729 }
1735 1730
1736 if (top_frame_index == -1) { 1731 if (top_frame_index == -1) {
1737 // We haven't found break frame, but no function is blocking us anyway. 1732 // We haven't found break frame, but no function is blocking us anyway.
1738 return target.GetNotFoundMessage(); 1733 return target.GetNotFoundMessage();
1739 } 1734 }
1740 1735
1741 bool target_frame_found = false; 1736 bool target_frame_found = false;
1742 int bottom_js_frame_index = top_frame_index; 1737 int bottom_js_frame_index = top_frame_index;
1743 bool c_code_found = false; 1738 bool non_droppable_frame_found = false;
1739 LiveEdit::FunctionPatchabilityStatus non_droppable_reason;
1744 1740
1745 for (; frame_index < frames.length(); frame_index++) { 1741 for (; frame_index < frames.length(); frame_index++) {
1746 StackFrame* frame = frames[frame_index]; 1742 StackFrame* frame = frames[frame_index];
1747 if (!IsDropableFrame(frame)) { 1743 if (frame->is_exit()) {
1748 c_code_found = true; 1744 non_droppable_frame_found = true;
1745 non_droppable_reason = LiveEdit::FUNCTION_BLOCKED_UNDER_NATIVE_CODE;
1746 break;
1747 }
1748 if (frame->is_java_script() &&
1749 JavaScriptFrame::cast(frame)->function()->shared()->is_generator()) {
1750 non_droppable_frame_found = true;
1751 non_droppable_reason = LiveEdit::FUNCTION_BLOCKED_UNDER_GENERATOR;
1749 break; 1752 break;
1750 } 1753 }
1751 if (target.MatchActivation( 1754 if (target.MatchActivation(
1752 frame, LiveEdit::FUNCTION_BLOCKED_ON_ACTIVE_STACK)) { 1755 frame, LiveEdit::FUNCTION_BLOCKED_ON_ACTIVE_STACK)) {
1753 target_frame_found = true; 1756 target_frame_found = true;
1754 bottom_js_frame_index = frame_index; 1757 bottom_js_frame_index = frame_index;
1755 } 1758 }
1756 } 1759 }
1757 1760
1758 if (c_code_found) { 1761 if (non_droppable_frame_found) {
1759 // There is a C frames on stack. Check that there are no target frames 1762 // There is a C or generator frame on stack. We can't drop C frames, and we
1760 // below them. 1763 // can't restart generators. Check that there are no target frames below
1764 // them.
1761 for (; frame_index < frames.length(); frame_index++) { 1765 for (; frame_index < frames.length(); frame_index++) {
1762 StackFrame* frame = frames[frame_index]; 1766 StackFrame* frame = frames[frame_index];
1763 if (frame->is_java_script()) { 1767 if (frame->is_java_script()) {
1764 if (target.MatchActivation( 1768 if (target.MatchActivation(frame, non_droppable_reason)) {
1765 frame, LiveEdit::FUNCTION_BLOCKED_UNDER_NATIVE_CODE)) { 1769 // Fail.
1766 // Cannot drop frame under C frames.
1767 return NULL; 1770 return NULL;
1768 } 1771 }
1769 } 1772 }
1770 } 1773 }
1771 } 1774 }
1772 1775
1773 if (!do_drop) { 1776 if (!do_drop) {
1774 // We are in check-only mode. 1777 // We are in check-only mode.
1775 return NULL; 1778 return NULL;
1776 } 1779 }
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
1826 if (*obj == Smi::FromInt(LiveEdit::FUNCTION_BLOCKED_ON_ACTIVE_STACK)) { 1829 if (*obj == Smi::FromInt(LiveEdit::FUNCTION_BLOCKED_ON_ACTIVE_STACK)) {
1827 Handle<Object> replaced( 1830 Handle<Object> replaced(
1828 Smi::FromInt(LiveEdit::FUNCTION_REPLACED_ON_ACTIVE_STACK), isolate); 1831 Smi::FromInt(LiveEdit::FUNCTION_REPLACED_ON_ACTIVE_STACK), isolate);
1829 SetElementSloppy(result, i, replaced); 1832 SetElementSloppy(result, i, replaced);
1830 } 1833 }
1831 } 1834 }
1832 return NULL; 1835 return NULL;
1833 } 1836 }
1834 1837
1835 1838
1839 bool LiveEdit::FindActiveGenerators(Handle<FixedArray> shared_info_array,
1840 Handle<FixedArray> result,
1841 int len) {
1842 Isolate* isolate = shared_info_array->GetIsolate();
1843 Heap* heap = isolate->heap();
1844 heap->EnsureHeapIsIterable();
1845 bool found_suspended_activations = false;
1846
1847 ASSERT_LE(len, result->length());
1848
1849 DisallowHeapAllocation no_allocation;
1850
1851 FunctionPatchabilityStatus active = FUNCTION_BLOCKED_ACTIVE_GENERATOR;
1852
1853 HeapIterator iterator(heap);
1854 HeapObject* obj = NULL;
1855 while ((obj = iterator.next()) != NULL) {
1856 if (!obj->IsJSGeneratorObject()) continue;
1857
1858 JSGeneratorObject* gen = JSGeneratorObject::cast(obj);
1859 if (gen->is_closed()) continue;
1860
1861 HandleScope scope(isolate);
1862
1863 for (int i = 0; i < len; i++) {
1864 Handle<JSValue> jsvalue =
1865 Handle<JSValue>::cast(FixedArray::get(shared_info_array, i));
1866 Handle<SharedFunctionInfo> shared =
1867 UnwrapSharedFunctionInfoFromJSValue(jsvalue);
1868
1869 if (gen->function()->shared() == *shared) {
1870 result->set(i, Smi::FromInt(active));
1871 found_suspended_activations = true;
1872 }
1873 }
1874 }
1875
1876 return found_suspended_activations;
1877 }
1878
1879
1836 class InactiveThreadActivationsChecker : public ThreadVisitor { 1880 class InactiveThreadActivationsChecker : public ThreadVisitor {
1837 public: 1881 public:
1838 InactiveThreadActivationsChecker(Handle<JSArray> shared_info_array, 1882 InactiveThreadActivationsChecker(Handle<JSArray> shared_info_array,
1839 Handle<JSArray> result) 1883 Handle<JSArray> result)
1840 : shared_info_array_(shared_info_array), result_(result), 1884 : shared_info_array_(shared_info_array), result_(result),
1841 has_blocked_functions_(false) { 1885 has_blocked_functions_(false) {
1842 } 1886 }
1843 void VisitThread(Isolate* isolate, ThreadLocalTop* top) { 1887 void VisitThread(Isolate* isolate, ThreadLocalTop* top) {
1844 for (StackFrameIterator it(isolate, top); !it.done(); it.Advance()) { 1888 for (StackFrameIterator it(isolate, top); !it.done(); it.Advance()) {
1845 has_blocked_functions_ |= CheckActivation( 1889 has_blocked_functions_ |= CheckActivation(
(...skipping 10 matching lines...) Expand all
1856 Handle<JSArray> result_; 1900 Handle<JSArray> result_;
1857 bool has_blocked_functions_; 1901 bool has_blocked_functions_;
1858 }; 1902 };
1859 1903
1860 1904
1861 Handle<JSArray> LiveEdit::CheckAndDropActivations( 1905 Handle<JSArray> LiveEdit::CheckAndDropActivations(
1862 Handle<JSArray> shared_info_array, bool do_drop) { 1906 Handle<JSArray> shared_info_array, bool do_drop) {
1863 Isolate* isolate = shared_info_array->GetIsolate(); 1907 Isolate* isolate = shared_info_array->GetIsolate();
1864 int len = GetArrayLength(shared_info_array); 1908 int len = GetArrayLength(shared_info_array);
1865 1909
1910 CHECK(shared_info_array->HasFastElements());
1911 Handle<FixedArray> shared_info_array_elements(
1912 FixedArray::cast(shared_info_array->elements()));
1913
1866 Handle<JSArray> result = isolate->factory()->NewJSArray(len); 1914 Handle<JSArray> result = isolate->factory()->NewJSArray(len);
1915 Handle<FixedArray> result_elements =
1916 JSObject::EnsureWritableFastElements(result);
1867 1917
1868 // Fill the default values. 1918 // Fill the default values.
1869 for (int i = 0; i < len; i++) { 1919 for (int i = 0; i < len; i++) {
1870 SetElementSloppy( 1920 FunctionPatchabilityStatus status = FUNCTION_AVAILABLE_FOR_PATCH;
1871 result, 1921 result_elements->set(i, Smi::FromInt(status));
1872 i,
1873 Handle<Smi>(Smi::FromInt(FUNCTION_AVAILABLE_FOR_PATCH), isolate));
1874 } 1922 }
1875 1923
1924 // Scan the heap for active generators -- those that are either currently
1925 // running (as we wouldn't want to restart them, because we don't know where
1926 // to restart them from) or suspended. Fail if any one corresponds to the set
1927 // of functions being edited.
1928 if (FindActiveGenerators(shared_info_array_elements, result_elements, len)) {
1929 return result;
1930 }
1876 1931
1877 // First check inactive threads. Fail if some functions are blocked there. 1932 // Check inactive threads. Fail if some functions are blocked there.
1878 InactiveThreadActivationsChecker inactive_threads_checker(shared_info_array, 1933 InactiveThreadActivationsChecker inactive_threads_checker(shared_info_array,
1879 result); 1934 result);
1880 isolate->thread_manager()->IterateArchivedThreads( 1935 isolate->thread_manager()->IterateArchivedThreads(
1881 &inactive_threads_checker); 1936 &inactive_threads_checker);
1882 if (inactive_threads_checker.HasBlockedFunctions()) { 1937 if (inactive_threads_checker.HasBlockedFunctions()) {
1883 return result; 1938 return result;
1884 } 1939 }
1885 1940
1886 // Try to drop activations from the current stack. 1941 // Try to drop activations from the current stack.
1887 const char* error_message = 1942 const char* error_message =
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
1930 SingleFrameTarget target(frame); 1985 SingleFrameTarget target(frame);
1931 1986
1932 const char* result = DropActivationsInActiveThreadImpl( 1987 const char* result = DropActivationsInActiveThreadImpl(
1933 frame->isolate(), target, true); 1988 frame->isolate(), target, true);
1934 if (result != NULL) { 1989 if (result != NULL) {
1935 return result; 1990 return result;
1936 } 1991 }
1937 if (target.saved_status() == LiveEdit::FUNCTION_BLOCKED_UNDER_NATIVE_CODE) { 1992 if (target.saved_status() == LiveEdit::FUNCTION_BLOCKED_UNDER_NATIVE_CODE) {
1938 return "Function is blocked under native code"; 1993 return "Function is blocked under native code";
1939 } 1994 }
1995 if (target.saved_status() == LiveEdit::FUNCTION_BLOCKED_UNDER_GENERATOR) {
1996 return "Function is blocked under a generator activation";
1997 }
1940 return NULL; 1998 return NULL;
1941 } 1999 }
1942 2000
1943 2001
1944 LiveEditFunctionTracker::LiveEditFunctionTracker(Isolate* isolate, 2002 LiveEditFunctionTracker::LiveEditFunctionTracker(Isolate* isolate,
1945 FunctionLiteral* fun) 2003 FunctionLiteral* fun)
1946 : isolate_(isolate) { 2004 : isolate_(isolate) {
1947 if (isolate_->active_function_info_listener() != NULL) { 2005 if (isolate_->active_function_info_listener() != NULL) {
1948 isolate_->active_function_info_listener()->FunctionStarted(fun); 2006 isolate_->active_function_info_listener()->FunctionStarted(fun);
1949 } 2007 }
(...skipping 20 matching lines...) Expand all
1970 void LiveEditFunctionTracker::RecordRootFunctionInfo(Handle<Code> code) { 2028 void LiveEditFunctionTracker::RecordRootFunctionInfo(Handle<Code> code) {
1971 isolate_->active_function_info_listener()->FunctionCode(code); 2029 isolate_->active_function_info_listener()->FunctionCode(code);
1972 } 2030 }
1973 2031
1974 2032
1975 bool LiveEditFunctionTracker::IsActive(Isolate* isolate) { 2033 bool LiveEditFunctionTracker::IsActive(Isolate* isolate) {
1976 return isolate->active_function_info_listener() != NULL; 2034 return isolate->active_function_info_listener() != NULL;
1977 } 2035 }
1978 2036
1979 } } // namespace v8::internal 2037 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/liveedit.h ('k') | src/liveedit-debugger.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698