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

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

Issue 2642253005: [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),
46 is_active_(false), 43 is_active_(false),
47 hook_on_function_call_(false), 44 hook_on_function_call_(false),
48 is_suppressed_(false), 45 is_suppressed_(false),
49 live_edit_enabled_(true), // TODO(yangguo): set to false by default. 46 live_edit_enabled_(true), // TODO(yangguo): set to false by default.
50 break_disabled_(false), 47 break_disabled_(false),
51 break_points_active_(true), 48 break_points_active_(true),
52 in_debug_event_listener_(false), 49 in_debug_event_listener_(false),
53 break_on_exception_(false), 50 break_on_exception_(false),
54 break_on_uncaught_exception_(false), 51 break_on_uncaught_exception_(false),
55 side_effect_check_failed_(false), 52 side_effect_check_failed_(false),
(...skipping 469 matching lines...) Expand 10 before | Expand all | Expand 10 after
525 522
526 // Find actual break points, if any, and trigger debug break event. 523 // Find actual break points, if any, and trigger debug break event.
527 MaybeHandle<FixedArray> break_points_hit = 524 MaybeHandle<FixedArray> break_points_hit =
528 CheckBreakPoints(debug_info, &location); 525 CheckBreakPoints(debug_info, &location);
529 if (!break_points_hit.is_null()) { 526 if (!break_points_hit.is_null()) {
530 // Clear all current stepping setup. 527 // Clear all current stepping setup.
531 ClearStepping(); 528 ClearStepping();
532 // Notify the debug event listeners. 529 // Notify the debug event listeners.
533 Handle<JSArray> jsarr = isolate_->factory()->NewJSArrayWithElements( 530 Handle<JSArray> jsarr = isolate_->factory()->NewJSArrayWithElements(
534 break_points_hit.ToHandleChecked()); 531 break_points_hit.ToHandleChecked());
535 OnDebugBreak(jsarr, false); 532 OnDebugBreak(jsarr);
536 return; 533 return;
537 } 534 }
538 535
539 // No break point. Check for stepping. 536 // No break point. Check for stepping.
540 StepAction step_action = last_step_action(); 537 StepAction step_action = last_step_action();
541 Address current_fp = frame->UnpaddedFP(); 538 Address current_fp = frame->UnpaddedFP();
542 Address target_fp = thread_local_.target_fp_; 539 Address target_fp = thread_local_.target_fp_;
543 Address last_fp = thread_local_.last_fp_; 540 Address last_fp = thread_local_.last_fp_;
544 541
545 bool step_break = false; 542 bool step_break = false;
(...skipping 21 matching lines...) Expand all
567 case StepFrame: 564 case StepFrame:
568 step_break = current_fp != last_fp; 565 step_break = current_fp != last_fp;
569 break; 566 break;
570 } 567 }
571 568
572 // Clear all current stepping setup. 569 // Clear all current stepping setup.
573 ClearStepping(); 570 ClearStepping();
574 571
575 if (step_break) { 572 if (step_break) {
576 // Notify the debug event listeners. 573 // Notify the debug event listeners.
577 OnDebugBreak(isolate_->factory()->undefined_value(), false); 574 OnDebugBreak(isolate_->factory()->undefined_value());
578 } else { 575 } else {
579 // Re-prepare to continue. 576 // Re-prepare to continue.
580 PrepareStep(step_action); 577 PrepareStep(step_action);
581 } 578 }
582 } 579 }
583 580
584 581
585 // Find break point objects for this location, if any, and evaluate them. 582 // Find break point objects for this location, if any, and evaluate them.
586 // Return an array of break point objects that evaluated true, or an empty 583 // Return an array of break point objects that evaluated true, or an empty
587 // handle if none evaluated true. 584 // handle if none evaluated true.
(...skipping 1191 matching lines...) Expand 10 before | Expand all | Expand 10 after
1779 1776
1780 // Create the event data object. 1777 // Create the event data object.
1781 Handle<Object> event_data; 1778 Handle<Object> event_data;
1782 // Bail out and don't call debugger if exception. 1779 // Bail out and don't call debugger if exception.
1783 if (!MakeExceptionEvent( 1780 if (!MakeExceptionEvent(
1784 exception, uncaught, promise).ToHandle(&event_data)) { 1781 exception, uncaught, promise).ToHandle(&event_data)) {
1785 return; 1782 return;
1786 } 1783 }
1787 1784
1788 // Process debug event. 1785 // Process debug event.
1789 ProcessDebugEvent(v8::Exception, Handle<JSObject>::cast(event_data), false); 1786 ProcessDebugEvent(v8::Exception, Handle<JSObject>::cast(event_data));
1790 // Return to continue execution from where the exception was thrown. 1787 // Return to continue execution from where the exception was thrown.
1791 } 1788 }
1792 1789
1793 void Debug::OnDebugBreak(Handle<Object> break_points_hit, bool auto_continue) { 1790 void Debug::OnDebugBreak(Handle<Object> break_points_hit) {
1794 // The caller provided for DebugScope. 1791 // The caller provided for DebugScope.
1795 AssertDebugContext(); 1792 AssertDebugContext();
1796 // Bail out if there is no listener for this event 1793 // Bail out if there is no listener for this event
1797 if (ignore_events()) return; 1794 if (ignore_events()) return;
1798 1795
1799 #ifdef DEBUG 1796 #ifdef DEBUG
1800 PrintBreakLocation(); 1797 PrintBreakLocation();
1801 #endif // DEBUG 1798 #endif // DEBUG
1802 1799
1803 if (debug_event_listener_) { 1800 if (debug_event_listener_) {
(...skipping 14 matching lines...) Expand all
1818 if (!non_inspector_listener_exists()) return; 1815 if (!non_inspector_listener_exists()) return;
1819 } 1816 }
1820 1817
1821 HandleScope scope(isolate_); 1818 HandleScope scope(isolate_);
1822 // Create the event data object. 1819 // Create the event data object.
1823 Handle<Object> event_data; 1820 Handle<Object> event_data;
1824 // Bail out and don't call debugger if exception. 1821 // Bail out and don't call debugger if exception.
1825 if (!MakeBreakEvent(break_points_hit).ToHandle(&event_data)) return; 1822 if (!MakeBreakEvent(break_points_hit).ToHandle(&event_data)) return;
1826 1823
1827 // Process debug event. 1824 // Process debug event.
1828 ProcessDebugEvent(v8::Break, Handle<JSObject>::cast(event_data), 1825 ProcessDebugEvent(v8::Break, Handle<JSObject>::cast(event_data));
1829 auto_continue);
1830 } 1826 }
1831 1827
1832 1828
1833 void Debug::OnCompileError(Handle<Script> script) { 1829 void Debug::OnCompileError(Handle<Script> script) {
1834 ProcessCompileEvent(v8::CompileError, script); 1830 ProcessCompileEvent(v8::CompileError, script);
1835 } 1831 }
1836 1832
1837 1833
1838 // Handle debugger actions when a new script is compiled. 1834 // Handle debugger actions when a new script is compiled.
1839 void Debug::OnAfterCompile(Handle<Script> script) { 1835 void Debug::OnAfterCompile(Handle<Script> script) {
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
1909 1905
1910 // Create the script collected state object. 1906 // Create the script collected state object.
1911 Handle<Object> event_data; 1907 Handle<Object> event_data;
1912 // Bail out and don't call debugger if exception. 1908 // Bail out and don't call debugger if exception.
1913 if (!MakeAsyncTaskEvent(handle(Smi::FromInt(type), isolate_), 1909 if (!MakeAsyncTaskEvent(handle(Smi::FromInt(type), isolate_),
1914 handle(Smi::FromInt(id), isolate_)) 1910 handle(Smi::FromInt(id), isolate_))
1915 .ToHandle(&event_data)) 1911 .ToHandle(&event_data))
1916 return; 1912 return;
1917 1913
1918 // Process debug event. 1914 // Process debug event.
1919 ProcessDebugEvent(v8::AsyncTaskEvent, Handle<JSObject>::cast(event_data), 1915 ProcessDebugEvent(v8::AsyncTaskEvent, Handle<JSObject>::cast(event_data));
1920 true);
1921 } 1916 }
1922 1917
1923 void Debug::ProcessDebugEvent(v8::DebugEvent event, Handle<JSObject> event_data, 1918 void Debug::ProcessDebugEvent(v8::DebugEvent event,
1924 bool auto_continue) { 1919 Handle<JSObject> event_data) {
1925 HandleScope scope(isolate_);
1926
1927 // Create the execution state.
1928 Handle<Object> exec_state;
1929 // Bail out and don't call debugger if exception.
1930 if (!MakeExecutionState().ToHandle(&exec_state)) return;
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 1920 // Notify registered debug event listener. This can be either a C or
1938 // a JavaScript function. Don't call event listener for v8::Break 1921 // a JavaScript function. Don't call event listener for v8::Break
jgruber 2017/01/20 09:31:31 The last sentence seems no longer relevant.
1939 // here, if it's only a debug command -- they will be processed later. 1922 // here, if it's only a debug command -- they will be processed later.
1940 if ((event != v8::Break || !auto_continue) && !event_listener_.is_null()) { 1923 if (!event_listener_.is_null()) {
1941 CallEventCallback(event, exec_state, event_data, NULL); 1924 HandleScope scope(isolate_);
1925
1926 // Create the execution state.
1927 Handle<Object> exec_state;
1928 // Bail out and don't call debugger if exception.
1929 if (!MakeExecutionState().ToHandle(&exec_state)) return;
1930 CallEventCallback(event, exec_state, event_data);
1942 } 1931 }
1943 } 1932 }
1944 1933
1945 1934 void Debug::CallEventCallback(v8::DebugEvent event, Handle<Object> exec_state,
1946 void Debug::CallEventCallback(v8::DebugEvent event, 1935 Handle<Object> event_data) {
1947 Handle<Object> exec_state,
1948 Handle<Object> event_data,
1949 v8::Debug::ClientData* client_data) {
1950 // Prevent other interrupts from triggering, for example API callbacks, 1936 // Prevent other interrupts from triggering, for example API callbacks,
1951 // while dispatching event listners. 1937 // while dispatching event listners.
1952 PostponeInterruptsScope postpone(isolate_); 1938 PostponeInterruptsScope postpone(isolate_);
1953 bool previous = in_debug_event_listener_; 1939 bool previous = in_debug_event_listener_;
1954 in_debug_event_listener_ = true; 1940 in_debug_event_listener_ = true;
1955 if (event_listener_->IsForeign()) { 1941 if (event_listener_->IsForeign()) {
1956 // Invoke the C debug event listener. 1942 // Invoke the C debug event listener.
1957 v8::Debug::EventCallback callback = FUNCTION_CAST<v8::Debug::EventCallback>( 1943 v8::Debug::EventCallback callback = FUNCTION_CAST<v8::Debug::EventCallback>(
1958 Handle<Foreign>::cast(event_listener_)->foreign_address()); 1944 Handle<Foreign>::cast(event_listener_)->foreign_address());
1959 EventDetailsImpl event_details(event, 1945 EventDetailsImpl event_details(event, Handle<JSObject>::cast(exec_state),
1960 Handle<JSObject>::cast(exec_state),
1961 Handle<JSObject>::cast(event_data), 1946 Handle<JSObject>::cast(event_data),
1962 event_listener_data_, 1947 event_listener_data_);
1963 client_data);
1964 callback(event_details); 1948 callback(event_details);
1965 CHECK(!isolate_->has_scheduled_exception()); 1949 CHECK(!isolate_->has_scheduled_exception());
1966 } else { 1950 } else {
1967 // Invoke the JavaScript debug event listener. 1951 // Invoke the JavaScript debug event listener.
1968 DCHECK(event_listener_->IsJSFunction()); 1952 DCHECK(event_listener_->IsJSFunction());
1969 Handle<Object> argv[] = { Handle<Object>(Smi::FromInt(event), isolate_), 1953 Handle<Object> argv[] = { Handle<Object>(Smi::FromInt(event), isolate_),
1970 exec_state, 1954 exec_state,
1971 event_data, 1955 event_data,
1972 event_listener_data_ }; 1956 event_listener_data_ };
1973 Handle<JSReceiver> global = isolate_->global_proxy(); 1957 Handle<JSReceiver> global = isolate_->global_proxy();
(...skipping 30 matching lines...) Expand all
2004 1988
2005 // Don't call NotifyMessageHandler if already in debug scope to avoid running 1989 // Don't call NotifyMessageHandler if already in debug scope to avoid running
2006 // nested command loop. 1990 // nested command loop.
2007 if (in_nested_debug_scope) { 1991 if (in_nested_debug_scope) {
2008 if (event_listener_.is_null()) return; 1992 if (event_listener_.is_null()) return;
2009 // Create the execution state. 1993 // Create the execution state.
2010 Handle<Object> exec_state; 1994 Handle<Object> exec_state;
2011 // Bail out and don't call debugger if exception. 1995 // Bail out and don't call debugger if exception.
2012 if (!MakeExecutionState().ToHandle(&exec_state)) return; 1996 if (!MakeExecutionState().ToHandle(&exec_state)) return;
2013 1997
2014 CallEventCallback(event, exec_state, event_data, NULL); 1998 CallEventCallback(event, exec_state, event_data);
2015 } else { 1999 } else {
2016 // Process debug event. 2000 // Process debug event.
2017 ProcessDebugEvent(event, Handle<JSObject>::cast(event_data), true); 2001 ProcessDebugEvent(event, Handle<JSObject>::cast(event_data));
2018 } 2002 }
2019 } 2003 }
2020 2004
2021 2005
2022 Handle<Context> Debug::GetDebugContext() { 2006 Handle<Context> Debug::GetDebugContext() {
2023 if (!is_loaded()) return Handle<Context>(); 2007 if (!is_loaded()) return Handle<Context>();
2024 DebugScope debug_scope(this); 2008 DebugScope debug_scope(this);
2025 if (debug_scope.failed()) return Handle<Context>(); 2009 if (debug_scope.failed()) return Handle<Context>();
2026 // The global handle may be destroyed soon after. Return it reboxed. 2010 // The global handle may be destroyed soon after. Return it reboxed.
2027 return handle(*debug_context(), isolate_); 2011 return handle(*debug_context(), isolate_);
2028 } 2012 }
2029 2013
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 }
2160 2014
2161 void Debug::SetEventListener(Handle<Object> callback, 2015 void Debug::SetEventListener(Handle<Object> callback,
2162 Handle<Object> data) { 2016 Handle<Object> data) {
2163 GlobalHandles* global_handles = isolate_->global_handles(); 2017 GlobalHandles* global_handles = isolate_->global_handles();
2164 2018
2165 // Remove existing entry. 2019 // Remove existing entry.
2166 GlobalHandles::Destroy(event_listener_.location()); 2020 GlobalHandles::Destroy(event_listener_.location());
2167 event_listener_ = Handle<Object>(); 2021 event_listener_ = Handle<Object>();
2168 GlobalHandles::Destroy(event_listener_data_.location()); 2022 GlobalHandles::Destroy(event_listener_data_.location());
2169 event_listener_data_ = Handle<Object>(); 2023 event_listener_data_ = Handle<Object>();
2170 2024
2171 // Set new entry. 2025 // Set new entry.
2172 if (!callback->IsNullOrUndefined(isolate_)) { 2026 if (!callback->IsNullOrUndefined(isolate_)) {
2173 event_listener_ = global_handles->Create(*callback); 2027 event_listener_ = global_handles->Create(*callback);
2174 if (data.is_null()) data = isolate_->factory()->undefined_value(); 2028 if (data.is_null()) data = isolate_->factory()->undefined_value();
2175 event_listener_data_ = global_handles->Create(*data); 2029 event_listener_data_ = global_handles->Create(*data);
2176 } 2030 }
2177 2031
2178 UpdateState(); 2032 UpdateState();
2179 } 2033 }
2180 2034
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 }
2190 2035
2191 void Debug::SetDebugEventListener(debug::DebugEventListener* listener) { 2036 void Debug::SetDebugEventListener(debug::DebugEventListener* listener) {
2192 debug_event_listener_ = listener; 2037 debug_event_listener_ = listener;
2193 UpdateState(); 2038 UpdateState();
2194 } 2039 }
2195 2040
2196 void Debug::UpdateState() { 2041 void Debug::UpdateState() {
2197 bool is_active = message_handler_ != nullptr || !event_listener_.is_null() || 2042 bool is_active =
2198 debug_event_listener_ != nullptr; 2043 !event_listener_.is_null() || debug_event_listener_ != nullptr;
2199 if (is_active || in_debug_scope()) { 2044 if (is_active || in_debug_scope()) {
2200 // Note that the debug context could have already been loaded to 2045 // Note that the debug context could have already been loaded to
2201 // bootstrap test cases. 2046 // bootstrap test cases.
2202 isolate_->compilation_cache()->Disable(); 2047 isolate_->compilation_cache()->Disable();
2203 is_active = Load(); 2048 is_active = Load();
2204 } else if (is_loaded()) { 2049 } else if (is_loaded()) {
2205 isolate_->compilation_cache()->Enable(); 2050 isolate_->compilation_cache()->Enable();
2206 Unload(); 2051 Unload();
2207 } 2052 }
2208 is_active_ = is_active; 2053 is_active_ = is_active;
2209 } 2054 }
2210 2055
2211 void Debug::UpdateHookOnFunctionCall() { 2056 void Debug::UpdateHookOnFunctionCall() {
2212 STATIC_ASSERT(StepFrame > StepIn); 2057 STATIC_ASSERT(StepFrame > StepIn);
2213 STATIC_ASSERT(LastStepAction == StepFrame); 2058 STATIC_ASSERT(LastStepAction == StepFrame);
2214 hook_on_function_call_ = thread_local_.last_step_action_ >= StepIn || 2059 hook_on_function_call_ = thread_local_.last_step_action_ >= StepIn ||
2215 isolate_->needs_side_effect_check(); 2060 isolate_->needs_side_effect_check();
2216 } 2061 }
2217 2062
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
2243 MaybeHandle<Object> Debug::Call(Handle<Object> fun, Handle<Object> data) { 2063 MaybeHandle<Object> Debug::Call(Handle<Object> fun, Handle<Object> data) {
2244 DebugScope debug_scope(this); 2064 DebugScope debug_scope(this);
2245 if (debug_scope.failed()) return isolate_->factory()->undefined_value(); 2065 if (debug_scope.failed()) return isolate_->factory()->undefined_value();
2246 2066
2247 // Create the execution state. 2067 // Create the execution state.
2248 Handle<Object> exec_state; 2068 Handle<Object> exec_state;
2249 if (!MakeExecutionState().ToHandle(&exec_state)) { 2069 if (!MakeExecutionState().ToHandle(&exec_state)) {
2250 return isolate_->factory()->undefined_value(); 2070 return isolate_->factory()->undefined_value();
2251 } 2071 }
2252 2072
(...skipping 26 matching lines...) Expand all
2279 if (!JSFunction::cast(fun)->shared()->IsSubjectToDebugging()) return; 2099 if (!JSFunction::cast(fun)->shared()->IsSubjectToDebugging()) return;
2280 JSGlobalObject* global = 2100 JSGlobalObject* global =
2281 JSFunction::cast(fun)->context()->global_object(); 2101 JSFunction::cast(fun)->context()->global_object();
2282 // Don't stop in debugger functions. 2102 // Don't stop in debugger functions.
2283 if (IsDebugGlobal(global)) return; 2103 if (IsDebugGlobal(global)) return;
2284 // Don't stop if the break location is muted. 2104 // Don't stop if the break location is muted.
2285 if (IsMutedAtCurrentLocation(it.frame())) return; 2105 if (IsMutedAtCurrentLocation(it.frame())) return;
2286 } 2106 }
2287 } 2107 }
2288 2108
2289 // Collect the break state before clearing the flags.
2290 bool debug_command_only = isolate_->stack_guard()->CheckDebugCommand() &&
2291 !isolate_->stack_guard()->CheckDebugBreak();
2292
2293 isolate_->stack_guard()->ClearDebugBreak(); 2109 isolate_->stack_guard()->ClearDebugBreak();
2294 2110
2295 // Clear stepping to avoid duplicate breaks. 2111 // Clear stepping to avoid duplicate breaks.
2296 ClearStepping(); 2112 ClearStepping();
2297 2113
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
2307 HandleScope scope(isolate_); 2114 HandleScope scope(isolate_);
2308 DebugScope debug_scope(this); 2115 DebugScope debug_scope(this);
2309 if (debug_scope.failed()) return; 2116 if (debug_scope.failed()) return;
2310 2117
2311 // Notify the debug event listeners. Indicate auto continue if the break was 2118 OnDebugBreak(isolate_->factory()->undefined_value());
2312 // a debug command break.
2313 OnDebugBreak(isolate_->factory()->undefined_value(), debug_command_only);
2314 } 2119 }
2315 2120
2316 #ifdef DEBUG 2121 #ifdef DEBUG
2317 void Debug::PrintBreakLocation() { 2122 void Debug::PrintBreakLocation() {
2318 if (!FLAG_print_break_location) return; 2123 if (!FLAG_print_break_location) return;
2319 HandleScope scope(isolate_); 2124 HandleScope scope(isolate_);
2320 JavaScriptFrameIterator iterator(isolate_); 2125 JavaScriptFrameIterator iterator(isolate_);
2321 if (iterator.done()) return; 2126 if (iterator.done()) return;
2322 JavaScriptFrame* frame = iterator.frame(); 2127 JavaScriptFrame* frame = iterator.frame();
2323 FrameSummary summary = FrameSummary::GetTop(frame); 2128 FrameSummary summary = FrameSummary::GetTop(frame);
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
2386 } 2191 }
2387 2192
2388 2193
2389 DebugScope::~DebugScope() { 2194 DebugScope::~DebugScope() {
2390 if (!failed_ && prev_ == NULL) { 2195 if (!failed_ && prev_ == NULL) {
2391 // Clear mirror cache when leaving the debugger. Skip this if there is a 2196 // Clear mirror cache when leaving the debugger. Skip this if there is a
2392 // pending exception as clearing the mirror cache calls back into 2197 // pending exception as clearing the mirror cache calls back into
2393 // JavaScript. This can happen if the v8::Debug::Call is used in which 2198 // JavaScript. This can happen if the v8::Debug::Call is used in which
2394 // case the exception should end up in the calling code. 2199 // case the exception should end up in the calling code.
2395 if (!isolate()->has_pending_exception()) debug_->ClearMirrorCache(); 2200 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();
2400 } 2201 }
2401 2202
2402 // Leaving this debugger entry. 2203 // Leaving this debugger entry.
2403 base::NoBarrier_Store(&debug_->thread_local_.current_debug_scope_, 2204 base::NoBarrier_Store(&debug_->thread_local_.current_debug_scope_,
2404 reinterpret_cast<base::AtomicWord>(prev_)); 2205 reinterpret_cast<base::AtomicWord>(prev_));
2405 2206
2406 // Restore to the previous break state. 2207 // Restore to the previous break state.
2407 debug_->thread_local_.break_frame_id_ = break_frame_id_; 2208 debug_->thread_local_.break_frame_id_ = break_frame_id_;
2408 debug_->thread_local_.break_id_ = break_id_; 2209 debug_->thread_local_.break_id_ = break_id_;
2409 debug_->thread_local_.return_value_ = return_value_; 2210 debug_->thread_local_.return_value_ = return_value_;
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
2448 // Convert the termination exception into a regular exception. 2249 // Convert the termination exception into a regular exception.
2449 isolate_->CancelTerminateExecution(); 2250 isolate_->CancelTerminateExecution();
2450 isolate_->Throw(*isolate_->factory()->NewEvalError( 2251 isolate_->Throw(*isolate_->factory()->NewEvalError(
2451 MessageTemplate::kNoSideEffectDebugEvaluate)); 2252 MessageTemplate::kNoSideEffectDebugEvaluate));
2452 } 2253 }
2453 isolate_->set_needs_side_effect_check(old_needs_side_effect_check_); 2254 isolate_->set_needs_side_effect_check(old_needs_side_effect_check_);
2454 isolate_->debug()->UpdateHookOnFunctionCall(); 2255 isolate_->debug()->UpdateHookOnFunctionCall();
2455 isolate_->debug()->side_effect_check_failed_ = false; 2256 isolate_->debug()->side_effect_check_failed_ = false;
2456 } 2257 }
2457 2258
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
2548 EventDetailsImpl::EventDetailsImpl(DebugEvent event, 2259 EventDetailsImpl::EventDetailsImpl(DebugEvent event,
2549 Handle<JSObject> exec_state, 2260 Handle<JSObject> exec_state,
2550 Handle<JSObject> event_data, 2261 Handle<JSObject> event_data,
2551 Handle<Object> callback_data, 2262 Handle<Object> callback_data)
2552 v8::Debug::ClientData* client_data)
2553 : event_(event), 2263 : event_(event),
2554 exec_state_(exec_state), 2264 exec_state_(exec_state),
2555 event_data_(event_data), 2265 event_data_(event_data),
2556 callback_data_(callback_data), 2266 callback_data_(callback_data) {}
2557 client_data_(client_data) {}
2558
2559 2267
2560 DebugEvent EventDetailsImpl::GetEvent() const { 2268 DebugEvent EventDetailsImpl::GetEvent() const {
2561 return event_; 2269 return event_;
2562 } 2270 }
2563 2271
2564 2272
2565 v8::Local<v8::Object> EventDetailsImpl::GetExecutionState() const { 2273 v8::Local<v8::Object> EventDetailsImpl::GetExecutionState() const {
2566 return v8::Utils::ToLocal(exec_state_); 2274 return v8::Utils::ToLocal(exec_state_);
2567 } 2275 }
2568 2276
2569 2277
2570 v8::Local<v8::Object> EventDetailsImpl::GetEventData() const { 2278 v8::Local<v8::Object> EventDetailsImpl::GetEventData() const {
2571 return v8::Utils::ToLocal(event_data_); 2279 return v8::Utils::ToLocal(event_data_);
2572 } 2280 }
2573 2281
2574 2282
2575 v8::Local<v8::Context> EventDetailsImpl::GetEventContext() const { 2283 v8::Local<v8::Context> EventDetailsImpl::GetEventContext() const {
2576 return GetDebugEventContext(exec_state_->GetIsolate()); 2284 return GetDebugEventContext(exec_state_->GetIsolate());
2577 } 2285 }
2578 2286
2579 2287
2580 v8::Local<v8::Value> EventDetailsImpl::GetCallbackData() const { 2288 v8::Local<v8::Value> EventDetailsImpl::GetCallbackData() const {
2581 return v8::Utils::ToLocal(callback_data_); 2289 return v8::Utils::ToLocal(callback_data_);
2582 } 2290 }
2583 2291
2584 2292
2585 v8::Debug::ClientData* EventDetailsImpl::GetClientData() const {
2586 return client_data_;
2587 }
2588
2589 v8::Isolate* EventDetailsImpl::GetIsolate() const { 2293 v8::Isolate* EventDetailsImpl::GetIsolate() const {
2590 return reinterpret_cast<v8::Isolate*>(exec_state_->GetIsolate()); 2294 return reinterpret_cast<v8::Isolate*>(exec_state_->GetIsolate());
2591 } 2295 }
2592 2296
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
2675 } // namespace internal 2297 } // namespace internal
2676 } // namespace v8 2298 } // 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