OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |