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

Side by Side Diff: src/liveedit.cc

Issue 266983004: 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
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 1637 matching lines...) Expand 10 before | Expand all | Expand 10 after
1648 for (Address a = unused_stack_top; 1648 for (Address a = unused_stack_top;
1649 a < unused_stack_bottom; 1649 a < unused_stack_bottom;
1650 a += kPointerSize) { 1650 a += kPointerSize) {
1651 Memory::Object_at(a) = Smi::FromInt(0); 1651 Memory::Object_at(a) = Smi::FromInt(0);
1652 } 1652 }
1653 1653
1654 return NULL; 1654 return NULL;
1655 } 1655 }
1656 1656
1657 1657
1658 static bool IsDropableFrame(StackFrame* frame) {
1659 return !frame->is_exit();
1660 }
1661
1662
1663 // Describes a set of call frames that execute any of listed functions. 1658 // Describes a set of call frames that execute any of listed functions.
1664 // Finding no such frames does not mean error. 1659 // Finding no such frames does not mean error.
1665 class MultipleFunctionTarget { 1660 class MultipleFunctionTarget {
1666 public: 1661 public:
1667 MultipleFunctionTarget(Handle<JSArray> shared_info_array, 1662 MultipleFunctionTarget(Handle<JSArray> shared_info_array,
1668 Handle<JSArray> result) 1663 Handle<JSArray> result)
1669 : m_shared_info_array(shared_info_array), 1664 : m_shared_info_array(shared_info_array),
1670 m_result(result) {} 1665 m_result(result) {}
1671 bool MatchActivation(StackFrame* frame, 1666 bool MatchActivation(StackFrame* frame,
1672 LiveEdit::FunctionPatchabilityStatus status) { 1667 LiveEdit::FunctionPatchabilityStatus status) {
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
1706 } 1701 }
1707 } 1702 }
1708 1703
1709 if (top_frame_index == -1) { 1704 if (top_frame_index == -1) {
1710 // We haven't found break frame, but no function is blocking us anyway. 1705 // We haven't found break frame, but no function is blocking us anyway.
1711 return target.GetNotFoundMessage(); 1706 return target.GetNotFoundMessage();
1712 } 1707 }
1713 1708
1714 bool target_frame_found = false; 1709 bool target_frame_found = false;
1715 int bottom_js_frame_index = top_frame_index; 1710 int bottom_js_frame_index = top_frame_index;
1716 bool c_code_found = false; 1711 bool non_droppable_frame_found = false;
1712 LiveEdit::FunctionPatchabilityStatus non_droppable_reason;
1717 1713
1718 for (; frame_index < frames.length(); frame_index++) { 1714 for (; frame_index < frames.length(); frame_index++) {
1719 StackFrame* frame = frames[frame_index]; 1715 StackFrame* frame = frames[frame_index];
1720 if (!IsDropableFrame(frame)) { 1716 if (frame->is_exit()) {
1721 c_code_found = true; 1717 non_droppable_frame_found = true;
1718 non_droppable_reason = LiveEdit::FUNCTION_BLOCKED_UNDER_NATIVE_CODE;
1719 break;
1720 }
1721 if (!frame->is_java_script()) continue;
1722 if (JavaScriptFrame::cast(frame)->function()->shared()->is_generator()) {
1723 non_droppable_frame_found = true;
1724 non_droppable_reason = LiveEdit::FUNCTION_BLOCKED_UNDER_GENERATOR;
1722 break; 1725 break;
1723 } 1726 }
1724 if (target.MatchActivation( 1727 if (target.MatchActivation(
1725 frame, LiveEdit::FUNCTION_BLOCKED_ON_ACTIVE_STACK)) { 1728 frame, LiveEdit::FUNCTION_BLOCKED_ON_ACTIVE_STACK)) {
1726 target_frame_found = true; 1729 target_frame_found = true;
1727 bottom_js_frame_index = frame_index; 1730 bottom_js_frame_index = frame_index;
1728 } 1731 }
1729 } 1732 }
1730 1733
1731 if (c_code_found) { 1734 if (non_droppable_frame_found) {
1732 // There is a C frames on stack. Check that there are no target frames 1735 // There is a C or generator frame on stack. We can't drop C frames, and we
1733 // below them. 1736 // can't restart generators. Check that there are no target frames below
1737 // them.
1734 for (; frame_index < frames.length(); frame_index++) { 1738 for (; frame_index < frames.length(); frame_index++) {
1735 StackFrame* frame = frames[frame_index]; 1739 StackFrame* frame = frames[frame_index];
1736 if (frame->is_java_script()) { 1740 if (frame->is_java_script()) {
1737 if (target.MatchActivation( 1741 if (target.MatchActivation(frame, non_droppable_reason)) {
1738 frame, LiveEdit::FUNCTION_BLOCKED_UNDER_NATIVE_CODE)) { 1742 // Fail.
1739 // Cannot drop frame under C frames.
1740 return NULL; 1743 return NULL;
1741 } 1744 }
1742 } 1745 }
1743 } 1746 }
1744 } 1747 }
1745 1748
1746 if (!do_drop) { 1749 if (!do_drop) {
1747 // We are in check-only mode. 1750 // We are in check-only mode.
1748 return NULL; 1751 return NULL;
1749 } 1752 }
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
1799 if (*obj == Smi::FromInt(LiveEdit::FUNCTION_BLOCKED_ON_ACTIVE_STACK)) { 1802 if (*obj == Smi::FromInt(LiveEdit::FUNCTION_BLOCKED_ON_ACTIVE_STACK)) {
1800 Handle<Object> replaced( 1803 Handle<Object> replaced(
1801 Smi::FromInt(LiveEdit::FUNCTION_REPLACED_ON_ACTIVE_STACK), isolate); 1804 Smi::FromInt(LiveEdit::FUNCTION_REPLACED_ON_ACTIVE_STACK), isolate);
1802 SetElementSloppy(result, i, replaced); 1805 SetElementSloppy(result, i, replaced);
1803 } 1806 }
1804 } 1807 }
1805 return NULL; 1808 return NULL;
1806 } 1809 }
1807 1810
1808 1811
1812 bool LiveEdit::FindActiveGenerators(Handle<FixedArray> shared_info_array,
1813 Handle<FixedArray> result, int len) {
Yang 2014/05/06 13:05:03 one argument per line is easier on the eye.
1814 Isolate* isolate = shared_info_array->GetIsolate();
1815 Heap* heap = isolate->heap();
1816 heap->EnsureHeapIsIterable();
1817 bool found_suspended_activations = false;
1818
1819 ASSERT_LE(len, result->length());
1820
1821 DisallowHeapAllocation no_allocation;
1822
1823 FunctionPatchabilityStatus active = FUNCTION_BLOCKED_ACTIVE_GENERATOR;
1824
1825 HeapIterator iterator(heap);
1826 HeapObject* obj = NULL;
1827 while (((obj = iterator.next()) != NULL)) {
Yang 2014/05/06 13:05:03 I think we can remove one set of brackets here.
1828 if (!obj->IsJSGeneratorObject()) continue;
1829
1830 JSGeneratorObject* gen = JSGeneratorObject::cast(obj);
1831 if (gen->is_closed()) continue;
1832
1833 HandleScope scope(isolate);
1834
1835 for (int i = 0; i < len; i++) {
1836 Handle<JSValue> jsvalue =
1837 Handle<JSValue>::cast(FixedArray::get(shared_info_array, i));
1838 Handle<SharedFunctionInfo> shared =
1839 UnwrapSharedFunctionInfoFromJSValue(jsvalue);
1840
1841 if (gen->function()->shared() == *shared) {
1842 result->set(i, Smi::FromInt(active));
1843 found_suspended_activations = true;
1844 }
1845 }
1846 }
1847
1848 return found_suspended_activations;
1849 }
1850
1851
1809 class InactiveThreadActivationsChecker : public ThreadVisitor { 1852 class InactiveThreadActivationsChecker : public ThreadVisitor {
1810 public: 1853 public:
1811 InactiveThreadActivationsChecker(Handle<JSArray> shared_info_array, 1854 InactiveThreadActivationsChecker(Handle<JSArray> shared_info_array,
1812 Handle<JSArray> result) 1855 Handle<JSArray> result)
1813 : shared_info_array_(shared_info_array), result_(result), 1856 : shared_info_array_(shared_info_array), result_(result),
1814 has_blocked_functions_(false) { 1857 has_blocked_functions_(false) {
1815 } 1858 }
1816 void VisitThread(Isolate* isolate, ThreadLocalTop* top) { 1859 void VisitThread(Isolate* isolate, ThreadLocalTop* top) {
1817 for (StackFrameIterator it(isolate, top); !it.done(); it.Advance()) { 1860 for (StackFrameIterator it(isolate, top); !it.done(); it.Advance()) {
1818 has_blocked_functions_ |= CheckActivation( 1861 has_blocked_functions_ |= CheckActivation(
(...skipping 10 matching lines...) Expand all
1829 Handle<JSArray> result_; 1872 Handle<JSArray> result_;
1830 bool has_blocked_functions_; 1873 bool has_blocked_functions_;
1831 }; 1874 };
1832 1875
1833 1876
1834 Handle<JSArray> LiveEdit::CheckAndDropActivations( 1877 Handle<JSArray> LiveEdit::CheckAndDropActivations(
1835 Handle<JSArray> shared_info_array, bool do_drop) { 1878 Handle<JSArray> shared_info_array, bool do_drop) {
1836 Isolate* isolate = shared_info_array->GetIsolate(); 1879 Isolate* isolate = shared_info_array->GetIsolate();
1837 int len = GetArrayLength(shared_info_array); 1880 int len = GetArrayLength(shared_info_array);
1838 1881
1882 CHECK(shared_info_array->HasFastElements());
1883 Handle<FixedArray> shared_info_array_elements(
1884 FixedArray::cast(shared_info_array->elements()));
1885
1839 Handle<JSArray> result = isolate->factory()->NewJSArray(len); 1886 Handle<JSArray> result = isolate->factory()->NewJSArray(len);
1887 Handle<FixedArray> result_elements =
1888 JSObject::EnsureWritableFastElements(result);
1840 1889
1841 // Fill the default values. 1890 // Fill the default values.
1842 for (int i = 0; i < len; i++) { 1891 for (int i = 0; i < len; i++) {
1843 SetElementSloppy( 1892 FunctionPatchabilityStatus status = FUNCTION_AVAILABLE_FOR_PATCH;
1844 result, 1893 result_elements->set(i, Smi::FromInt(status));
1845 i,
1846 Handle<Smi>(Smi::FromInt(FUNCTION_AVAILABLE_FOR_PATCH), isolate));
1847 } 1894 }
1848 1895
1896 // 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
1898 // to restart them from) or suspended. Fail if any one corresponds to the set
1899 // of functions being edited.
1900 if (FindActiveGenerators(shared_info_array_elements, result_elements, len))
Yang 2014/05/06 13:05:03 please use curly brackets if the if-statement cont
1901 return result;
1849 1902
1850 // First check inactive threads. Fail if some functions are blocked there. 1903 // Check inactive threads. Fail if some functions are blocked there.
1851 InactiveThreadActivationsChecker inactive_threads_checker(shared_info_array, 1904 InactiveThreadActivationsChecker inactive_threads_checker(shared_info_array,
1852 result); 1905 result);
1853 isolate->thread_manager()->IterateArchivedThreads( 1906 isolate->thread_manager()->IterateArchivedThreads(
1854 &inactive_threads_checker); 1907 &inactive_threads_checker);
1855 if (inactive_threads_checker.HasBlockedFunctions()) { 1908 if (inactive_threads_checker.HasBlockedFunctions()) {
1856 return result; 1909 return result;
1857 } 1910 }
1858 1911
1859 // Try to drop activations from the current stack. 1912 // Try to drop activations from the current stack.
1860 const char* error_message = 1913 const char* error_message =
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
1903 SingleFrameTarget target(frame); 1956 SingleFrameTarget target(frame);
1904 1957
1905 const char* result = DropActivationsInActiveThreadImpl( 1958 const char* result = DropActivationsInActiveThreadImpl(
1906 frame->isolate(), target, true); 1959 frame->isolate(), target, true);
1907 if (result != NULL) { 1960 if (result != NULL) {
1908 return result; 1961 return result;
1909 } 1962 }
1910 if (target.saved_status() == LiveEdit::FUNCTION_BLOCKED_UNDER_NATIVE_CODE) { 1963 if (target.saved_status() == LiveEdit::FUNCTION_BLOCKED_UNDER_NATIVE_CODE) {
1911 return "Function is blocked under native code"; 1964 return "Function is blocked under native code";
1912 } 1965 }
1966 if (target.saved_status() == LiveEdit::FUNCTION_BLOCKED_UNDER_GENERATOR) {
1967 return "Function is blocked under a generator activation";
1968 }
1913 return NULL; 1969 return NULL;
1914 } 1970 }
1915 1971
1916 1972
1917 LiveEditFunctionTracker::LiveEditFunctionTracker(Isolate* isolate, 1973 LiveEditFunctionTracker::LiveEditFunctionTracker(Isolate* isolate,
1918 FunctionLiteral* fun) 1974 FunctionLiteral* fun)
1919 : isolate_(isolate) { 1975 : isolate_(isolate) {
1920 if (isolate_->active_function_info_listener() != NULL) { 1976 if (isolate_->active_function_info_listener() != NULL) {
1921 isolate_->active_function_info_listener()->FunctionStarted(fun); 1977 isolate_->active_function_info_listener()->FunctionStarted(fun);
1922 } 1978 }
(...skipping 20 matching lines...) Expand all
1943 void LiveEditFunctionTracker::RecordRootFunctionInfo(Handle<Code> code) { 1999 void LiveEditFunctionTracker::RecordRootFunctionInfo(Handle<Code> code) {
1944 isolate_->active_function_info_listener()->FunctionCode(code); 2000 isolate_->active_function_info_listener()->FunctionCode(code);
1945 } 2001 }
1946 2002
1947 2003
1948 bool LiveEditFunctionTracker::IsActive(Isolate* isolate) { 2004 bool LiveEditFunctionTracker::IsActive(Isolate* isolate) {
1949 return isolate->active_function_info_listener() != NULL; 2005 return isolate->active_function_info_listener() != NULL;
1950 } 2006 }
1951 2007
1952 } } // namespace v8::internal 2008 } } // namespace v8::internal
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698