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

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

Issue 2644233003: Revert of [debugger api] remove legacy JSON debug protocol. (Closed)
Patch Set: Created 3 years, 11 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
« no previous file with comments | « src/debug/debug.h ('k') | src/debug/debug.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 #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 22 matching lines...) Expand all
33 33
34 #include "include/v8-debug.h" 34 #include "include/v8-debug.h"
35 35
36 namespace v8 { 36 namespace v8 {
37 namespace internal { 37 namespace internal {
38 38
39 Debug::Debug(Isolate* isolate) 39 Debug::Debug(Isolate* isolate)
40 : debug_context_(Handle<Context>()), 40 : debug_context_(Handle<Context>()),
41 event_listener_(Handle<Object>()), 41 event_listener_(Handle<Object>()),
42 event_listener_data_(Handle<Object>()), 42 event_listener_data_(Handle<Object>()),
43 message_handler_(NULL),
44 command_received_(0),
45 command_queue_(isolate->logger(), kQueueInitialSize),
43 is_active_(false), 46 is_active_(false),
44 hook_on_function_call_(false), 47 hook_on_function_call_(false),
45 is_suppressed_(false), 48 is_suppressed_(false),
46 live_edit_enabled_(true), // TODO(yangguo): set to false by default. 49 live_edit_enabled_(true), // TODO(yangguo): set to false by default.
47 break_disabled_(false), 50 break_disabled_(false),
48 break_points_active_(true), 51 break_points_active_(true),
49 in_debug_event_listener_(false), 52 in_debug_event_listener_(false),
50 break_on_exception_(false), 53 break_on_exception_(false),
51 break_on_uncaught_exception_(false), 54 break_on_uncaught_exception_(false),
52 side_effect_check_failed_(false), 55 side_effect_check_failed_(false),
(...skipping 469 matching lines...) Expand 10 before | Expand all | Expand 10 after
522 525
523 // Find actual break points, if any, and trigger debug break event. 526 // Find actual break points, if any, and trigger debug break event.
524 MaybeHandle<FixedArray> break_points_hit = 527 MaybeHandle<FixedArray> break_points_hit =
525 CheckBreakPoints(debug_info, &location); 528 CheckBreakPoints(debug_info, &location);
526 if (!break_points_hit.is_null()) { 529 if (!break_points_hit.is_null()) {
527 // Clear all current stepping setup. 530 // Clear all current stepping setup.
528 ClearStepping(); 531 ClearStepping();
529 // Notify the debug event listeners. 532 // Notify the debug event listeners.
530 Handle<JSArray> jsarr = isolate_->factory()->NewJSArrayWithElements( 533 Handle<JSArray> jsarr = isolate_->factory()->NewJSArrayWithElements(
531 break_points_hit.ToHandleChecked()); 534 break_points_hit.ToHandleChecked());
532 OnDebugBreak(jsarr); 535 OnDebugBreak(jsarr, false);
533 return; 536 return;
534 } 537 }
535 538
536 // No break point. Check for stepping. 539 // No break point. Check for stepping.
537 StepAction step_action = last_step_action(); 540 StepAction step_action = last_step_action();
538 Address current_fp = frame->UnpaddedFP(); 541 Address current_fp = frame->UnpaddedFP();
539 Address target_fp = thread_local_.target_fp_; 542 Address target_fp = thread_local_.target_fp_;
540 Address last_fp = thread_local_.last_fp_; 543 Address last_fp = thread_local_.last_fp_;
541 544
542 bool step_break = false; 545 bool step_break = false;
(...skipping 21 matching lines...) Expand all
564 case StepFrame: 567 case StepFrame:
565 step_break = current_fp != last_fp; 568 step_break = current_fp != last_fp;
566 break; 569 break;
567 } 570 }
568 571
569 // Clear all current stepping setup. 572 // Clear all current stepping setup.
570 ClearStepping(); 573 ClearStepping();
571 574
572 if (step_break) { 575 if (step_break) {
573 // Notify the debug event listeners. 576 // Notify the debug event listeners.
574 OnDebugBreak(isolate_->factory()->undefined_value()); 577 OnDebugBreak(isolate_->factory()->undefined_value(), false);
575 } else { 578 } else {
576 // Re-prepare to continue. 579 // Re-prepare to continue.
577 PrepareStep(step_action); 580 PrepareStep(step_action);
578 } 581 }
579 } 582 }
580 583
581 584
582 // Find break point objects for this location, if any, and evaluate them. 585 // Find break point objects for this location, if any, and evaluate them.
583 // Return an array of break point objects that evaluated true, or an empty 586 // Return an array of break point objects that evaluated true, or an empty
584 // handle if none evaluated true. 587 // handle if none evaluated true.
(...skipping 1191 matching lines...) Expand 10 before | Expand all | Expand 10 after
1776 1779
1777 // Create the event data object. 1780 // Create the event data object.
1778 Handle<Object> event_data; 1781 Handle<Object> event_data;
1779 // Bail out and don't call debugger if exception. 1782 // Bail out and don't call debugger if exception.
1780 if (!MakeExceptionEvent( 1783 if (!MakeExceptionEvent(
1781 exception, uncaught, promise).ToHandle(&event_data)) { 1784 exception, uncaught, promise).ToHandle(&event_data)) {
1782 return; 1785 return;
1783 } 1786 }
1784 1787
1785 // Process debug event. 1788 // Process debug event.
1786 ProcessDebugEvent(v8::Exception, Handle<JSObject>::cast(event_data)); 1789 ProcessDebugEvent(v8::Exception, Handle<JSObject>::cast(event_data), false);
1787 // Return to continue execution from where the exception was thrown. 1790 // Return to continue execution from where the exception was thrown.
1788 } 1791 }
1789 1792
1790 void Debug::OnDebugBreak(Handle<Object> break_points_hit) { 1793 void Debug::OnDebugBreak(Handle<Object> break_points_hit, bool auto_continue) {
1791 // The caller provided for DebugScope. 1794 // The caller provided for DebugScope.
1792 AssertDebugContext(); 1795 AssertDebugContext();
1793 // Bail out if there is no listener for this event 1796 // Bail out if there is no listener for this event
1794 if (ignore_events()) return; 1797 if (ignore_events()) return;
1795 1798
1796 #ifdef DEBUG 1799 #ifdef DEBUG
1797 PrintBreakLocation(); 1800 PrintBreakLocation();
1798 #endif // DEBUG 1801 #endif // DEBUG
1799 1802
1800 if (debug_event_listener_) { 1803 if (debug_event_listener_) {
(...skipping 14 matching lines...) Expand all
1815 if (!non_inspector_listener_exists()) return; 1818 if (!non_inspector_listener_exists()) return;
1816 } 1819 }
1817 1820
1818 HandleScope scope(isolate_); 1821 HandleScope scope(isolate_);
1819 // Create the event data object. 1822 // Create the event data object.
1820 Handle<Object> event_data; 1823 Handle<Object> event_data;
1821 // Bail out and don't call debugger if exception. 1824 // Bail out and don't call debugger if exception.
1822 if (!MakeBreakEvent(break_points_hit).ToHandle(&event_data)) return; 1825 if (!MakeBreakEvent(break_points_hit).ToHandle(&event_data)) return;
1823 1826
1824 // Process debug event. 1827 // Process debug event.
1825 ProcessDebugEvent(v8::Break, Handle<JSObject>::cast(event_data)); 1828 ProcessDebugEvent(v8::Break, Handle<JSObject>::cast(event_data),
1829 auto_continue);
1826 } 1830 }
1827 1831
1828 1832
1829 void Debug::OnCompileError(Handle<Script> script) { 1833 void Debug::OnCompileError(Handle<Script> script) {
1830 ProcessCompileEvent(v8::CompileError, script); 1834 ProcessCompileEvent(v8::CompileError, script);
1831 } 1835 }
1832 1836
1833 1837
1834 // Handle debugger actions when a new script is compiled. 1838 // Handle debugger actions when a new script is compiled.
1835 void Debug::OnAfterCompile(Handle<Script> script) { 1839 void Debug::OnAfterCompile(Handle<Script> script) {
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
1905 1909
1906 // Create the script collected state object. 1910 // Create the script collected state object.
1907 Handle<Object> event_data; 1911 Handle<Object> event_data;
1908 // Bail out and don't call debugger if exception. 1912 // Bail out and don't call debugger if exception.
1909 if (!MakeAsyncTaskEvent(handle(Smi::FromInt(type), isolate_), 1913 if (!MakeAsyncTaskEvent(handle(Smi::FromInt(type), isolate_),
1910 handle(Smi::FromInt(id), isolate_)) 1914 handle(Smi::FromInt(id), isolate_))
1911 .ToHandle(&event_data)) 1915 .ToHandle(&event_data))
1912 return; 1916 return;
1913 1917
1914 // Process debug event. 1918 // Process debug event.
1915 ProcessDebugEvent(v8::AsyncTaskEvent, Handle<JSObject>::cast(event_data)); 1919 ProcessDebugEvent(v8::AsyncTaskEvent, Handle<JSObject>::cast(event_data),
1920 true);
1916 } 1921 }
1917 1922
1918 void Debug::ProcessDebugEvent(v8::DebugEvent event, 1923 void Debug::ProcessDebugEvent(v8::DebugEvent event, Handle<JSObject> event_data,
1919 Handle<JSObject> event_data) { 1924 bool auto_continue) {
1920 // Notify registered debug event listener. This can be either a C or
1921 // a JavaScript function.
1922 if (event_listener_.is_null()) return;
1923 HandleScope scope(isolate_); 1925 HandleScope scope(isolate_);
1924 1926
1925 // Create the execution state. 1927 // Create the execution state.
1926 Handle<Object> exec_state; 1928 Handle<Object> exec_state;
1927 // Bail out and don't call debugger if exception. 1929 // Bail out and don't call debugger if exception.
1928 if (!MakeExecutionState().ToHandle(&exec_state)) return; 1930 if (!MakeExecutionState().ToHandle(&exec_state)) return;
1929 1931
1932 // First notify the message handler if any.
1933 if (message_handler_ != NULL) {
1934 NotifyMessageHandler(event, Handle<JSObject>::cast(exec_state), event_data,
1935 auto_continue);
1936 }
1937 // Notify registered debug event listener. This can be either a C or
1938 // a JavaScript function. Don't call event listener for v8::Break
1939 // here, if it's only a debug command -- they will be processed later.
1940 if ((event != v8::Break || !auto_continue) && !event_listener_.is_null()) {
1941 CallEventCallback(event, exec_state, event_data, NULL);
1942 }
1943 }
1944
1945
1946 void Debug::CallEventCallback(v8::DebugEvent event,
1947 Handle<Object> exec_state,
1948 Handle<Object> event_data,
1949 v8::Debug::ClientData* client_data) {
1930 // Prevent other interrupts from triggering, for example API callbacks, 1950 // Prevent other interrupts from triggering, for example API callbacks,
1931 // while dispatching event listners. 1951 // while dispatching event listners.
1932 PostponeInterruptsScope postpone(isolate_); 1952 PostponeInterruptsScope postpone(isolate_);
1933 bool previous = in_debug_event_listener_; 1953 bool previous = in_debug_event_listener_;
1934 in_debug_event_listener_ = true; 1954 in_debug_event_listener_ = true;
1935 if (event_listener_->IsForeign()) { 1955 if (event_listener_->IsForeign()) {
1936 // Invoke the C debug event listener. 1956 // Invoke the C debug event listener.
1937 v8::Debug::EventCallback callback = FUNCTION_CAST<v8::Debug::EventCallback>( 1957 v8::Debug::EventCallback callback = FUNCTION_CAST<v8::Debug::EventCallback>(
1938 Handle<Foreign>::cast(event_listener_)->foreign_address()); 1958 Handle<Foreign>::cast(event_listener_)->foreign_address());
1939 EventDetailsImpl event_details(event, Handle<JSObject>::cast(exec_state), 1959 EventDetailsImpl event_details(event,
1960 Handle<JSObject>::cast(exec_state),
1940 Handle<JSObject>::cast(event_data), 1961 Handle<JSObject>::cast(event_data),
1941 event_listener_data_); 1962 event_listener_data_,
1963 client_data);
1942 callback(event_details); 1964 callback(event_details);
1943 CHECK(!isolate_->has_scheduled_exception()); 1965 CHECK(!isolate_->has_scheduled_exception());
1944 } else { 1966 } else {
1945 // Invoke the JavaScript debug event listener. 1967 // Invoke the JavaScript debug event listener.
1946 DCHECK(event_listener_->IsJSFunction()); 1968 DCHECK(event_listener_->IsJSFunction());
1947 Handle<Object> argv[] = { Handle<Object>(Smi::FromInt(event), isolate_), 1969 Handle<Object> argv[] = { Handle<Object>(Smi::FromInt(event), isolate_),
1948 exec_state, 1970 exec_state,
1949 event_data, 1971 event_data,
1950 event_listener_data_ }; 1972 event_listener_data_ };
1951 Handle<JSReceiver> global = isolate_->global_proxy(); 1973 Handle<JSReceiver> global = isolate_->global_proxy();
1952 MaybeHandle<Object> result = 1974 MaybeHandle<Object> result =
1953 Execution::Call(isolate_, Handle<JSFunction>::cast(event_listener_), 1975 Execution::Call(isolate_, Handle<JSFunction>::cast(event_listener_),
1954 global, arraysize(argv), argv); 1976 global, arraysize(argv), argv);
1955 CHECK(!result.is_null()); // Listeners must not throw. 1977 CHECK(!result.is_null()); // Listeners must not throw.
1956 } 1978 }
1957 in_debug_event_listener_ = previous; 1979 in_debug_event_listener_ = previous;
1958 } 1980 }
1959 1981
1960 void Debug::ProcessCompileEvent(v8::DebugEvent event, Handle<Script> script) { 1982 void Debug::ProcessCompileEvent(v8::DebugEvent event, Handle<Script> script) {
1961 if (ignore_events()) return; 1983 if (ignore_events()) return;
1962 if (script->type() != i::Script::TYPE_NORMAL && 1984 if (script->type() != i::Script::TYPE_NORMAL &&
1963 script->type() != i::Script::TYPE_WASM) { 1985 script->type() != i::Script::TYPE_WASM) {
1964 return; 1986 return;
1965 } 1987 }
1966 SuppressDebug while_processing(this); 1988 SuppressDebug while_processing(this);
1989 bool in_nested_debug_scope = in_debug_scope();
1967 DebugScope debug_scope(this); 1990 DebugScope debug_scope(this);
1968 if (debug_scope.failed()) return; 1991 if (debug_scope.failed()) return;
1969 1992
1970 if (debug_event_listener_) { 1993 if (debug_event_listener_) {
1971 debug_event_listener_->ScriptCompiled(ToApiHandle<debug::Script>(script), 1994 debug_event_listener_->ScriptCompiled(ToApiHandle<debug::Script>(script),
1972 event != v8::AfterCompile); 1995 event != v8::AfterCompile);
1973 if (!non_inspector_listener_exists()) return; 1996 if (!non_inspector_listener_exists()) return;
1974 } 1997 }
1975 1998
1976 HandleScope scope(isolate_); 1999 HandleScope scope(isolate_);
1977 // Create the compile state object. 2000 // Create the compile state object.
1978 Handle<Object> event_data; 2001 Handle<Object> event_data;
1979 // Bail out and don't call debugger if exception. 2002 // Bail out and don't call debugger if exception.
1980 if (!MakeCompileEvent(script, event).ToHandle(&event_data)) return; 2003 if (!MakeCompileEvent(script, event).ToHandle(&event_data)) return;
1981 2004
1982 // Process debug event. 2005 // Don't call NotifyMessageHandler if already in debug scope to avoid running
1983 ProcessDebugEvent(event, Handle<JSObject>::cast(event_data)); 2006 // nested command loop.
2007 if (in_nested_debug_scope) {
2008 if (event_listener_.is_null()) return;
2009 // Create the execution state.
2010 Handle<Object> exec_state;
2011 // Bail out and don't call debugger if exception.
2012 if (!MakeExecutionState().ToHandle(&exec_state)) return;
2013
2014 CallEventCallback(event, exec_state, event_data, NULL);
2015 } else {
2016 // Process debug event.
2017 ProcessDebugEvent(event, Handle<JSObject>::cast(event_data), true);
2018 }
1984 } 2019 }
1985 2020
1986 2021
1987 Handle<Context> Debug::GetDebugContext() { 2022 Handle<Context> Debug::GetDebugContext() {
1988 if (!is_loaded()) return Handle<Context>(); 2023 if (!is_loaded()) return Handle<Context>();
1989 DebugScope debug_scope(this); 2024 DebugScope debug_scope(this);
1990 if (debug_scope.failed()) return Handle<Context>(); 2025 if (debug_scope.failed()) return Handle<Context>();
1991 // The global handle may be destroyed soon after. Return it reboxed. 2026 // The global handle may be destroyed soon after. Return it reboxed.
1992 return handle(*debug_context(), isolate_); 2027 return handle(*debug_context(), isolate_);
1993 } 2028 }
1994 2029
2030 void Debug::NotifyMessageHandler(v8::DebugEvent event,
2031 Handle<JSObject> exec_state,
2032 Handle<JSObject> event_data,
2033 bool auto_continue) {
2034 // Prevent other interrupts from triggering, for example API callbacks,
2035 // while dispatching message handler callbacks.
2036 PostponeInterruptsScope no_interrupts(isolate_);
2037 DCHECK(is_active_);
2038 HandleScope scope(isolate_);
2039 // Process the individual events.
2040 bool sendEventMessage = false;
2041 switch (event) {
2042 case v8::Break:
2043 sendEventMessage = !auto_continue;
2044 break;
2045 case v8::CompileError:
2046 case v8::AsyncTaskEvent:
2047 break;
2048 case v8::Exception:
2049 case v8::AfterCompile:
2050 sendEventMessage = true;
2051 break;
2052 }
2053
2054 // The debug command interrupt flag might have been set when the command was
2055 // added. It should be enough to clear the flag only once while we are in the
2056 // debugger.
2057 DCHECK(in_debug_scope());
2058 isolate_->stack_guard()->ClearDebugCommand();
2059
2060 // Notify the debugger that a debug event has occurred unless auto continue is
2061 // active in which case no event is send.
2062 if (sendEventMessage) {
2063 MessageImpl message = MessageImpl::NewEvent(
2064 event, auto_continue, Handle<JSObject>::cast(exec_state),
2065 Handle<JSObject>::cast(event_data));
2066 InvokeMessageHandler(message);
2067 }
2068
2069 // If auto continue don't make the event cause a break, but process messages
2070 // in the queue if any. For script collected events don't even process
2071 // messages in the queue as the execution state might not be what is expected
2072 // by the client.
2073 if (auto_continue && !has_commands()) return;
2074
2075 // DebugCommandProcessor goes here.
2076 bool running = auto_continue;
2077
2078 Handle<Object> cmd_processor_ctor =
2079 JSReceiver::GetProperty(isolate_, exec_state, "debugCommandProcessor")
2080 .ToHandleChecked();
2081 Handle<Object> ctor_args[] = {isolate_->factory()->ToBoolean(running)};
2082 Handle<JSReceiver> cmd_processor = Handle<JSReceiver>::cast(
2083 Execution::Call(isolate_, cmd_processor_ctor, exec_state, 1, ctor_args)
2084 .ToHandleChecked());
2085 Handle<JSFunction> process_debug_request = Handle<JSFunction>::cast(
2086 JSReceiver::GetProperty(isolate_, cmd_processor, "processDebugRequest")
2087 .ToHandleChecked());
2088 Handle<Object> is_running =
2089 JSReceiver::GetProperty(isolate_, cmd_processor, "isRunning")
2090 .ToHandleChecked();
2091
2092 // Process requests from the debugger.
2093 do {
2094 // Wait for new command in the queue.
2095 command_received_.Wait();
2096
2097 // Get the command from the queue.
2098 CommandMessage command = command_queue_.Get();
2099 isolate_->logger()->DebugTag(
2100 "Got request from command queue, in interactive loop.");
2101 if (!is_active()) {
2102 // Delete command text and user data.
2103 command.Dispose();
2104 return;
2105 }
2106
2107 Vector<const uc16> command_text(
2108 const_cast<const uc16*>(command.text().start()),
2109 command.text().length());
2110 Handle<String> request_text = isolate_->factory()
2111 ->NewStringFromTwoByte(command_text)
2112 .ToHandleChecked();
2113 Handle<Object> request_args[] = {request_text};
2114 Handle<Object> answer_value;
2115 Handle<String> answer;
2116 MaybeHandle<Object> maybe_exception;
2117 MaybeHandle<Object> maybe_result = Execution::TryCall(
2118 isolate_, process_debug_request, cmd_processor, 1, request_args,
2119 Execution::MessageHandling::kReport, &maybe_exception);
2120
2121 if (maybe_result.ToHandle(&answer_value)) {
2122 if (answer_value->IsUndefined(isolate_)) {
2123 answer = isolate_->factory()->empty_string();
2124 } else {
2125 answer = Handle<String>::cast(answer_value);
2126 }
2127
2128 // Log the JSON request/response.
2129 if (FLAG_trace_debug_json) {
2130 PrintF("%s\n", request_text->ToCString().get());
2131 PrintF("%s\n", answer->ToCString().get());
2132 }
2133
2134 Handle<Object> is_running_args[] = {answer};
2135 maybe_result = Execution::Call(isolate_, is_running, cmd_processor, 1,
2136 is_running_args);
2137 Handle<Object> result;
2138 if (!maybe_result.ToHandle(&result)) break;
2139 running = result->IsTrue(isolate_);
2140 } else {
2141 Handle<Object> exception;
2142 if (!maybe_exception.ToHandle(&exception)) break;
2143 Handle<Object> result;
2144 if (!Object::ToString(isolate_, exception).ToHandle(&result)) break;
2145 answer = Handle<String>::cast(result);
2146 }
2147
2148 // Return the result.
2149 MessageImpl message = MessageImpl::NewResponse(
2150 event, running, exec_state, event_data, answer, command.client_data());
2151 InvokeMessageHandler(message);
2152 command.Dispose();
2153
2154 // Return from debug event processing if either the VM is put into the
2155 // running state (through a continue command) or auto continue is active
2156 // and there are no more commands queued.
2157 } while (!running || has_commands());
2158 command_queue_.Clear();
2159 }
1995 2160
1996 void Debug::SetEventListener(Handle<Object> callback, 2161 void Debug::SetEventListener(Handle<Object> callback,
1997 Handle<Object> data) { 2162 Handle<Object> data) {
1998 GlobalHandles* global_handles = isolate_->global_handles(); 2163 GlobalHandles* global_handles = isolate_->global_handles();
1999 2164
2000 // Remove existing entry. 2165 // Remove existing entry.
2001 GlobalHandles::Destroy(event_listener_.location()); 2166 GlobalHandles::Destroy(event_listener_.location());
2002 event_listener_ = Handle<Object>(); 2167 event_listener_ = Handle<Object>();
2003 GlobalHandles::Destroy(event_listener_data_.location()); 2168 GlobalHandles::Destroy(event_listener_data_.location());
2004 event_listener_data_ = Handle<Object>(); 2169 event_listener_data_ = Handle<Object>();
2005 2170
2006 // Set new entry. 2171 // Set new entry.
2007 if (!callback->IsNullOrUndefined(isolate_)) { 2172 if (!callback->IsNullOrUndefined(isolate_)) {
2008 event_listener_ = global_handles->Create(*callback); 2173 event_listener_ = global_handles->Create(*callback);
2009 if (data.is_null()) data = isolate_->factory()->undefined_value(); 2174 if (data.is_null()) data = isolate_->factory()->undefined_value();
2010 event_listener_data_ = global_handles->Create(*data); 2175 event_listener_data_ = global_handles->Create(*data);
2011 } 2176 }
2012 2177
2013 UpdateState(); 2178 UpdateState();
2014 } 2179 }
2015 2180
2181 void Debug::SetMessageHandler(v8::Debug::MessageHandler handler) {
2182 message_handler_ = handler;
2183 UpdateState();
2184 if (handler == NULL && in_debug_scope()) {
2185 // Send an empty command to the debugger if in a break to make JavaScript
2186 // run again if the debugger is closed.
2187 EnqueueCommandMessage(Vector<const uint16_t>::empty());
2188 }
2189 }
2016 2190
2017 void Debug::SetDebugEventListener(debug::DebugEventListener* listener) { 2191 void Debug::SetDebugEventListener(debug::DebugEventListener* listener) {
2018 debug_event_listener_ = listener; 2192 debug_event_listener_ = listener;
2019 UpdateState(); 2193 UpdateState();
2020 } 2194 }
2021 2195
2022 void Debug::UpdateState() { 2196 void Debug::UpdateState() {
2023 bool is_active = 2197 bool is_active = message_handler_ != nullptr || !event_listener_.is_null() ||
2024 !event_listener_.is_null() || debug_event_listener_ != nullptr; 2198 debug_event_listener_ != nullptr;
2025 if (is_active || in_debug_scope()) { 2199 if (is_active || in_debug_scope()) {
2026 // Note that the debug context could have already been loaded to 2200 // Note that the debug context could have already been loaded to
2027 // bootstrap test cases. 2201 // bootstrap test cases.
2028 isolate_->compilation_cache()->Disable(); 2202 isolate_->compilation_cache()->Disable();
2029 is_active = Load(); 2203 is_active = Load();
2030 } else if (is_loaded()) { 2204 } else if (is_loaded()) {
2031 isolate_->compilation_cache()->Enable(); 2205 isolate_->compilation_cache()->Enable();
2032 Unload(); 2206 Unload();
2033 } 2207 }
2034 is_active_ = is_active; 2208 is_active_ = is_active;
2035 } 2209 }
2036 2210
2037 void Debug::UpdateHookOnFunctionCall() { 2211 void Debug::UpdateHookOnFunctionCall() {
2038 STATIC_ASSERT(StepFrame > StepIn); 2212 STATIC_ASSERT(StepFrame > StepIn);
2039 STATIC_ASSERT(LastStepAction == StepFrame); 2213 STATIC_ASSERT(LastStepAction == StepFrame);
2040 hook_on_function_call_ = thread_local_.last_step_action_ >= StepIn || 2214 hook_on_function_call_ = thread_local_.last_step_action_ >= StepIn ||
2041 isolate_->needs_side_effect_check(); 2215 isolate_->needs_side_effect_check();
2042 } 2216 }
2043 2217
2218 // Calls the registered debug message handler. This callback is part of the
2219 // public API.
2220 void Debug::InvokeMessageHandler(MessageImpl message) {
2221 if (message_handler_ != NULL) message_handler_(message);
2222 }
2223
2224 // Puts a command coming from the public API on the queue. Creates
2225 // a copy of the command string managed by the debugger. Up to this
2226 // point, the command data was managed by the API client. Called
2227 // by the API client thread.
2228 void Debug::EnqueueCommandMessage(Vector<const uint16_t> command,
2229 v8::Debug::ClientData* client_data) {
2230 // Need to cast away const.
2231 CommandMessage message = CommandMessage::New(
2232 Vector<uint16_t>(const_cast<uint16_t*>(command.start()),
2233 command.length()),
2234 client_data);
2235 isolate_->logger()->DebugTag("Put command on command_queue.");
2236 command_queue_.Put(message);
2237 command_received_.Signal();
2238
2239 // Set the debug command break flag to have the command processed.
2240 if (!in_debug_scope()) isolate_->stack_guard()->RequestDebugCommand();
2241 }
2242
2044 MaybeHandle<Object> Debug::Call(Handle<Object> fun, Handle<Object> data) { 2243 MaybeHandle<Object> Debug::Call(Handle<Object> fun, Handle<Object> data) {
2045 DebugScope debug_scope(this); 2244 DebugScope debug_scope(this);
2046 if (debug_scope.failed()) return isolate_->factory()->undefined_value(); 2245 if (debug_scope.failed()) return isolate_->factory()->undefined_value();
2047 2246
2048 // Create the execution state. 2247 // Create the execution state.
2049 Handle<Object> exec_state; 2248 Handle<Object> exec_state;
2050 if (!MakeExecutionState().ToHandle(&exec_state)) { 2249 if (!MakeExecutionState().ToHandle(&exec_state)) {
2051 return isolate_->factory()->undefined_value(); 2250 return isolate_->factory()->undefined_value();
2052 } 2251 }
2053 2252
(...skipping 26 matching lines...) Expand all
2080 if (!JSFunction::cast(fun)->shared()->IsSubjectToDebugging()) return; 2279 if (!JSFunction::cast(fun)->shared()->IsSubjectToDebugging()) return;
2081 JSGlobalObject* global = 2280 JSGlobalObject* global =
2082 JSFunction::cast(fun)->context()->global_object(); 2281 JSFunction::cast(fun)->context()->global_object();
2083 // Don't stop in debugger functions. 2282 // Don't stop in debugger functions.
2084 if (IsDebugGlobal(global)) return; 2283 if (IsDebugGlobal(global)) return;
2085 // Don't stop if the break location is muted. 2284 // Don't stop if the break location is muted.
2086 if (IsMutedAtCurrentLocation(it.frame())) return; 2285 if (IsMutedAtCurrentLocation(it.frame())) return;
2087 } 2286 }
2088 } 2287 }
2089 2288
2289 // Collect the break state before clearing the flags.
2290 bool debug_command_only = isolate_->stack_guard()->CheckDebugCommand() &&
2291 !isolate_->stack_guard()->CheckDebugBreak();
2292
2090 isolate_->stack_guard()->ClearDebugBreak(); 2293 isolate_->stack_guard()->ClearDebugBreak();
2091 2294
2092 // Clear stepping to avoid duplicate breaks. 2295 // Clear stepping to avoid duplicate breaks.
2093 ClearStepping(); 2296 ClearStepping();
2094 2297
2298 ProcessDebugMessages(debug_command_only);
2299 }
2300
2301 void Debug::ProcessDebugMessages(bool debug_command_only) {
2302 isolate_->stack_guard()->ClearDebugCommand();
2303
2304 StackLimitCheck check(isolate_);
2305 if (check.HasOverflowed()) return;
2306
2095 HandleScope scope(isolate_); 2307 HandleScope scope(isolate_);
2096 DebugScope debug_scope(this); 2308 DebugScope debug_scope(this);
2097 if (debug_scope.failed()) return; 2309 if (debug_scope.failed()) return;
2098 2310
2099 OnDebugBreak(isolate_->factory()->undefined_value()); 2311 // Notify the debug event listeners. Indicate auto continue if the break was
2312 // a debug command break.
2313 OnDebugBreak(isolate_->factory()->undefined_value(), debug_command_only);
2100 } 2314 }
2101 2315
2102 #ifdef DEBUG 2316 #ifdef DEBUG
2103 void Debug::PrintBreakLocation() { 2317 void Debug::PrintBreakLocation() {
2104 if (!FLAG_print_break_location) return; 2318 if (!FLAG_print_break_location) return;
2105 HandleScope scope(isolate_); 2319 HandleScope scope(isolate_);
2106 JavaScriptFrameIterator iterator(isolate_); 2320 JavaScriptFrameIterator iterator(isolate_);
2107 if (iterator.done()) return; 2321 if (iterator.done()) return;
2108 JavaScriptFrame* frame = iterator.frame(); 2322 JavaScriptFrame* frame = iterator.frame();
2109 FrameSummary summary = FrameSummary::GetTop(frame); 2323 FrameSummary summary = FrameSummary::GetTop(frame);
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
2172 } 2386 }
2173 2387
2174 2388
2175 DebugScope::~DebugScope() { 2389 DebugScope::~DebugScope() {
2176 if (!failed_ && prev_ == NULL) { 2390 if (!failed_ && prev_ == NULL) {
2177 // Clear mirror cache when leaving the debugger. Skip this if there is a 2391 // Clear mirror cache when leaving the debugger. Skip this if there is a
2178 // pending exception as clearing the mirror cache calls back into 2392 // pending exception as clearing the mirror cache calls back into
2179 // JavaScript. This can happen if the v8::Debug::Call is used in which 2393 // JavaScript. This can happen if the v8::Debug::Call is used in which
2180 // case the exception should end up in the calling code. 2394 // case the exception should end up in the calling code.
2181 if (!isolate()->has_pending_exception()) debug_->ClearMirrorCache(); 2395 if (!isolate()->has_pending_exception()) debug_->ClearMirrorCache();
2396
2397 // If there are commands in the queue when leaving the debugger request
2398 // that these commands are processed.
2399 if (debug_->has_commands()) isolate()->stack_guard()->RequestDebugCommand();
2182 } 2400 }
2183 2401
2184 // Leaving this debugger entry. 2402 // Leaving this debugger entry.
2185 base::NoBarrier_Store(&debug_->thread_local_.current_debug_scope_, 2403 base::NoBarrier_Store(&debug_->thread_local_.current_debug_scope_,
2186 reinterpret_cast<base::AtomicWord>(prev_)); 2404 reinterpret_cast<base::AtomicWord>(prev_));
2187 2405
2188 // Restore to the previous break state. 2406 // Restore to the previous break state.
2189 debug_->thread_local_.break_frame_id_ = break_frame_id_; 2407 debug_->thread_local_.break_frame_id_ = break_frame_id_;
2190 debug_->thread_local_.break_id_ = break_id_; 2408 debug_->thread_local_.break_id_ = break_id_;
2191 debug_->thread_local_.return_value_ = return_value_; 2409 debug_->thread_local_.return_value_ = return_value_;
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
2230 // Convert the termination exception into a regular exception. 2448 // Convert the termination exception into a regular exception.
2231 isolate_->CancelTerminateExecution(); 2449 isolate_->CancelTerminateExecution();
2232 isolate_->Throw(*isolate_->factory()->NewEvalError( 2450 isolate_->Throw(*isolate_->factory()->NewEvalError(
2233 MessageTemplate::kNoSideEffectDebugEvaluate)); 2451 MessageTemplate::kNoSideEffectDebugEvaluate));
2234 } 2452 }
2235 isolate_->set_needs_side_effect_check(old_needs_side_effect_check_); 2453 isolate_->set_needs_side_effect_check(old_needs_side_effect_check_);
2236 isolate_->debug()->UpdateHookOnFunctionCall(); 2454 isolate_->debug()->UpdateHookOnFunctionCall();
2237 isolate_->debug()->side_effect_check_failed_ = false; 2455 isolate_->debug()->side_effect_check_failed_ = false;
2238 } 2456 }
2239 2457
2458 MessageImpl MessageImpl::NewEvent(DebugEvent event, bool running,
2459 Handle<JSObject> exec_state,
2460 Handle<JSObject> event_data) {
2461 MessageImpl message(true, event, running, exec_state, event_data,
2462 Handle<String>(), NULL);
2463 return message;
2464 }
2465
2466 MessageImpl MessageImpl::NewResponse(DebugEvent event, bool running,
2467 Handle<JSObject> exec_state,
2468 Handle<JSObject> event_data,
2469 Handle<String> response_json,
2470 v8::Debug::ClientData* client_data) {
2471 MessageImpl message(false, event, running, exec_state, event_data,
2472 response_json, client_data);
2473 return message;
2474 }
2475
2476 MessageImpl::MessageImpl(bool is_event, DebugEvent event, bool running,
2477 Handle<JSObject> exec_state,
2478 Handle<JSObject> event_data,
2479 Handle<String> response_json,
2480 v8::Debug::ClientData* client_data)
2481 : is_event_(is_event),
2482 event_(event),
2483 running_(running),
2484 exec_state_(exec_state),
2485 event_data_(event_data),
2486 response_json_(response_json),
2487 client_data_(client_data) {}
2488
2489 bool MessageImpl::IsEvent() const { return is_event_; }
2490
2491 bool MessageImpl::IsResponse() const { return !is_event_; }
2492
2493 DebugEvent MessageImpl::GetEvent() const { return event_; }
2494
2495 bool MessageImpl::WillStartRunning() const { return running_; }
2496
2497 v8::Local<v8::Object> MessageImpl::GetExecutionState() const {
2498 return v8::Utils::ToLocal(exec_state_);
2499 }
2500
2501 v8::Isolate* MessageImpl::GetIsolate() const {
2502 return reinterpret_cast<v8::Isolate*>(exec_state_->GetIsolate());
2503 }
2504
2505 v8::Local<v8::Object> MessageImpl::GetEventData() const {
2506 return v8::Utils::ToLocal(event_data_);
2507 }
2508
2509 v8::Local<v8::String> MessageImpl::GetJSON() const {
2510 Isolate* isolate = event_data_->GetIsolate();
2511 v8::EscapableHandleScope scope(reinterpret_cast<v8::Isolate*>(isolate));
2512
2513 if (IsEvent()) {
2514 // Call toJSONProtocol on the debug event object.
2515 Handle<Object> fun =
2516 JSReceiver::GetProperty(isolate, event_data_, "toJSONProtocol")
2517 .ToHandleChecked();
2518 if (!fun->IsJSFunction()) {
2519 return v8::Local<v8::String>();
2520 }
2521
2522 MaybeHandle<Object> maybe_exception;
2523 MaybeHandle<Object> maybe_json = Execution::TryCall(
2524 isolate, fun, event_data_, 0, nullptr,
2525 Execution::MessageHandling::kReport, &maybe_exception);
2526 Handle<Object> json;
2527 if (!maybe_json.ToHandle(&json) || !json->IsString()) {
2528 return v8::Local<v8::String>();
2529 }
2530 return scope.Escape(v8::Utils::ToLocal(Handle<String>::cast(json)));
2531 } else {
2532 return v8::Utils::ToLocal(response_json_);
2533 }
2534 }
2535
2536 v8::Local<v8::Context> MessageImpl::GetEventContext() const {
2537 Isolate* isolate = event_data_->GetIsolate();
2538 v8::Local<v8::Context> context = GetDebugEventContext(isolate);
2539 // Isolate::context() may be NULL when "script collected" event occurs.
2540 DCHECK(!context.IsEmpty());
2541 return context;
2542 }
2543
2544 v8::Debug::ClientData* MessageImpl::GetClientData() const {
2545 return client_data_;
2546 }
2547
2240 EventDetailsImpl::EventDetailsImpl(DebugEvent event, 2548 EventDetailsImpl::EventDetailsImpl(DebugEvent event,
2241 Handle<JSObject> exec_state, 2549 Handle<JSObject> exec_state,
2242 Handle<JSObject> event_data, 2550 Handle<JSObject> event_data,
2243 Handle<Object> callback_data) 2551 Handle<Object> callback_data,
2552 v8::Debug::ClientData* client_data)
2244 : event_(event), 2553 : event_(event),
2245 exec_state_(exec_state), 2554 exec_state_(exec_state),
2246 event_data_(event_data), 2555 event_data_(event_data),
2247 callback_data_(callback_data) {} 2556 callback_data_(callback_data),
2557 client_data_(client_data) {}
2558
2248 2559
2249 DebugEvent EventDetailsImpl::GetEvent() const { 2560 DebugEvent EventDetailsImpl::GetEvent() const {
2250 return event_; 2561 return event_;
2251 } 2562 }
2252 2563
2253 2564
2254 v8::Local<v8::Object> EventDetailsImpl::GetExecutionState() const { 2565 v8::Local<v8::Object> EventDetailsImpl::GetExecutionState() const {
2255 return v8::Utils::ToLocal(exec_state_); 2566 return v8::Utils::ToLocal(exec_state_);
2256 } 2567 }
2257 2568
2258 2569
2259 v8::Local<v8::Object> EventDetailsImpl::GetEventData() const { 2570 v8::Local<v8::Object> EventDetailsImpl::GetEventData() const {
2260 return v8::Utils::ToLocal(event_data_); 2571 return v8::Utils::ToLocal(event_data_);
2261 } 2572 }
2262 2573
2263 2574
2264 v8::Local<v8::Context> EventDetailsImpl::GetEventContext() const { 2575 v8::Local<v8::Context> EventDetailsImpl::GetEventContext() const {
2265 return GetDebugEventContext(exec_state_->GetIsolate()); 2576 return GetDebugEventContext(exec_state_->GetIsolate());
2266 } 2577 }
2267 2578
2268 2579
2269 v8::Local<v8::Value> EventDetailsImpl::GetCallbackData() const { 2580 v8::Local<v8::Value> EventDetailsImpl::GetCallbackData() const {
2270 return v8::Utils::ToLocal(callback_data_); 2581 return v8::Utils::ToLocal(callback_data_);
2271 } 2582 }
2272 2583
2273 2584
2585 v8::Debug::ClientData* EventDetailsImpl::GetClientData() const {
2586 return client_data_;
2587 }
2588
2274 v8::Isolate* EventDetailsImpl::GetIsolate() const { 2589 v8::Isolate* EventDetailsImpl::GetIsolate() const {
2275 return reinterpret_cast<v8::Isolate*>(exec_state_->GetIsolate()); 2590 return reinterpret_cast<v8::Isolate*>(exec_state_->GetIsolate());
2276 } 2591 }
2277 2592
2593 CommandMessage::CommandMessage()
2594 : text_(Vector<uint16_t>::empty()), client_data_(NULL) {}
2595
2596 CommandMessage::CommandMessage(const Vector<uint16_t>& text,
2597 v8::Debug::ClientData* data)
2598 : text_(text), client_data_(data) {}
2599
2600 void CommandMessage::Dispose() {
2601 text_.Dispose();
2602 delete client_data_;
2603 client_data_ = NULL;
2604 }
2605
2606 CommandMessage CommandMessage::New(const Vector<uint16_t>& command,
2607 v8::Debug::ClientData* data) {
2608 return CommandMessage(command.Clone(), data);
2609 }
2610
2611 CommandMessageQueue::CommandMessageQueue(int size)
2612 : start_(0), end_(0), size_(size) {
2613 messages_ = NewArray<CommandMessage>(size);
2614 }
2615
2616 CommandMessageQueue::~CommandMessageQueue() {
2617 while (!IsEmpty()) Get().Dispose();
2618 DeleteArray(messages_);
2619 }
2620
2621 CommandMessage CommandMessageQueue::Get() {
2622 DCHECK(!IsEmpty());
2623 int result = start_;
2624 start_ = (start_ + 1) % size_;
2625 return messages_[result];
2626 }
2627
2628 void CommandMessageQueue::Put(const CommandMessage& message) {
2629 if ((end_ + 1) % size_ == start_) {
2630 Expand();
2631 }
2632 messages_[end_] = message;
2633 end_ = (end_ + 1) % size_;
2634 }
2635
2636 void CommandMessageQueue::Expand() {
2637 CommandMessageQueue new_queue(size_ * 2);
2638 while (!IsEmpty()) {
2639 new_queue.Put(Get());
2640 }
2641 CommandMessage* array_to_free = messages_;
2642 *this = new_queue;
2643 new_queue.messages_ = array_to_free;
2644 // Make the new_queue empty so that it doesn't call Dispose on any messages.
2645 new_queue.start_ = new_queue.end_;
2646 // Automatic destructor called on new_queue, freeing array_to_free.
2647 }
2648
2649 LockingCommandMessageQueue::LockingCommandMessageQueue(Logger* logger, int size)
2650 : logger_(logger), queue_(size) {}
2651
2652 bool LockingCommandMessageQueue::IsEmpty() const {
2653 base::LockGuard<base::Mutex> lock_guard(&mutex_);
2654 return queue_.IsEmpty();
2655 }
2656
2657 CommandMessage LockingCommandMessageQueue::Get() {
2658 base::LockGuard<base::Mutex> lock_guard(&mutex_);
2659 CommandMessage result = queue_.Get();
2660 logger_->DebugEvent("Get", result.text());
2661 return result;
2662 }
2663
2664 void LockingCommandMessageQueue::Put(const CommandMessage& message) {
2665 base::LockGuard<base::Mutex> lock_guard(&mutex_);
2666 queue_.Put(message);
2667 logger_->DebugEvent("Put", message.text());
2668 }
2669
2670 void LockingCommandMessageQueue::Clear() {
2671 base::LockGuard<base::Mutex> lock_guard(&mutex_);
2672 queue_.Clear();
2673 }
2674
2278 } // namespace internal 2675 } // namespace internal
2279 } // namespace v8 2676 } // namespace v8
OLDNEW
« no previous file with comments | « src/debug/debug.h ('k') | src/debug/debug.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698