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

Side by Side Diff: src/debug.cc

Issue 8404030: Version 3.7.1 (Closed) Base URL: http://v8.googlecode.com/svn/trunk/
Patch Set: Created 9 years, 1 month 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/debug.h ('k') | src/deoptimizer.h » ('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 2011 the V8 project authors. All rights reserved. 1 // Copyright 2011 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 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
80 V8::FatalProcessOutOfMemory("PrintLn"); 80 V8::FatalProcessOutOfMemory("PrintLn");
81 return; 81 return;
82 } 82 }
83 s->WriteAscii(data.start()); 83 s->WriteAscii(data.start());
84 PrintF("%s\n", data.start()); 84 PrintF("%s\n", data.start());
85 } 85 }
86 86
87 87
88 static Handle<Code> ComputeCallDebugBreak(int argc, Code::Kind kind) { 88 static Handle<Code> ComputeCallDebugBreak(int argc, Code::Kind kind) {
89 Isolate* isolate = Isolate::Current(); 89 Isolate* isolate = Isolate::Current();
90 CALL_HEAP_FUNCTION( 90 return isolate->stub_cache()->ComputeCallDebugBreak(argc, kind);
91 isolate,
92 isolate->stub_cache()->ComputeCallDebugBreak(argc, kind),
93 Code);
94 } 91 }
95 92
96 93
97 static Handle<Code> ComputeCallDebugPrepareStepIn(int argc, Code::Kind kind) { 94 static Handle<Code> ComputeCallDebugPrepareStepIn(int argc, Code::Kind kind) {
98 Isolate* isolate = Isolate::Current(); 95 Isolate* isolate = Isolate::Current();
99 CALL_HEAP_FUNCTION( 96 return isolate->stub_cache()->ComputeCallDebugPrepareStepIn(argc, kind);
100 isolate,
101 isolate->stub_cache()->ComputeCallDebugPrepareStepIn(argc, kind),
102 Code);
103 } 97 }
104 98
105 99
106 static v8::Handle<v8::Context> GetDebugEventContext(Isolate* isolate) { 100 static v8::Handle<v8::Context> GetDebugEventContext(Isolate* isolate) {
107 Handle<Context> context = isolate->debug()->debugger_entry()->GetContext(); 101 Handle<Context> context = isolate->debug()->debugger_entry()->GetContext();
108 // Isolate::context() may have been NULL when "script collected" event 102 // Isolate::context() may have been NULL when "script collected" event
109 // occured. 103 // occured.
110 if (context.is_null()) return v8::Local<v8::Context>(); 104 if (context.is_null()) return v8::Local<v8::Context>();
111 Handle<Context> global_context(context->global_context()); 105 Handle<Context> global_context(context->global_context());
112 return v8::Utils::ToLocal(global_context); 106 return v8::Utils::ToLocal(global_context);
(...skipping 1607 matching lines...) Expand 10 before | Expand all | Expand 10 after
1720 } 1714 }
1721 1715
1722 1716
1723 void Debug::ClearStepNext() { 1717 void Debug::ClearStepNext() {
1724 thread_local_.last_step_action_ = StepNone; 1718 thread_local_.last_step_action_ = StepNone;
1725 thread_local_.last_statement_position_ = RelocInfo::kNoPosition; 1719 thread_local_.last_statement_position_ = RelocInfo::kNoPosition;
1726 thread_local_.last_fp_ = 0; 1720 thread_local_.last_fp_ = 0;
1727 } 1721 }
1728 1722
1729 1723
1724 // Helper function to compile full code for debugging. This code will
1725 // have debug break slots and deoptimization
1726 // information. Deoptimization information is required in case that an
1727 // optimized version of this function is still activated on the
1728 // stack. It will also make sure that the full code is compiled with
1729 // the same flags as the previous version - that is flags which can
1730 // change the code generated. The current method of mapping from
1731 // already compiled full code without debug break slots to full code
1732 // with debug break slots depends on the generated code is otherwise
1733 // exactly the same.
1734 static bool CompileFullCodeForDebugging(Handle<SharedFunctionInfo> shared,
1735 Handle<Code> current_code) {
1736 ASSERT(!current_code->has_debug_break_slots());
1737
1738 CompilationInfo info(shared);
1739 info.MarkCompilingForDebugging(current_code);
1740 ASSERT(!info.shared_info()->is_compiled());
1741 ASSERT(!info.isolate()->has_pending_exception());
1742
1743 // Use compile lazy which will end up compiling the full code in the
1744 // configuration configured above.
1745 bool result = Compiler::CompileLazy(&info);
1746 ASSERT(result != Isolate::Current()->has_pending_exception());
1747 info.isolate()->clear_pending_exception();
1748 #if DEBUG
1749 if (result) {
1750 Handle<Code> new_code(shared->code());
1751 ASSERT(new_code->has_debug_break_slots());
1752 ASSERT(current_code->is_compiled_optimizable() ==
1753 new_code->is_compiled_optimizable());
1754 ASSERT(current_code->instruction_size() <= new_code->instruction_size());
1755 }
1756 #endif
1757 return result;
1758 }
1759
1760
1730 void Debug::PrepareForBreakPoints() { 1761 void Debug::PrepareForBreakPoints() {
1731 // If preparing for the first break point make sure to deoptimize all 1762 // If preparing for the first break point make sure to deoptimize all
1732 // functions as debugging does not work with optimized code. 1763 // functions as debugging does not work with optimized code.
1733 if (!has_break_points_) { 1764 if (!has_break_points_) {
1734 Deoptimizer::DeoptimizeAll(); 1765 Deoptimizer::DeoptimizeAll();
1735 1766
1736 // We are going to iterate heap to find all functions without 1767 Handle<Code> lazy_compile =
1737 // debug break slots. 1768 Handle<Code>(isolate_->builtins()->builtin(Builtins::kLazyCompile));
1738 isolate_->heap()->CollectAllGarbage(Heap::kMakeHeapIterableMask); 1769
1739 1770 // Keep the list of activated functions in a handlified list as it
1740 AssertNoAllocation no_allocation; 1771 // is used both in GC and non-GC code.
1741 Builtins* builtins = isolate_->builtins(); 1772 List<Handle<JSFunction> > active_functions(100);
1742 Code* lazy_compile = builtins->builtin(Builtins::kLazyCompile); 1773
1743 1774 {
1744 // Find all non-optimized code functions with activation frames on 1775 // We are going to iterate heap to find all functions without
1745 // the stack. 1776 // debug break slots.
1746 List<JSFunction*> active_functions(100); 1777 isolate_->heap()->CollectAllGarbage(Heap::kMakeHeapIterableMask);
1747 for (JavaScriptFrameIterator it(isolate_); !it.done(); it.Advance()) { 1778
1748 JavaScriptFrame* frame = it.frame(); 1779 // Ensure no GC in this scope as we are comparing raw pointer
1749 if (frame->function()->IsJSFunction()) { 1780 // values and performing a heap iteration.
1750 JSFunction* function = JSFunction::cast(frame->function()); 1781 AssertNoAllocation no_allocation;
1751 if (function->code()->kind() == Code::FUNCTION) 1782
1752 active_functions.Add(function); 1783 // Find all non-optimized code functions with activation frames on
1784 // the stack.
1785 for (JavaScriptFrameIterator it(isolate_); !it.done(); it.Advance()) {
1786 JavaScriptFrame* frame = it.frame();
1787 if (frame->function()->IsJSFunction()) {
1788 JSFunction* function = JSFunction::cast(frame->function());
1789 if (function->code()->kind() == Code::FUNCTION &&
1790 !function->code()->has_debug_break_slots())
1791 active_functions.Add(Handle<JSFunction>(function));
1792 }
1793 }
1794 // Sort the functions on the object pointer value to prepare for
1795 // the binary search below.
1796 active_functions.Sort(HandleObjectPointerCompare<JSFunction>);
1797
1798 // Scan the heap for all non-optimized functions which has no
1799 // debug break slots.
1800 HeapIterator iterator;
1801 HeapObject* obj = NULL;
1802 while (((obj = iterator.next()) != NULL)) {
1803 if (obj->IsJSFunction()) {
1804 JSFunction* function = JSFunction::cast(obj);
1805 if (function->shared()->allows_lazy_compilation() &&
1806 function->shared()->script()->IsScript() &&
1807 function->code()->kind() == Code::FUNCTION &&
1808 !function->code()->has_debug_break_slots()) {
1809 bool has_activation =
1810 SortedListBSearch<Handle<JSFunction> >(
1811 active_functions,
1812 Handle<JSFunction>(function),
1813 HandleObjectPointerCompare<JSFunction>) != -1;
1814 if (!has_activation) {
1815 function->set_code(*lazy_compile);
1816 function->shared()->set_code(*lazy_compile);
1817 }
1818 }
1819 }
1753 } 1820 }
1754 } 1821 }
1755 active_functions.Sort(); 1822
1756 1823 // Now the non-GC scope is left, and the sorting of the functions
1757 // Scan the heap for all non-optimized functions which has no 1824 // in active_function is not ensured any more. The code below does
1758 // debug break slots. 1825 // not rely on it.
1759 HeapIterator iterator; 1826
1760 HeapObject* obj = NULL; 1827 // Now recompile all functions with activation frames and and
1761 while (((obj = iterator.next()) != NULL)) { 1828 // patch the return address to run in the new compiled code.
1762 if (obj->IsJSFunction()) { 1829 for (int i = 0; i < active_functions.length(); i++) {
1763 JSFunction* function = JSFunction::cast(obj); 1830 Handle<JSFunction> function = active_functions[i];
1764 if (function->shared()->allows_lazy_compilation() && 1831 Handle<SharedFunctionInfo> shared(function->shared());
1765 function->shared()->script()->IsScript() && 1832 // If recompilation is not possible just skip it.
1766 function->code()->kind() == Code::FUNCTION && 1833 if (shared->is_toplevel() ||
1767 !function->code()->has_debug_break_slots()) { 1834 !shared->allows_lazy_compilation() ||
1768 bool has_activation = 1835 shared->code()->kind() == Code::BUILTIN) {
1769 SortedListBSearch<JSFunction*>(active_functions, function) != -1; 1836 continue;
1770 if (!has_activation) { 1837 }
1771 function->set_code(lazy_compile); 1838
1772 function->shared()->set_code(lazy_compile); 1839 // Make sure that the shared full code is compiled with debug
1840 // break slots.
1841 Handle<Code> current_code(function->code());
1842 if (shared->code()->has_debug_break_slots()) {
1843 // if the code is already recompiled to have break slots skip
1844 // recompilation.
1845 ASSERT(!function->code()->has_debug_break_slots());
1846 } else {
1847 // Try to compile the full code with debug break slots. If it
1848 // fails just keep the current code.
1849 ASSERT(shared->code() == *current_code);
1850 ZoneScope zone_scope(isolate_, DELETE_ON_EXIT);
1851 shared->set_code(*lazy_compile);
1852 bool prev_force_debugger_active =
1853 isolate_->debugger()->force_debugger_active();
1854 isolate_->debugger()->set_force_debugger_active(true);
1855 CompileFullCodeForDebugging(shared, current_code);
1856 isolate_->debugger()->set_force_debugger_active(
1857 prev_force_debugger_active);
1858 if (!shared->is_compiled()) {
1859 shared->set_code(*current_code);
1860 continue;
1861 }
1862 }
1863 Handle<Code> new_code(shared->code());
1864
1865 // Find the function and patch return address.
1866 for (JavaScriptFrameIterator it(isolate_); !it.done(); it.Advance()) {
1867 JavaScriptFrame* frame = it.frame();
1868 // If the current frame is for this function in its
1869 // non-optimized form rewrite the return address to continue
1870 // in the newly compiled full code with debug break slots.
1871 if (frame->function()->IsJSFunction() &&
1872 frame->function() == *function &&
1873 frame->LookupCode()->kind() == Code::FUNCTION) {
1874 intptr_t delta = frame->pc() - current_code->instruction_start();
1875 int debug_break_slot_count = 0;
1876 int mask = RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT);
1877 for (RelocIterator it(*new_code, mask); !it.done(); it.next()) {
1878 // Check if the pc in the new code with debug break
1879 // slots is before this slot.
1880 RelocInfo* info = it.rinfo();
1881 int debug_break_slot_bytes =
1882 debug_break_slot_count * Assembler::kDebugBreakSlotLength;
1883 intptr_t new_delta =
1884 info->pc() -
1885 new_code->instruction_start() -
1886 debug_break_slot_bytes;
1887 if (new_delta > delta) {
1888 break;
1889 }
1890
1891 // Passed a debug break slot in the full code with debug
1892 // break slots.
1893 debug_break_slot_count++;
1773 } 1894 }
1895 int debug_break_slot_bytes =
1896 debug_break_slot_count * Assembler::kDebugBreakSlotLength;
1897 if (FLAG_trace_deopt) {
1898 PrintF("Replacing code %08" V8PRIxPTR " - %08" V8PRIxPTR " (%d) "
1899 "with %08" V8PRIxPTR " - %08" V8PRIxPTR " (%d) "
1900 "for debugging, "
1901 "changing pc from %08" V8PRIxPTR " to %08" V8PRIxPTR "\n",
1902 reinterpret_cast<intptr_t>(
1903 current_code->instruction_start()),
1904 reinterpret_cast<intptr_t>(
1905 current_code->instruction_start()) +
1906 current_code->instruction_size(),
1907 current_code->instruction_size(),
1908 reinterpret_cast<intptr_t>(new_code->instruction_start()),
1909 reinterpret_cast<intptr_t>(new_code->instruction_start()) +
1910 new_code->instruction_size(),
1911 new_code->instruction_size(),
1912 reinterpret_cast<intptr_t>(frame->pc()),
1913 reinterpret_cast<intptr_t>(new_code->instruction_start()) +
1914 delta + debug_break_slot_bytes);
1915 }
1916
1917 // Patch the return address to return into the code with
1918 // debug break slots.
1919 frame->set_pc(
1920 new_code->instruction_start() + delta + debug_break_slot_bytes);
1774 } 1921 }
1775 } 1922 }
1776 } 1923 }
1777 } 1924 }
1778 } 1925 }
1779 1926
1780 1927
1781 // Ensures the debug information is present for shared. 1928 // Ensures the debug information is present for shared.
1782 bool Debug::EnsureDebugInfo(Handle<SharedFunctionInfo> shared) { 1929 bool Debug::EnsureDebugInfo(Handle<SharedFunctionInfo> shared) {
1783 // Return if we already have the debug info for shared. 1930 // Return if we already have the debug info for shared.
1784 if (HasDebugInfo(shared)) { 1931 if (HasDebugInfo(shared)) {
1785 ASSERT(shared->is_compiled()); 1932 ASSERT(shared->is_compiled());
1786 return true; 1933 return true;
1787 } 1934 }
1788 1935
1789 // Ensure shared in compiled. Return false if this failed. 1936 // Ensure shared in compiled. Return false if this failed.
1790 if (!EnsureCompiled(shared, CLEAR_EXCEPTION)) return false; 1937 if (!SharedFunctionInfo::EnsureCompiled(shared, CLEAR_EXCEPTION)) {
1938 return false;
1939 }
1791 1940
1792 // Create the debug info object. 1941 // Create the debug info object.
1793 Handle<DebugInfo> debug_info = FACTORY->NewDebugInfo(shared); 1942 Handle<DebugInfo> debug_info = FACTORY->NewDebugInfo(shared);
1794 1943
1795 // Add debug info to the list. 1944 // Add debug info to the list.
1796 DebugInfoListNode* node = new DebugInfoListNode(*debug_info); 1945 DebugInfoListNode* node = new DebugInfoListNode(*debug_info);
1797 node->set_next(debug_info_list_); 1946 node->set_next(debug_info_list_);
1798 debug_info_list_ = node; 1947 debug_info_list_ = node;
1799 1948
1800 // Now there is at least one break point. 1949 // Now there is at least one break point.
(...skipping 269 matching lines...) Expand 10 before | Expand all | Expand 10 after
2070 } 2219 }
2071 2220
2072 2221
2073 Debugger::Debugger(Isolate* isolate) 2222 Debugger::Debugger(Isolate* isolate)
2074 : debugger_access_(isolate->debugger_access()), 2223 : debugger_access_(isolate->debugger_access()),
2075 event_listener_(Handle<Object>()), 2224 event_listener_(Handle<Object>()),
2076 event_listener_data_(Handle<Object>()), 2225 event_listener_data_(Handle<Object>()),
2077 compiling_natives_(false), 2226 compiling_natives_(false),
2078 is_loading_debugger_(false), 2227 is_loading_debugger_(false),
2079 never_unload_debugger_(false), 2228 never_unload_debugger_(false),
2229 force_debugger_active_(false),
2080 message_handler_(NULL), 2230 message_handler_(NULL),
2081 debugger_unload_pending_(false), 2231 debugger_unload_pending_(false),
2082 host_dispatch_handler_(NULL), 2232 host_dispatch_handler_(NULL),
2083 dispatch_handler_access_(OS::CreateMutex()), 2233 dispatch_handler_access_(OS::CreateMutex()),
2084 debug_message_dispatch_handler_(NULL), 2234 debug_message_dispatch_handler_(NULL),
2085 message_dispatch_helper_thread_(NULL), 2235 message_dispatch_helper_thread_(NULL),
2086 host_dispatch_micros_(100 * 1000), 2236 host_dispatch_micros_(100 * 1000),
2087 agent_(NULL), 2237 agent_(NULL),
2088 command_queue_(isolate->logger(), kQueueInitialSize), 2238 command_queue_(isolate->logger(), kQueueInitialSize),
2089 command_received_(OS::CreateSemaphore(0)), 2239 command_received_(OS::CreateSemaphore(0)),
(...skipping 747 matching lines...) Expand 10 before | Expand all | Expand 10 after
2837 // Set the debug command break flag to have the command processed. 2987 // Set the debug command break flag to have the command processed.
2838 if (!isolate_->debug()->InDebugger()) { 2988 if (!isolate_->debug()->InDebugger()) {
2839 isolate_->stack_guard()->DebugCommand(); 2989 isolate_->stack_guard()->DebugCommand();
2840 } 2990 }
2841 } 2991 }
2842 2992
2843 2993
2844 bool Debugger::IsDebuggerActive() { 2994 bool Debugger::IsDebuggerActive() {
2845 ScopedLock with(debugger_access_); 2995 ScopedLock with(debugger_access_);
2846 2996
2847 return message_handler_ != NULL || !event_listener_.is_null(); 2997 return message_handler_ != NULL ||
2998 !event_listener_.is_null() ||
2999 force_debugger_active_;
2848 } 3000 }
2849 3001
2850 3002
2851 Handle<Object> Debugger::Call(Handle<JSFunction> fun, 3003 Handle<Object> Debugger::Call(Handle<JSFunction> fun,
2852 Handle<Object> data, 3004 Handle<Object> data,
2853 bool* pending_exception) { 3005 bool* pending_exception) {
2854 // When calling functions in the debugger prevent it from beeing unloaded. 3006 // When calling functions in the debugger prevent it from beeing unloaded.
2855 Debugger::never_unload_debugger_ = true; 3007 Debugger::never_unload_debugger_ = true;
2856 3008
2857 // Enter the debugger. 3009 // Enter the debugger.
(...skipping 464 matching lines...) Expand 10 before | Expand all | Expand 10 after
3322 { 3474 {
3323 Locker locker; 3475 Locker locker;
3324 Isolate::Current()->debugger()->CallMessageDispatchHandler(); 3476 Isolate::Current()->debugger()->CallMessageDispatchHandler();
3325 } 3477 }
3326 } 3478 }
3327 } 3479 }
3328 3480
3329 #endif // ENABLE_DEBUGGER_SUPPORT 3481 #endif // ENABLE_DEBUGGER_SUPPORT
3330 3482
3331 } } // namespace v8::internal 3483 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/debug.h ('k') | src/deoptimizer.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698