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

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

Issue 2537313005: [debug] Revert debug API removal (Closed)
Patch Set: Created 4 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
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/debug.h" 5 #include "src/debug/debug.h"
6 6
7 #include <memory> 7 #include <memory>
8 8
9 #include "src/api.h" 9 #include "src/api.h"
10 #include "src/arguments.h" 10 #include "src/arguments.h"
(...skipping 20 matching lines...) Expand all
31 31
32 #include "include/v8-debug.h" 32 #include "include/v8-debug.h"
33 33
34 namespace v8 { 34 namespace v8 {
35 namespace internal { 35 namespace internal {
36 36
37 Debug::Debug(Isolate* isolate) 37 Debug::Debug(Isolate* isolate)
38 : debug_context_(Handle<Context>()), 38 : debug_context_(Handle<Context>()),
39 event_listener_(Handle<Object>()), 39 event_listener_(Handle<Object>()),
40 event_listener_data_(Handle<Object>()), 40 event_listener_data_(Handle<Object>()),
41 message_handler_(NULL),
42 command_received_(0),
43 command_queue_(isolate->logger(), kQueueInitialSize),
41 is_active_(false), 44 is_active_(false),
42 is_suppressed_(false), 45 is_suppressed_(false),
43 live_edit_enabled_(true), // TODO(yangguo): set to false by default. 46 live_edit_enabled_(true), // TODO(yangguo): set to false by default.
44 break_disabled_(false), 47 break_disabled_(false),
45 break_points_active_(true), 48 break_points_active_(true),
46 in_debug_event_listener_(false), 49 in_debug_event_listener_(false),
47 break_on_exception_(false), 50 break_on_exception_(false),
48 break_on_uncaught_exception_(false), 51 break_on_uncaught_exception_(false),
49 debug_info_list_(NULL), 52 debug_info_list_(NULL),
50 feature_tracker_(isolate), 53 feature_tracker_(isolate),
(...skipping 464 matching lines...) Expand 10 before | Expand all | Expand 10 after
515 518
516 // Find the break location where execution has stopped. 519 // Find the break location where execution has stopped.
517 BreakLocation location = BreakLocation::FromFrame(debug_info, frame); 520 BreakLocation location = BreakLocation::FromFrame(debug_info, frame);
518 521
519 // Find actual break points, if any, and trigger debug break event. 522 // Find actual break points, if any, and trigger debug break event.
520 Handle<Object> break_points_hit = CheckBreakPoints(debug_info, &location); 523 Handle<Object> break_points_hit = CheckBreakPoints(debug_info, &location);
521 if (!break_points_hit->IsUndefined(isolate_)) { 524 if (!break_points_hit->IsUndefined(isolate_)) {
522 // Clear all current stepping setup. 525 // Clear all current stepping setup.
523 ClearStepping(); 526 ClearStepping();
524 // Notify the debug event listeners. 527 // Notify the debug event listeners.
525 OnDebugBreak(break_points_hit); 528 OnDebugBreak(break_points_hit, false);
526 return; 529 return;
527 } 530 }
528 531
529 // No break point. Check for stepping. 532 // No break point. Check for stepping.
530 StepAction step_action = last_step_action(); 533 StepAction step_action = last_step_action();
531 Address current_fp = frame->UnpaddedFP(); 534 Address current_fp = frame->UnpaddedFP();
532 Address target_fp = thread_local_.target_fp_; 535 Address target_fp = thread_local_.target_fp_;
533 Address last_fp = thread_local_.last_fp_; 536 Address last_fp = thread_local_.last_fp_;
534 537
535 bool step_break = false; 538 bool step_break = false;
(...skipping 23 matching lines...) Expand all
559 case StepFrame: 562 case StepFrame:
560 step_break = current_fp != last_fp; 563 step_break = current_fp != last_fp;
561 break; 564 break;
562 } 565 }
563 566
564 // Clear all current stepping setup. 567 // Clear all current stepping setup.
565 ClearStepping(); 568 ClearStepping();
566 569
567 if (step_break) { 570 if (step_break) {
568 // Notify the debug event listeners. 571 // Notify the debug event listeners.
569 OnDebugBreak(isolate_->factory()->undefined_value()); 572 OnDebugBreak(isolate_->factory()->undefined_value(), false);
570 } else { 573 } else {
571 // Re-prepare to continue. 574 // Re-prepare to continue.
572 PrepareStep(step_action); 575 PrepareStep(step_action);
573 } 576 }
574 } 577 }
575 578
576 579
577 // Find break point objects for this location, if any, and evaluate them. 580 // Find break point objects for this location, if any, and evaluate them.
578 // Return an array of break point objects that evaluated true. 581 // Return an array of break point objects that evaluated true.
579 Handle<Object> Debug::CheckBreakPoints(Handle<DebugInfo> debug_info, 582 Handle<Object> Debug::CheckBreakPoints(Handle<DebugInfo> debug_info,
(...skipping 1157 matching lines...) Expand 10 before | Expand all | Expand 10 after
1737 1740
1738 // Create the event data object. 1741 // Create the event data object.
1739 Handle<Object> event_data; 1742 Handle<Object> event_data;
1740 // Bail out and don't call debugger if exception. 1743 // Bail out and don't call debugger if exception.
1741 if (!MakeExceptionEvent( 1744 if (!MakeExceptionEvent(
1742 exception, uncaught, promise).ToHandle(&event_data)) { 1745 exception, uncaught, promise).ToHandle(&event_data)) {
1743 return; 1746 return;
1744 } 1747 }
1745 1748
1746 // Process debug event. 1749 // Process debug event.
1747 ProcessDebugEvent(v8::Exception, Handle<JSObject>::cast(event_data)); 1750 ProcessDebugEvent(v8::Exception, Handle<JSObject>::cast(event_data), false);
1748 // Return to continue execution from where the exception was thrown. 1751 // Return to continue execution from where the exception was thrown.
1749 } 1752 }
1750 1753
1751 void Debug::OnDebugBreak(Handle<Object> break_points_hit) { 1754 void Debug::OnDebugBreak(Handle<Object> break_points_hit, bool auto_continue) {
1752 // The caller provided for DebugScope. 1755 // The caller provided for DebugScope.
1753 AssertDebugContext(); 1756 AssertDebugContext();
1754 // Bail out if there is no listener for this event 1757 // Bail out if there is no listener for this event
1755 if (ignore_events()) return; 1758 if (ignore_events()) return;
1756 1759
1757 #ifdef DEBUG 1760 #ifdef DEBUG
1758 PrintBreakLocation(); 1761 PrintBreakLocation();
1759 #endif // DEBUG 1762 #endif // DEBUG
1760 1763
1761 HandleScope scope(isolate_); 1764 HandleScope scope(isolate_);
1762 // Create the event data object. 1765 // Create the event data object.
1763 Handle<Object> event_data; 1766 Handle<Object> event_data;
1764 // Bail out and don't call debugger if exception. 1767 // Bail out and don't call debugger if exception.
1765 if (!MakeBreakEvent(break_points_hit).ToHandle(&event_data)) return; 1768 if (!MakeBreakEvent(break_points_hit).ToHandle(&event_data)) return;
1766 1769
1767 // Process debug event. 1770 // Process debug event.
1768 ProcessDebugEvent(v8::Break, Handle<JSObject>::cast(event_data)); 1771 ProcessDebugEvent(v8::Break, Handle<JSObject>::cast(event_data),
1772 auto_continue);
1769 } 1773 }
1770 1774
1771 1775
1772 void Debug::OnCompileError(Handle<Script> script) { 1776 void Debug::OnCompileError(Handle<Script> script) {
1773 ProcessCompileEvent(v8::CompileError, script); 1777 ProcessCompileEvent(v8::CompileError, script);
1774 } 1778 }
1775 1779
1780 void Debug::OnBeforeCompile(Handle<Script> script) {
1781 ProcessCompileEvent(v8::BeforeCompile, script);
1782 }
1776 1783
1777 // Handle debugger actions when a new script is compiled. 1784 // Handle debugger actions when a new script is compiled.
1778 void Debug::OnAfterCompile(Handle<Script> script) { 1785 void Debug::OnAfterCompile(Handle<Script> script) {
1779 ProcessCompileEvent(v8::AfterCompile, script); 1786 ProcessCompileEvent(v8::AfterCompile, script);
1780 } 1787 }
1781 1788
1782 void Debug::OnAsyncTaskEvent(Handle<String> type, Handle<Object> id, 1789 void Debug::OnAsyncTaskEvent(Handle<String> type, Handle<Object> id,
1783 Handle<String> name) { 1790 Handle<String> name) {
1784 DCHECK(id->IsNumber()); 1791 DCHECK(id->IsNumber());
1785 if (in_debug_scope() || ignore_events()) return; 1792 if (in_debug_scope() || ignore_events()) return;
1786 1793
1787 HandleScope scope(isolate_); 1794 HandleScope scope(isolate_);
1788 DebugScope debug_scope(this); 1795 DebugScope debug_scope(this);
1789 if (debug_scope.failed()) return; 1796 if (debug_scope.failed()) return;
1790 1797
1791 // Create the script collected state object. 1798 // Create the script collected state object.
1792 Handle<Object> event_data; 1799 Handle<Object> event_data;
1793 // Bail out and don't call debugger if exception. 1800 // Bail out and don't call debugger if exception.
1794 if (!MakeAsyncTaskEvent(type, id, name).ToHandle(&event_data)) return; 1801 if (!MakeAsyncTaskEvent(type, id, name).ToHandle(&event_data)) return;
1795 1802
1796 // Process debug event. 1803 // Process debug event.
1797 ProcessDebugEvent(v8::AsyncTaskEvent, Handle<JSObject>::cast(event_data)); 1804 ProcessDebugEvent(v8::AsyncTaskEvent, Handle<JSObject>::cast(event_data),
1805 true);
1798 } 1806 }
1799 1807
1800 void Debug::ProcessDebugEvent(v8::DebugEvent event, 1808 void Debug::ProcessDebugEvent(v8::DebugEvent event, Handle<JSObject> event_data,
1801 Handle<JSObject> event_data) { 1809 bool auto_continue) {
1802 HandleScope scope(isolate_); 1810 HandleScope scope(isolate_);
1803 1811
1804 // Create the execution state. 1812 // Create the execution state.
1805 Handle<Object> exec_state; 1813 Handle<Object> exec_state;
1806 // Bail out and don't call debugger if exception. 1814 // Bail out and don't call debugger if exception.
1807 if (!MakeExecutionState().ToHandle(&exec_state)) return; 1815 if (!MakeExecutionState().ToHandle(&exec_state)) return;
1808 1816
1809 // Notify registered debug event listener. 1817 // First notify the message handler if any.
1810 if (!event_listener_.is_null()) { 1818 if (message_handler_ != NULL) {
1819 NotifyMessageHandler(event, Handle<JSObject>::cast(exec_state), event_data,
1820 auto_continue);
1821 }
1822 // Notify registered debug event listener. This can be either a C or
1823 // a JavaScript function. Don't call event listener for v8::Break
1824 // here, if it's only a debug command -- they will be processed later.
1825 if ((event != v8::Break || !auto_continue) && !event_listener_.is_null()) {
1811 CallEventCallback(event, exec_state, event_data, NULL); 1826 CallEventCallback(event, exec_state, event_data, NULL);
1812 } 1827 }
1813 } 1828 }
1814 1829
1815 1830
1816 void Debug::CallEventCallback(v8::DebugEvent event, 1831 void Debug::CallEventCallback(v8::DebugEvent event,
1817 Handle<Object> exec_state, 1832 Handle<Object> exec_state,
1818 Handle<Object> event_data, 1833 Handle<Object> event_data,
1819 v8::Debug::ClientData* client_data) { 1834 v8::Debug::ClientData* client_data) {
1820 // Prevent other interrupts from triggering, for example API callbacks, 1835 // Prevent other interrupts from triggering, for example API callbacks,
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
1852 1867
1853 1868
1854 void Debug::ProcessCompileEvent(v8::DebugEvent event, Handle<Script> script) { 1869 void Debug::ProcessCompileEvent(v8::DebugEvent event, Handle<Script> script) {
1855 if (ignore_events()) return; 1870 if (ignore_events()) return;
1856 if (script->type() != i::Script::TYPE_NORMAL && 1871 if (script->type() != i::Script::TYPE_NORMAL &&
1857 script->type() != i::Script::TYPE_WASM) { 1872 script->type() != i::Script::TYPE_WASM) {
1858 return; 1873 return;
1859 } 1874 }
1860 SuppressDebug while_processing(this); 1875 SuppressDebug while_processing(this);
1861 1876
1877 bool in_nested_debug_scope = in_debug_scope();
1862 HandleScope scope(isolate_); 1878 HandleScope scope(isolate_);
1863 DebugScope debug_scope(this); 1879 DebugScope debug_scope(this);
1864 if (debug_scope.failed()) return; 1880 if (debug_scope.failed()) return;
1865 1881
1866 if (event == v8::AfterCompile) { 1882 if (event == v8::AfterCompile) {
1867 // If debugging there might be script break points registered for this 1883 // If debugging there might be script break points registered for this
1868 // script. Make sure that these break points are set. 1884 // script. Make sure that these break points are set.
1869 Handle<Object> argv[] = {Script::GetWrapper(script)}; 1885 Handle<Object> argv[] = {Script::GetWrapper(script)};
1870 if (CallFunction("UpdateScriptBreakPoints", arraysize(argv), argv) 1886 if (CallFunction("UpdateScriptBreakPoints", arraysize(argv), argv)
1871 .is_null()) { 1887 .is_null()) {
1872 return; 1888 return;
1873 } 1889 }
1874 } 1890 }
1875 1891
1876 // Create the compile state object. 1892 // Create the compile state object.
1877 Handle<Object> event_data; 1893 Handle<Object> event_data;
1878 // Bail out and don't call debugger if exception. 1894 // Bail out and don't call debugger if exception.
1879 if (!MakeCompileEvent(script, event).ToHandle(&event_data)) return; 1895 if (!MakeCompileEvent(script, event).ToHandle(&event_data)) return;
1880 1896
1881 ProcessDebugEvent(event, Handle<JSObject>::cast(event_data)); 1897 // Don't call NotifyMessageHandler if already in debug scope to avoid running
1898 // nested command loop.
1899 if (in_nested_debug_scope) {
1900 if (event_listener_.is_null()) return;
1901 // Create the execution state.
1902 Handle<Object> exec_state;
1903 // Bail out and don't call debugger if exception.
1904 if (!MakeExecutionState().ToHandle(&exec_state)) return;
1905
1906 CallEventCallback(event, exec_state, event_data, NULL);
1907 } else {
1908 // Process debug event.
1909 ProcessDebugEvent(event, Handle<JSObject>::cast(event_data), true);
1910 }
1882 } 1911 }
1883 1912
1884 1913
1885 Handle<Context> Debug::GetDebugContext() { 1914 Handle<Context> Debug::GetDebugContext() {
1886 if (!is_loaded()) return Handle<Context>(); 1915 if (!is_loaded()) return Handle<Context>();
1887 DebugScope debug_scope(this); 1916 DebugScope debug_scope(this);
1888 if (debug_scope.failed()) return Handle<Context>(); 1917 if (debug_scope.failed()) return Handle<Context>();
1889 // The global handle may be destroyed soon after. Return it reboxed. 1918 // The global handle may be destroyed soon after. Return it reboxed.
1890 return handle(*debug_context(), isolate_); 1919 return handle(*debug_context(), isolate_);
1891 } 1920 }
1892 1921
1922 void Debug::NotifyMessageHandler(v8::DebugEvent event,
1923 Handle<JSObject> exec_state,
1924 Handle<JSObject> event_data,
1925 bool auto_continue) {
1926 // Prevent other interrupts from triggering, for example API callbacks,
1927 // while dispatching message handler callbacks.
1928 PostponeInterruptsScope no_interrupts(isolate_);
1929 DCHECK(is_active_);
1930 HandleScope scope(isolate_);
1931 // Process the individual events.
1932 bool sendEventMessage = false;
1933 switch (event) {
1934 case v8::Break:
1935 sendEventMessage = !auto_continue;
1936 break;
1937 case v8::NewFunction:
1938 case v8::BeforeCompile:
1939 case v8::CompileError:
1940 case v8::AsyncTaskEvent:
1941 break;
1942 case v8::Exception:
1943 case v8::AfterCompile:
1944 sendEventMessage = true;
1945 break;
1946 }
1947
1948 // The debug command interrupt flag might have been set when the command was
1949 // added. It should be enough to clear the flag only once while we are in the
1950 // debugger.
1951 DCHECK(in_debug_scope());
1952 isolate_->stack_guard()->ClearDebugCommand();
1953
1954 // Notify the debugger that a debug event has occurred unless auto continue is
1955 // active in which case no event is send.
1956 if (sendEventMessage) {
1957 MessageImpl message = MessageImpl::NewEvent(
1958 event, auto_continue, Handle<JSObject>::cast(exec_state),
1959 Handle<JSObject>::cast(event_data));
1960 InvokeMessageHandler(message);
1961 }
1962
1963 // If auto continue don't make the event cause a break, but process messages
1964 // in the queue if any. For script collected events don't even process
1965 // messages in the queue as the execution state might not be what is expected
1966 // by the client.
1967 if (auto_continue && !has_commands()) return;
1968
1969 // DebugCommandProcessor goes here.
1970 bool running = auto_continue;
1971
1972 Handle<Object> cmd_processor_ctor =
1973 JSReceiver::GetProperty(isolate_, exec_state, "debugCommandProcessor")
1974 .ToHandleChecked();
1975 Handle<Object> ctor_args[] = {isolate_->factory()->ToBoolean(running)};
1976 Handle<JSReceiver> cmd_processor = Handle<JSReceiver>::cast(
1977 Execution::Call(isolate_, cmd_processor_ctor, exec_state, 1, ctor_args)
1978 .ToHandleChecked());
1979 Handle<JSFunction> process_debug_request = Handle<JSFunction>::cast(
1980 JSReceiver::GetProperty(isolate_, cmd_processor, "processDebugRequest")
1981 .ToHandleChecked());
1982 Handle<Object> is_running =
1983 JSReceiver::GetProperty(isolate_, cmd_processor, "isRunning")
1984 .ToHandleChecked();
1985
1986 // Process requests from the debugger.
1987 do {
1988 // Wait for new command in the queue.
1989 command_received_.Wait();
1990
1991 // Get the command from the queue.
1992 CommandMessage command = command_queue_.Get();
1993 isolate_->logger()->DebugTag(
1994 "Got request from command queue, in interactive loop.");
1995 if (!is_active()) {
1996 // Delete command text and user data.
1997 command.Dispose();
1998 return;
1999 }
2000
2001 Vector<const uc16> command_text(
2002 const_cast<const uc16*>(command.text().start()),
2003 command.text().length());
2004 Handle<String> request_text = isolate_->factory()
2005 ->NewStringFromTwoByte(command_text)
2006 .ToHandleChecked();
2007 Handle<Object> request_args[] = {request_text};
2008 Handle<Object> answer_value;
2009 Handle<String> answer;
2010 MaybeHandle<Object> maybe_exception;
2011 MaybeHandle<Object> maybe_result =
2012 Execution::TryCall(isolate_, process_debug_request, cmd_processor, 1,
2013 request_args, &maybe_exception);
2014
2015 if (maybe_result.ToHandle(&answer_value)) {
2016 if (answer_value->IsUndefined(isolate_)) {
2017 answer = isolate_->factory()->empty_string();
2018 } else {
2019 answer = Handle<String>::cast(answer_value);
2020 }
2021
2022 // Log the JSON request/response.
2023 if (FLAG_trace_debug_json) {
2024 PrintF("%s\n", request_text->ToCString().get());
2025 PrintF("%s\n", answer->ToCString().get());
2026 }
2027
2028 Handle<Object> is_running_args[] = {answer};
2029 maybe_result = Execution::Call(isolate_, is_running, cmd_processor, 1,
2030 is_running_args);
2031 Handle<Object> result;
2032 if (!maybe_result.ToHandle(&result)) break;
2033 running = result->IsTrue(isolate_);
2034 } else {
2035 Handle<Object> exception;
2036 if (!maybe_exception.ToHandle(&exception)) break;
2037 Handle<Object> result;
2038 if (!Object::ToString(isolate_, exception).ToHandle(&result)) break;
2039 answer = Handle<String>::cast(result);
2040 }
2041
2042 // Return the result.
2043 MessageImpl message = MessageImpl::NewResponse(
2044 event, running, exec_state, event_data, answer, command.client_data());
2045 InvokeMessageHandler(message);
2046 command.Dispose();
2047
2048 // Return from debug event processing if either the VM is put into the
2049 // running state (through a continue command) or auto continue is active
2050 // and there are no more commands queued.
2051 } while (!running || has_commands());
2052 command_queue_.Clear();
2053 }
1893 2054
1894 void Debug::SetEventListener(Handle<Object> callback, 2055 void Debug::SetEventListener(Handle<Object> callback,
1895 Handle<Object> data) { 2056 Handle<Object> data) {
1896 GlobalHandles* global_handles = isolate_->global_handles(); 2057 GlobalHandles* global_handles = isolate_->global_handles();
1897 2058
1898 // Remove existing entry. 2059 // Remove existing entry.
1899 GlobalHandles::Destroy(event_listener_.location()); 2060 GlobalHandles::Destroy(event_listener_.location());
1900 event_listener_ = Handle<Object>(); 2061 event_listener_ = Handle<Object>();
1901 GlobalHandles::Destroy(event_listener_data_.location()); 2062 GlobalHandles::Destroy(event_listener_data_.location());
1902 event_listener_data_ = Handle<Object>(); 2063 event_listener_data_ = Handle<Object>();
1903 2064
1904 // Set new entry. 2065 // Set new entry.
1905 if (!callback->IsUndefined(isolate_) && !callback->IsNull(isolate_)) { 2066 if (!callback->IsUndefined(isolate_) && !callback->IsNull(isolate_)) {
1906 event_listener_ = global_handles->Create(*callback); 2067 event_listener_ = global_handles->Create(*callback);
1907 if (data.is_null()) data = isolate_->factory()->undefined_value(); 2068 if (data.is_null()) data = isolate_->factory()->undefined_value();
1908 event_listener_data_ = global_handles->Create(*data); 2069 event_listener_data_ = global_handles->Create(*data);
1909 } 2070 }
1910 2071
1911 UpdateState(); 2072 UpdateState();
1912 } 2073 }
1913 2074
2075 void Debug::SetMessageHandler(v8::Debug::MessageHandler handler) {
2076 message_handler_ = handler;
2077 UpdateState();
2078 if (handler == NULL && in_debug_scope()) {
2079 // Send an empty command to the debugger if in a break to make JavaScript
2080 // run again if the debugger is closed.
2081 EnqueueCommandMessage(Vector<const uint16_t>::empty());
2082 }
2083 }
1914 2084
1915 void Debug::UpdateState() { 2085 void Debug::UpdateState() {
1916 bool is_active = !event_listener_.is_null(); 2086 bool is_active = message_handler_ != NULL || !event_listener_.is_null();
1917 if (is_active || in_debug_scope()) { 2087 if (is_active || in_debug_scope()) {
1918 // Note that the debug context could have already been loaded to 2088 // Note that the debug context could have already been loaded to
1919 // bootstrap test cases. 2089 // bootstrap test cases.
1920 isolate_->compilation_cache()->Disable(); 2090 isolate_->compilation_cache()->Disable();
1921 is_active = Load(); 2091 is_active = Load();
1922 } else if (is_loaded()) { 2092 } else if (is_loaded()) {
1923 isolate_->compilation_cache()->Enable(); 2093 isolate_->compilation_cache()->Enable();
1924 Unload(); 2094 Unload();
1925 } 2095 }
1926 is_active_ = is_active; 2096 is_active_ = is_active;
1927 } 2097 }
1928 2098
2099 // Calls the registered debug message handler. This callback is part of the
2100 // public API.
2101 void Debug::InvokeMessageHandler(MessageImpl message) {
2102 if (message_handler_ != NULL) message_handler_(message);
2103 }
2104
2105 // Puts a command coming from the public API on the queue. Creates
2106 // a copy of the command string managed by the debugger. Up to this
2107 // point, the command data was managed by the API client. Called
2108 // by the API client thread.
2109 void Debug::EnqueueCommandMessage(Vector<const uint16_t> command,
2110 v8::Debug::ClientData* client_data) {
2111 // Need to cast away const.
2112 CommandMessage message = CommandMessage::New(
2113 Vector<uint16_t>(const_cast<uint16_t*>(command.start()),
2114 command.length()),
2115 client_data);
2116 isolate_->logger()->DebugTag("Put command on command_queue.");
2117 command_queue_.Put(message);
2118 command_received_.Signal();
2119
2120 // Set the debug command break flag to have the command processed.
2121 if (!in_debug_scope()) isolate_->stack_guard()->RequestDebugCommand();
2122 }
1929 2123
1930 MaybeHandle<Object> Debug::Call(Handle<Object> fun, Handle<Object> data) { 2124 MaybeHandle<Object> Debug::Call(Handle<Object> fun, Handle<Object> data) {
1931 DebugScope debug_scope(this); 2125 DebugScope debug_scope(this);
1932 if (debug_scope.failed()) return isolate_->factory()->undefined_value(); 2126 if (debug_scope.failed()) return isolate_->factory()->undefined_value();
1933 2127
1934 // Create the execution state. 2128 // Create the execution state.
1935 Handle<Object> exec_state; 2129 Handle<Object> exec_state;
1936 if (!MakeExecutionState().ToHandle(&exec_state)) { 2130 if (!MakeExecutionState().ToHandle(&exec_state)) {
1937 return isolate_->factory()->undefined_value(); 2131 return isolate_->factory()->undefined_value();
1938 } 2132 }
(...skipping 27 matching lines...) Expand all
1966 if (!JSFunction::cast(fun)->shared()->IsSubjectToDebugging()) return; 2160 if (!JSFunction::cast(fun)->shared()->IsSubjectToDebugging()) return;
1967 JSGlobalObject* global = 2161 JSGlobalObject* global =
1968 JSFunction::cast(fun)->context()->global_object(); 2162 JSFunction::cast(fun)->context()->global_object();
1969 // Don't stop in debugger functions. 2163 // Don't stop in debugger functions.
1970 if (IsDebugGlobal(global)) return; 2164 if (IsDebugGlobal(global)) return;
1971 // Don't stop if the break location is muted. 2165 // Don't stop if the break location is muted.
1972 if (IsMutedAtCurrentLocation(it.frame())) return; 2166 if (IsMutedAtCurrentLocation(it.frame())) return;
1973 } 2167 }
1974 } 2168 }
1975 2169
2170 // Collect the break state before clearing the flags.
2171 bool debug_command_only = isolate_->stack_guard()->CheckDebugCommand() &&
2172 !isolate_->stack_guard()->CheckDebugBreak();
2173
1976 isolate_->stack_guard()->ClearDebugBreak(); 2174 isolate_->stack_guard()->ClearDebugBreak();
1977 2175
1978 // Clear stepping to avoid duplicate breaks. 2176 // Clear stepping to avoid duplicate breaks.
1979 ClearStepping(); 2177 ClearStepping();
1980 2178
2179 ProcessDebugMessages(debug_command_only);
2180 }
2181
2182 void Debug::ProcessDebugMessages(bool debug_command_only) {
2183 isolate_->stack_guard()->ClearDebugCommand();
2184
2185 StackLimitCheck check(isolate_);
2186 if (check.HasOverflowed()) return;
2187
1981 HandleScope scope(isolate_); 2188 HandleScope scope(isolate_);
1982 DebugScope debug_scope(this); 2189 DebugScope debug_scope(this);
1983 if (debug_scope.failed()) return; 2190 if (debug_scope.failed()) return;
1984 2191
1985 // Notify the debug event listeners. 2192 // Notify the debug event listeners. Indicate auto continue if the break was
1986 OnDebugBreak(isolate_->factory()->undefined_value()); 2193 // a debug command break.
2194 OnDebugBreak(isolate_->factory()->undefined_value(), debug_command_only);
1987 } 2195 }
1988 2196
1989 #ifdef DEBUG 2197 #ifdef DEBUG
1990 void Debug::PrintBreakLocation() { 2198 void Debug::PrintBreakLocation() {
1991 if (!FLAG_print_break_location) return; 2199 if (!FLAG_print_break_location) return;
1992 HandleScope scope(isolate_); 2200 HandleScope scope(isolate_);
1993 JavaScriptFrameIterator iterator(isolate_); 2201 JavaScriptFrameIterator iterator(isolate_);
1994 if (iterator.done()) return; 2202 if (iterator.done()) return;
1995 JavaScriptFrame* frame = iterator.frame(); 2203 JavaScriptFrame* frame = iterator.frame();
1996 FrameSummary summary = FrameSummary::GetFirst(frame); 2204 FrameSummary summary = FrameSummary::GetFirst(frame);
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
2060 } 2268 }
2061 2269
2062 2270
2063 DebugScope::~DebugScope() { 2271 DebugScope::~DebugScope() {
2064 if (!failed_ && prev_ == NULL) { 2272 if (!failed_ && prev_ == NULL) {
2065 // Clear mirror cache when leaving the debugger. Skip this if there is a 2273 // Clear mirror cache when leaving the debugger. Skip this if there is a
2066 // pending exception as clearing the mirror cache calls back into 2274 // pending exception as clearing the mirror cache calls back into
2067 // JavaScript. This can happen if the v8::Debug::Call is used in which 2275 // JavaScript. This can happen if the v8::Debug::Call is used in which
2068 // case the exception should end up in the calling code. 2276 // case the exception should end up in the calling code.
2069 if (!isolate()->has_pending_exception()) debug_->ClearMirrorCache(); 2277 if (!isolate()->has_pending_exception()) debug_->ClearMirrorCache();
2278
2279 // If there are commands in the queue when leaving the debugger request
2280 // that these commands are processed.
2281 if (debug_->has_commands()) isolate()->stack_guard()->RequestDebugCommand();
2070 } 2282 }
2071 2283
2072 // Leaving this debugger entry. 2284 // Leaving this debugger entry.
2073 base::NoBarrier_Store(&debug_->thread_local_.current_debug_scope_, 2285 base::NoBarrier_Store(&debug_->thread_local_.current_debug_scope_,
2074 reinterpret_cast<base::AtomicWord>(prev_)); 2286 reinterpret_cast<base::AtomicWord>(prev_));
2075 2287
2076 // Restore to the previous break state. 2288 // Restore to the previous break state.
2077 debug_->thread_local_.break_frame_id_ = break_frame_id_; 2289 debug_->thread_local_.break_frame_id_ = break_frame_id_;
2078 debug_->thread_local_.break_id_ = break_id_; 2290 debug_->thread_local_.break_id_ = break_id_;
2079 debug_->thread_local_.return_value_ = return_value_; 2291 debug_->thread_local_.return_value_ = return_value_;
2080 2292
2081 debug_->UpdateState(); 2293 debug_->UpdateState();
2082 } 2294 }
2083 2295
2296 MessageImpl MessageImpl::NewEvent(DebugEvent event, bool running,
2297 Handle<JSObject> exec_state,
2298 Handle<JSObject> event_data) {
2299 MessageImpl message(true, event, running, exec_state, event_data,
2300 Handle<String>(), NULL);
2301 return message;
2302 }
2303
2304 MessageImpl MessageImpl::NewResponse(DebugEvent event, bool running,
2305 Handle<JSObject> exec_state,
2306 Handle<JSObject> event_data,
2307 Handle<String> response_json,
2308 v8::Debug::ClientData* client_data) {
2309 MessageImpl message(false, event, running, exec_state, event_data,
2310 response_json, client_data);
2311 return message;
2312 }
2313
2314 MessageImpl::MessageImpl(bool is_event, DebugEvent event, bool running,
2315 Handle<JSObject> exec_state,
2316 Handle<JSObject> event_data,
2317 Handle<String> response_json,
2318 v8::Debug::ClientData* client_data)
2319 : is_event_(is_event),
2320 event_(event),
2321 running_(running),
2322 exec_state_(exec_state),
2323 event_data_(event_data),
2324 response_json_(response_json),
2325 client_data_(client_data) {}
2326
2327 bool MessageImpl::IsEvent() const { return is_event_; }
2328
2329 bool MessageImpl::IsResponse() const { return !is_event_; }
2330
2331 DebugEvent MessageImpl::GetEvent() const { return event_; }
2332
2333 bool MessageImpl::WillStartRunning() const { return running_; }
2334
2335 v8::Local<v8::Object> MessageImpl::GetExecutionState() const {
2336 return v8::Utils::ToLocal(exec_state_);
2337 }
2338
2339 v8::Isolate* MessageImpl::GetIsolate() const {
2340 return reinterpret_cast<v8::Isolate*>(exec_state_->GetIsolate());
2341 }
2342
2343 v8::Local<v8::Object> MessageImpl::GetEventData() const {
2344 return v8::Utils::ToLocal(event_data_);
2345 }
2346
2347 v8::Local<v8::String> MessageImpl::GetJSON() const {
2348 Isolate* isolate = event_data_->GetIsolate();
2349 v8::EscapableHandleScope scope(reinterpret_cast<v8::Isolate*>(isolate));
2350
2351 if (IsEvent()) {
2352 // Call toJSONProtocol on the debug event object.
2353 Handle<Object> fun =
2354 JSReceiver::GetProperty(isolate, event_data_, "toJSONProtocol")
2355 .ToHandleChecked();
2356 if (!fun->IsJSFunction()) {
2357 return v8::Local<v8::String>();
2358 }
2359
2360 MaybeHandle<Object> maybe_json =
2361 Execution::TryCall(isolate, fun, event_data_, 0, NULL);
2362 Handle<Object> json;
2363 if (!maybe_json.ToHandle(&json) || !json->IsString()) {
2364 return v8::Local<v8::String>();
2365 }
2366 return scope.Escape(v8::Utils::ToLocal(Handle<String>::cast(json)));
2367 } else {
2368 return v8::Utils::ToLocal(response_json_);
2369 }
2370 }
2371
2372 namespace {
2373 v8::Local<v8::Context> GetDebugEventContext(Isolate* isolate) {
2374 Handle<Context> context = isolate->debug()->debugger_entry()->GetContext();
2375 // Isolate::context() may have been NULL when "script collected" event
2376 // occured.
2377 if (context.is_null()) return v8::Local<v8::Context>();
2378 Handle<Context> native_context(context->native_context());
2379 return v8::Utils::ToLocal(native_context);
2380 }
2381 } // anonymous namespace
2382
2383 v8::Local<v8::Context> MessageImpl::GetEventContext() const {
2384 Isolate* isolate = event_data_->GetIsolate();
2385 v8::Local<v8::Context> context = GetDebugEventContext(isolate);
2386 // Isolate::context() may be NULL when "script collected" event occurs.
2387 DCHECK(!context.IsEmpty());
2388 return context;
2389 }
2390
2391 v8::Debug::ClientData* MessageImpl::GetClientData() const {
2392 return client_data_;
2393 }
2084 2394
2085 EventDetailsImpl::EventDetailsImpl(DebugEvent event, 2395 EventDetailsImpl::EventDetailsImpl(DebugEvent event,
2086 Handle<JSObject> exec_state, 2396 Handle<JSObject> exec_state,
2087 Handle<JSObject> event_data, 2397 Handle<JSObject> event_data,
2088 Handle<Object> callback_data, 2398 Handle<Object> callback_data,
2089 v8::Debug::ClientData* client_data) 2399 v8::Debug::ClientData* client_data)
2090 : event_(event), 2400 : event_(event),
2091 exec_state_(exec_state), 2401 exec_state_(exec_state),
2092 event_data_(event_data), 2402 event_data_(event_data),
2093 callback_data_(callback_data), 2403 callback_data_(callback_data),
2094 client_data_(client_data) {} 2404 client_data_(client_data) {}
2095 2405
2096 2406
2097 DebugEvent EventDetailsImpl::GetEvent() const { 2407 DebugEvent EventDetailsImpl::GetEvent() const {
2098 return event_; 2408 return event_;
2099 } 2409 }
2100 2410
2101 2411
2102 v8::Local<v8::Object> EventDetailsImpl::GetExecutionState() const { 2412 v8::Local<v8::Object> EventDetailsImpl::GetExecutionState() const {
2103 return v8::Utils::ToLocal(exec_state_); 2413 return v8::Utils::ToLocal(exec_state_);
2104 } 2414 }
2105 2415
2106 2416
2107 v8::Local<v8::Object> EventDetailsImpl::GetEventData() const { 2417 v8::Local<v8::Object> EventDetailsImpl::GetEventData() const {
2108 return v8::Utils::ToLocal(event_data_); 2418 return v8::Utils::ToLocal(event_data_);
2109 } 2419 }
2110 2420
2111 2421
2112 v8::Local<v8::Context> EventDetailsImpl::GetEventContext() const { 2422 v8::Local<v8::Context> EventDetailsImpl::GetEventContext() const {
2113 Handle<Context> context = 2423 return GetDebugEventContext(exec_state_->GetIsolate());
2114 exec_state_->GetIsolate()->debug()->debugger_entry()->GetContext();
2115 if (context.is_null()) return v8::Local<v8::Context>();
2116 Handle<Context> native_context(context->native_context());
2117 return v8::Utils::ToLocal(native_context);
2118 } 2424 }
2119 2425
2120 2426
2121 v8::Local<v8::Value> EventDetailsImpl::GetCallbackData() const { 2427 v8::Local<v8::Value> EventDetailsImpl::GetCallbackData() const {
2122 return v8::Utils::ToLocal(callback_data_); 2428 return v8::Utils::ToLocal(callback_data_);
2123 } 2429 }
2124 2430
2125 2431
2126 v8::Debug::ClientData* EventDetailsImpl::GetClientData() const { 2432 v8::Debug::ClientData* EventDetailsImpl::GetClientData() const {
2127 return client_data_; 2433 return client_data_;
2128 } 2434 }
2129 2435
2130 v8::Isolate* EventDetailsImpl::GetIsolate() const { 2436 v8::Isolate* EventDetailsImpl::GetIsolate() const {
2131 return reinterpret_cast<v8::Isolate*>(exec_state_->GetIsolate()); 2437 return reinterpret_cast<v8::Isolate*>(exec_state_->GetIsolate());
2132 } 2438 }
2133 2439
2440 CommandMessage::CommandMessage()
2441 : text_(Vector<uint16_t>::empty()), client_data_(NULL) {}
2442
2443 CommandMessage::CommandMessage(const Vector<uint16_t>& text,
2444 v8::Debug::ClientData* data)
2445 : text_(text), client_data_(data) {}
2446
2447 void CommandMessage::Dispose() {
2448 text_.Dispose();
2449 delete client_data_;
2450 client_data_ = NULL;
2451 }
2452
2453 CommandMessage CommandMessage::New(const Vector<uint16_t>& command,
2454 v8::Debug::ClientData* data) {
2455 return CommandMessage(command.Clone(), data);
2456 }
2457
2458 CommandMessageQueue::CommandMessageQueue(int size)
2459 : start_(0), end_(0), size_(size) {
2460 messages_ = NewArray<CommandMessage>(size);
2461 }
2462
2463 CommandMessageQueue::~CommandMessageQueue() {
2464 while (!IsEmpty()) Get().Dispose();
2465 DeleteArray(messages_);
2466 }
2467
2468 CommandMessage CommandMessageQueue::Get() {
2469 DCHECK(!IsEmpty());
2470 int result = start_;
2471 start_ = (start_ + 1) % size_;
2472 return messages_[result];
2473 }
2474
2475 void CommandMessageQueue::Put(const CommandMessage& message) {
2476 if ((end_ + 1) % size_ == start_) {
2477 Expand();
2478 }
2479 messages_[end_] = message;
2480 end_ = (end_ + 1) % size_;
2481 }
2482
2483 void CommandMessageQueue::Expand() {
2484 CommandMessageQueue new_queue(size_ * 2);
2485 while (!IsEmpty()) {
2486 new_queue.Put(Get());
2487 }
2488 CommandMessage* array_to_free = messages_;
2489 *this = new_queue;
2490 new_queue.messages_ = array_to_free;
2491 // Make the new_queue empty so that it doesn't call Dispose on any messages.
2492 new_queue.start_ = new_queue.end_;
2493 // Automatic destructor called on new_queue, freeing array_to_free.
2494 }
2495
2496 LockingCommandMessageQueue::LockingCommandMessageQueue(Logger* logger, int size)
2497 : logger_(logger), queue_(size) {}
2498
2499 bool LockingCommandMessageQueue::IsEmpty() const {
2500 base::LockGuard<base::Mutex> lock_guard(&mutex_);
2501 return queue_.IsEmpty();
2502 }
2503
2504 CommandMessage LockingCommandMessageQueue::Get() {
2505 base::LockGuard<base::Mutex> lock_guard(&mutex_);
2506 CommandMessage result = queue_.Get();
2507 logger_->DebugEvent("Get", result.text());
2508 return result;
2509 }
2510
2511 void LockingCommandMessageQueue::Put(const CommandMessage& message) {
2512 base::LockGuard<base::Mutex> lock_guard(&mutex_);
2513 queue_.Put(message);
2514 logger_->DebugEvent("Put", message.text());
2515 }
2516
2517 void LockingCommandMessageQueue::Clear() {
2518 base::LockGuard<base::Mutex> lock_guard(&mutex_);
2519 queue_.Clear();
2520 }
2521
2134 } // namespace internal 2522 } // namespace internal
2135 } // namespace v8 2523 } // namespace v8
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698