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

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

Issue 2642253005: [debugger api] remove legacy JSON debug protocol. (Closed)
Patch Set: fix cctest 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) {
1920 // Notify registered debug event listener. This can be either a C or
1921 // a JavaScript function.
1922 if (event_listener_.is_null()) return;
1925 HandleScope scope(isolate_); 1923 HandleScope scope(isolate_);
1926 1924
1927 // Create the execution state. 1925 // Create the execution state.
1928 Handle<Object> exec_state; 1926 Handle<Object> exec_state;
1929 // Bail out and don't call debugger if exception. 1927 // Bail out and don't call debugger if exception.
1930 if (!MakeExecutionState().ToHandle(&exec_state)) return; 1928 if (!MakeExecutionState().ToHandle(&exec_state)) return;
1931 1929
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) {
1950 // Prevent other interrupts from triggering, for example API callbacks, 1930 // Prevent other interrupts from triggering, for example API callbacks,
1951 // while dispatching event listners. 1931 // while dispatching event listners.
1952 PostponeInterruptsScope postpone(isolate_); 1932 PostponeInterruptsScope postpone(isolate_);
1953 bool previous = in_debug_event_listener_; 1933 bool previous = in_debug_event_listener_;
1954 in_debug_event_listener_ = true; 1934 in_debug_event_listener_ = true;
1955 if (event_listener_->IsForeign()) { 1935 if (event_listener_->IsForeign()) {
1956 // Invoke the C debug event listener. 1936 // Invoke the C debug event listener.
1957 v8::Debug::EventCallback callback = FUNCTION_CAST<v8::Debug::EventCallback>( 1937 v8::Debug::EventCallback callback = FUNCTION_CAST<v8::Debug::EventCallback>(
1958 Handle<Foreign>::cast(event_listener_)->foreign_address()); 1938 Handle<Foreign>::cast(event_listener_)->foreign_address());
1959 EventDetailsImpl event_details(event, 1939 EventDetailsImpl event_details(event, Handle<JSObject>::cast(exec_state),
1960 Handle<JSObject>::cast(exec_state),
1961 Handle<JSObject>::cast(event_data), 1940 Handle<JSObject>::cast(event_data),
1962 event_listener_data_, 1941 event_listener_data_);
1963 client_data);
1964 callback(event_details); 1942 callback(event_details);
1965 CHECK(!isolate_->has_scheduled_exception()); 1943 CHECK(!isolate_->has_scheduled_exception());
1966 } else { 1944 } else {
1967 // Invoke the JavaScript debug event listener. 1945 // Invoke the JavaScript debug event listener.
1968 DCHECK(event_listener_->IsJSFunction()); 1946 DCHECK(event_listener_->IsJSFunction());
1969 Handle<Object> argv[] = { Handle<Object>(Smi::FromInt(event), isolate_), 1947 Handle<Object> argv[] = { Handle<Object>(Smi::FromInt(event), isolate_),
1970 exec_state, 1948 exec_state,
1971 event_data, 1949 event_data,
1972 event_listener_data_ }; 1950 event_listener_data_ };
1973 Handle<JSReceiver> global = isolate_->global_proxy(); 1951 Handle<JSReceiver> global = isolate_->global_proxy();
1974 MaybeHandle<Object> result = 1952 MaybeHandle<Object> result =
1975 Execution::Call(isolate_, Handle<JSFunction>::cast(event_listener_), 1953 Execution::Call(isolate_, Handle<JSFunction>::cast(event_listener_),
1976 global, arraysize(argv), argv); 1954 global, arraysize(argv), argv);
1977 CHECK(!result.is_null()); // Listeners must not throw. 1955 CHECK(!result.is_null()); // Listeners must not throw.
1978 } 1956 }
1979 in_debug_event_listener_ = previous; 1957 in_debug_event_listener_ = previous;
1980 } 1958 }
1981 1959
1982 void Debug::ProcessCompileEvent(v8::DebugEvent event, Handle<Script> script) { 1960 void Debug::ProcessCompileEvent(v8::DebugEvent event, Handle<Script> script) {
1983 if (ignore_events()) return; 1961 if (ignore_events()) return;
1984 if (script->type() != i::Script::TYPE_NORMAL && 1962 if (script->type() != i::Script::TYPE_NORMAL &&
1985 script->type() != i::Script::TYPE_WASM) { 1963 script->type() != i::Script::TYPE_WASM) {
1986 return; 1964 return;
1987 } 1965 }
1988 SuppressDebug while_processing(this); 1966 SuppressDebug while_processing(this);
1989 bool in_nested_debug_scope = in_debug_scope();
1990 DebugScope debug_scope(this); 1967 DebugScope debug_scope(this);
1991 if (debug_scope.failed()) return; 1968 if (debug_scope.failed()) return;
1992 1969
1993 if (debug_event_listener_) { 1970 if (debug_event_listener_) {
1994 debug_event_listener_->ScriptCompiled(ToApiHandle<debug::Script>(script), 1971 debug_event_listener_->ScriptCompiled(ToApiHandle<debug::Script>(script),
1995 event != v8::AfterCompile); 1972 event != v8::AfterCompile);
1996 if (!non_inspector_listener_exists()) return; 1973 if (!non_inspector_listener_exists()) return;
1997 } 1974 }
1998 1975
1999 HandleScope scope(isolate_); 1976 HandleScope scope(isolate_);
2000 // Create the compile state object. 1977 // Create the compile state object.
2001 Handle<Object> event_data; 1978 Handle<Object> event_data;
2002 // Bail out and don't call debugger if exception. 1979 // Bail out and don't call debugger if exception.
2003 if (!MakeCompileEvent(script, event).ToHandle(&event_data)) return; 1980 if (!MakeCompileEvent(script, event).ToHandle(&event_data)) return;
2004 1981
2005 // Don't call NotifyMessageHandler if already in debug scope to avoid running 1982 // Process debug event.
2006 // nested command loop. 1983 ProcessDebugEvent(event, Handle<JSObject>::cast(event_data));
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 }
2019 } 1984 }
2020 1985
2021 1986
2022 Handle<Context> Debug::GetDebugContext() { 1987 Handle<Context> Debug::GetDebugContext() {
2023 if (!is_loaded()) return Handle<Context>(); 1988 if (!is_loaded()) return Handle<Context>();
2024 DebugScope debug_scope(this); 1989 DebugScope debug_scope(this);
2025 if (debug_scope.failed()) return Handle<Context>(); 1990 if (debug_scope.failed()) return Handle<Context>();
2026 // The global handle may be destroyed soon after. Return it reboxed. 1991 // The global handle may be destroyed soon after. Return it reboxed.
2027 return handle(*debug_context(), isolate_); 1992 return handle(*debug_context(), isolate_);
2028 } 1993 }
2029 1994
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 1995
2161 void Debug::SetEventListener(Handle<Object> callback, 1996 void Debug::SetEventListener(Handle<Object> callback,
2162 Handle<Object> data) { 1997 Handle<Object> data) {
2163 GlobalHandles* global_handles = isolate_->global_handles(); 1998 GlobalHandles* global_handles = isolate_->global_handles();
2164 1999
2165 // Remove existing entry. 2000 // Remove existing entry.
2166 GlobalHandles::Destroy(event_listener_.location()); 2001 GlobalHandles::Destroy(event_listener_.location());
2167 event_listener_ = Handle<Object>(); 2002 event_listener_ = Handle<Object>();
2168 GlobalHandles::Destroy(event_listener_data_.location()); 2003 GlobalHandles::Destroy(event_listener_data_.location());
2169 event_listener_data_ = Handle<Object>(); 2004 event_listener_data_ = Handle<Object>();
2170 2005
2171 // Set new entry. 2006 // Set new entry.
2172 if (!callback->IsNullOrUndefined(isolate_)) { 2007 if (!callback->IsNullOrUndefined(isolate_)) {
2173 event_listener_ = global_handles->Create(*callback); 2008 event_listener_ = global_handles->Create(*callback);
2174 if (data.is_null()) data = isolate_->factory()->undefined_value(); 2009 if (data.is_null()) data = isolate_->factory()->undefined_value();
2175 event_listener_data_ = global_handles->Create(*data); 2010 event_listener_data_ = global_handles->Create(*data);
2176 } 2011 }
2177 2012
2178 UpdateState(); 2013 UpdateState();
2179 } 2014 }
2180 2015
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 2016
2191 void Debug::SetDebugEventListener(debug::DebugEventListener* listener) { 2017 void Debug::SetDebugEventListener(debug::DebugEventListener* listener) {
2192 debug_event_listener_ = listener; 2018 debug_event_listener_ = listener;
2193 UpdateState(); 2019 UpdateState();
2194 } 2020 }
2195 2021
2196 void Debug::UpdateState() { 2022 void Debug::UpdateState() {
2197 bool is_active = message_handler_ != nullptr || !event_listener_.is_null() || 2023 bool is_active =
2198 debug_event_listener_ != nullptr; 2024 !event_listener_.is_null() || debug_event_listener_ != nullptr;
2199 if (is_active || in_debug_scope()) { 2025 if (is_active || in_debug_scope()) {
2200 // Note that the debug context could have already been loaded to 2026 // Note that the debug context could have already been loaded to
2201 // bootstrap test cases. 2027 // bootstrap test cases.
2202 isolate_->compilation_cache()->Disable(); 2028 isolate_->compilation_cache()->Disable();
2203 is_active = Load(); 2029 is_active = Load();
2204 } else if (is_loaded()) { 2030 } else if (is_loaded()) {
2205 isolate_->compilation_cache()->Enable(); 2031 isolate_->compilation_cache()->Enable();
2206 Unload(); 2032 Unload();
2207 } 2033 }
2208 is_active_ = is_active; 2034 is_active_ = is_active;
2209 } 2035 }
2210 2036
2211 void Debug::UpdateHookOnFunctionCall() { 2037 void Debug::UpdateHookOnFunctionCall() {
2212 STATIC_ASSERT(StepFrame > StepIn); 2038 STATIC_ASSERT(StepFrame > StepIn);
2213 STATIC_ASSERT(LastStepAction == StepFrame); 2039 STATIC_ASSERT(LastStepAction == StepFrame);
2214 hook_on_function_call_ = thread_local_.last_step_action_ >= StepIn || 2040 hook_on_function_call_ = thread_local_.last_step_action_ >= StepIn ||
2215 isolate_->needs_side_effect_check(); 2041 isolate_->needs_side_effect_check();
2216 } 2042 }
2217 2043
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) { 2044 MaybeHandle<Object> Debug::Call(Handle<Object> fun, Handle<Object> data) {
2244 DebugScope debug_scope(this); 2045 DebugScope debug_scope(this);
2245 if (debug_scope.failed()) return isolate_->factory()->undefined_value(); 2046 if (debug_scope.failed()) return isolate_->factory()->undefined_value();
2246 2047
2247 // Create the execution state. 2048 // Create the execution state.
2248 Handle<Object> exec_state; 2049 Handle<Object> exec_state;
2249 if (!MakeExecutionState().ToHandle(&exec_state)) { 2050 if (!MakeExecutionState().ToHandle(&exec_state)) {
2250 return isolate_->factory()->undefined_value(); 2051 return isolate_->factory()->undefined_value();
2251 } 2052 }
2252 2053
(...skipping 26 matching lines...) Expand all
2279 if (!JSFunction::cast(fun)->shared()->IsSubjectToDebugging()) return; 2080 if (!JSFunction::cast(fun)->shared()->IsSubjectToDebugging()) return;
2280 JSGlobalObject* global = 2081 JSGlobalObject* global =
2281 JSFunction::cast(fun)->context()->global_object(); 2082 JSFunction::cast(fun)->context()->global_object();
2282 // Don't stop in debugger functions. 2083 // Don't stop in debugger functions.
2283 if (IsDebugGlobal(global)) return; 2084 if (IsDebugGlobal(global)) return;
2284 // Don't stop if the break location is muted. 2085 // Don't stop if the break location is muted.
2285 if (IsMutedAtCurrentLocation(it.frame())) return; 2086 if (IsMutedAtCurrentLocation(it.frame())) return;
2286 } 2087 }
2287 } 2088 }
2288 2089
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(); 2090 isolate_->stack_guard()->ClearDebugBreak();
2294 2091
2295 // Clear stepping to avoid duplicate breaks. 2092 // Clear stepping to avoid duplicate breaks.
2296 ClearStepping(); 2093 ClearStepping();
2297 2094
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_); 2095 HandleScope scope(isolate_);
2308 DebugScope debug_scope(this); 2096 DebugScope debug_scope(this);
2309 if (debug_scope.failed()) return; 2097 if (debug_scope.failed()) return;
2310 2098
2311 // Notify the debug event listeners. Indicate auto continue if the break was 2099 OnDebugBreak(isolate_->factory()->undefined_value());
2312 // a debug command break.
2313 OnDebugBreak(isolate_->factory()->undefined_value(), debug_command_only);
2314 } 2100 }
2315 2101
2316 #ifdef DEBUG 2102 #ifdef DEBUG
2317 void Debug::PrintBreakLocation() { 2103 void Debug::PrintBreakLocation() {
2318 if (!FLAG_print_break_location) return; 2104 if (!FLAG_print_break_location) return;
2319 HandleScope scope(isolate_); 2105 HandleScope scope(isolate_);
2320 StackTraceFrameIterator iterator(isolate_); 2106 StackTraceFrameIterator iterator(isolate_);
2321 if (iterator.done()) return; 2107 if (iterator.done()) return;
2322 StandardFrame* frame = iterator.frame(); 2108 StandardFrame* frame = iterator.frame();
2323 FrameSummary summary = FrameSummary::GetTop(frame); 2109 FrameSummary summary = FrameSummary::GetTop(frame);
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
2384 } 2170 }
2385 2171
2386 2172
2387 DebugScope::~DebugScope() { 2173 DebugScope::~DebugScope() {
2388 if (!failed_ && prev_ == NULL) { 2174 if (!failed_ && prev_ == NULL) {
2389 // Clear mirror cache when leaving the debugger. Skip this if there is a 2175 // Clear mirror cache when leaving the debugger. Skip this if there is a
2390 // pending exception as clearing the mirror cache calls back into 2176 // pending exception as clearing the mirror cache calls back into
2391 // JavaScript. This can happen if the v8::Debug::Call is used in which 2177 // JavaScript. This can happen if the v8::Debug::Call is used in which
2392 // case the exception should end up in the calling code. 2178 // case the exception should end up in the calling code.
2393 if (!isolate()->has_pending_exception()) debug_->ClearMirrorCache(); 2179 if (!isolate()->has_pending_exception()) debug_->ClearMirrorCache();
2394
2395 // If there are commands in the queue when leaving the debugger request
2396 // that these commands are processed.
2397 if (debug_->has_commands()) isolate()->stack_guard()->RequestDebugCommand();
2398 } 2180 }
2399 2181
2400 // Leaving this debugger entry. 2182 // Leaving this debugger entry.
2401 base::NoBarrier_Store(&debug_->thread_local_.current_debug_scope_, 2183 base::NoBarrier_Store(&debug_->thread_local_.current_debug_scope_,
2402 reinterpret_cast<base::AtomicWord>(prev_)); 2184 reinterpret_cast<base::AtomicWord>(prev_));
2403 2185
2404 // Restore to the previous break state. 2186 // Restore to the previous break state.
2405 debug_->thread_local_.break_frame_id_ = break_frame_id_; 2187 debug_->thread_local_.break_frame_id_ = break_frame_id_;
2406 debug_->thread_local_.break_id_ = break_id_; 2188 debug_->thread_local_.break_id_ = break_id_;
2407 debug_->thread_local_.return_value_ = return_value_; 2189 debug_->thread_local_.return_value_ = return_value_;
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
2446 // Convert the termination exception into a regular exception. 2228 // Convert the termination exception into a regular exception.
2447 isolate_->CancelTerminateExecution(); 2229 isolate_->CancelTerminateExecution();
2448 isolate_->Throw(*isolate_->factory()->NewEvalError( 2230 isolate_->Throw(*isolate_->factory()->NewEvalError(
2449 MessageTemplate::kNoSideEffectDebugEvaluate)); 2231 MessageTemplate::kNoSideEffectDebugEvaluate));
2450 } 2232 }
2451 isolate_->set_needs_side_effect_check(old_needs_side_effect_check_); 2233 isolate_->set_needs_side_effect_check(old_needs_side_effect_check_);
2452 isolate_->debug()->UpdateHookOnFunctionCall(); 2234 isolate_->debug()->UpdateHookOnFunctionCall();
2453 isolate_->debug()->side_effect_check_failed_ = false; 2235 isolate_->debug()->side_effect_check_failed_ = false;
2454 } 2236 }
2455 2237
2456 MessageImpl MessageImpl::NewEvent(DebugEvent event, bool running,
2457 Handle<JSObject> exec_state,
2458 Handle<JSObject> event_data) {
2459 MessageImpl message(true, event, running, exec_state, event_data,
2460 Handle<String>(), NULL);
2461 return message;
2462 }
2463
2464 MessageImpl MessageImpl::NewResponse(DebugEvent event, bool running,
2465 Handle<JSObject> exec_state,
2466 Handle<JSObject> event_data,
2467 Handle<String> response_json,
2468 v8::Debug::ClientData* client_data) {
2469 MessageImpl message(false, event, running, exec_state, event_data,
2470 response_json, client_data);
2471 return message;
2472 }
2473
2474 MessageImpl::MessageImpl(bool is_event, DebugEvent event, bool running,
2475 Handle<JSObject> exec_state,
2476 Handle<JSObject> event_data,
2477 Handle<String> response_json,
2478 v8::Debug::ClientData* client_data)
2479 : is_event_(is_event),
2480 event_(event),
2481 running_(running),
2482 exec_state_(exec_state),
2483 event_data_(event_data),
2484 response_json_(response_json),
2485 client_data_(client_data) {}
2486
2487 bool MessageImpl::IsEvent() const { return is_event_; }
2488
2489 bool MessageImpl::IsResponse() const { return !is_event_; }
2490
2491 DebugEvent MessageImpl::GetEvent() const { return event_; }
2492
2493 bool MessageImpl::WillStartRunning() const { return running_; }
2494
2495 v8::Local<v8::Object> MessageImpl::GetExecutionState() const {
2496 return v8::Utils::ToLocal(exec_state_);
2497 }
2498
2499 v8::Isolate* MessageImpl::GetIsolate() const {
2500 return reinterpret_cast<v8::Isolate*>(exec_state_->GetIsolate());
2501 }
2502
2503 v8::Local<v8::Object> MessageImpl::GetEventData() const {
2504 return v8::Utils::ToLocal(event_data_);
2505 }
2506
2507 v8::Local<v8::String> MessageImpl::GetJSON() const {
2508 Isolate* isolate = event_data_->GetIsolate();
2509 v8::EscapableHandleScope scope(reinterpret_cast<v8::Isolate*>(isolate));
2510
2511 if (IsEvent()) {
2512 // Call toJSONProtocol on the debug event object.
2513 Handle<Object> fun =
2514 JSReceiver::GetProperty(isolate, event_data_, "toJSONProtocol")
2515 .ToHandleChecked();
2516 if (!fun->IsJSFunction()) {
2517 return v8::Local<v8::String>();
2518 }
2519
2520 MaybeHandle<Object> maybe_exception;
2521 MaybeHandle<Object> maybe_json = Execution::TryCall(
2522 isolate, fun, event_data_, 0, nullptr,
2523 Execution::MessageHandling::kReport, &maybe_exception);
2524 Handle<Object> json;
2525 if (!maybe_json.ToHandle(&json) || !json->IsString()) {
2526 return v8::Local<v8::String>();
2527 }
2528 return scope.Escape(v8::Utils::ToLocal(Handle<String>::cast(json)));
2529 } else {
2530 return v8::Utils::ToLocal(response_json_);
2531 }
2532 }
2533
2534 v8::Local<v8::Context> MessageImpl::GetEventContext() const {
2535 Isolate* isolate = event_data_->GetIsolate();
2536 v8::Local<v8::Context> context = GetDebugEventContext(isolate);
2537 // Isolate::context() may be NULL when "script collected" event occurs.
2538 DCHECK(!context.IsEmpty());
2539 return context;
2540 }
2541
2542 v8::Debug::ClientData* MessageImpl::GetClientData() const {
2543 return client_data_;
2544 }
2545
2546 EventDetailsImpl::EventDetailsImpl(DebugEvent event, 2238 EventDetailsImpl::EventDetailsImpl(DebugEvent event,
2547 Handle<JSObject> exec_state, 2239 Handle<JSObject> exec_state,
2548 Handle<JSObject> event_data, 2240 Handle<JSObject> event_data,
2549 Handle<Object> callback_data, 2241 Handle<Object> callback_data)
2550 v8::Debug::ClientData* client_data)
2551 : event_(event), 2242 : event_(event),
2552 exec_state_(exec_state), 2243 exec_state_(exec_state),
2553 event_data_(event_data), 2244 event_data_(event_data),
2554 callback_data_(callback_data), 2245 callback_data_(callback_data) {}
2555 client_data_(client_data) {}
2556
2557 2246
2558 DebugEvent EventDetailsImpl::GetEvent() const { 2247 DebugEvent EventDetailsImpl::GetEvent() const {
2559 return event_; 2248 return event_;
2560 } 2249 }
2561 2250
2562 2251
2563 v8::Local<v8::Object> EventDetailsImpl::GetExecutionState() const { 2252 v8::Local<v8::Object> EventDetailsImpl::GetExecutionState() const {
2564 return v8::Utils::ToLocal(exec_state_); 2253 return v8::Utils::ToLocal(exec_state_);
2565 } 2254 }
2566 2255
2567 2256
2568 v8::Local<v8::Object> EventDetailsImpl::GetEventData() const { 2257 v8::Local<v8::Object> EventDetailsImpl::GetEventData() const {
2569 return v8::Utils::ToLocal(event_data_); 2258 return v8::Utils::ToLocal(event_data_);
2570 } 2259 }
2571 2260
2572 2261
2573 v8::Local<v8::Context> EventDetailsImpl::GetEventContext() const { 2262 v8::Local<v8::Context> EventDetailsImpl::GetEventContext() const {
2574 return GetDebugEventContext(exec_state_->GetIsolate()); 2263 return GetDebugEventContext(exec_state_->GetIsolate());
2575 } 2264 }
2576 2265
2577 2266
2578 v8::Local<v8::Value> EventDetailsImpl::GetCallbackData() const { 2267 v8::Local<v8::Value> EventDetailsImpl::GetCallbackData() const {
2579 return v8::Utils::ToLocal(callback_data_); 2268 return v8::Utils::ToLocal(callback_data_);
2580 } 2269 }
2581 2270
2582 2271
2583 v8::Debug::ClientData* EventDetailsImpl::GetClientData() const {
2584 return client_data_;
2585 }
2586
2587 v8::Isolate* EventDetailsImpl::GetIsolate() const { 2272 v8::Isolate* EventDetailsImpl::GetIsolate() const {
2588 return reinterpret_cast<v8::Isolate*>(exec_state_->GetIsolate()); 2273 return reinterpret_cast<v8::Isolate*>(exec_state_->GetIsolate());
2589 } 2274 }
2590 2275
2591 CommandMessage::CommandMessage()
2592 : text_(Vector<uint16_t>::empty()), client_data_(NULL) {}
2593
2594 CommandMessage::CommandMessage(const Vector<uint16_t>& text,
2595 v8::Debug::ClientData* data)
2596 : text_(text), client_data_(data) {}
2597
2598 void CommandMessage::Dispose() {
2599 text_.Dispose();
2600 delete client_data_;
2601 client_data_ = NULL;
2602 }
2603
2604 CommandMessage CommandMessage::New(const Vector<uint16_t>& command,
2605 v8::Debug::ClientData* data) {
2606 return CommandMessage(command.Clone(), data);
2607 }
2608
2609 CommandMessageQueue::CommandMessageQueue(int size)
2610 : start_(0), end_(0), size_(size) {
2611 messages_ = NewArray<CommandMessage>(size);
2612 }
2613
2614 CommandMessageQueue::~CommandMessageQueue() {
2615 while (!IsEmpty()) Get().Dispose();
2616 DeleteArray(messages_);
2617 }
2618
2619 CommandMessage CommandMessageQueue::Get() {
2620 DCHECK(!IsEmpty());
2621 int result = start_;
2622 start_ = (start_ + 1) % size_;
2623 return messages_[result];
2624 }
2625
2626 void CommandMessageQueue::Put(const CommandMessage& message) {
2627 if ((end_ + 1) % size_ == start_) {
2628 Expand();
2629 }
2630 messages_[end_] = message;
2631 end_ = (end_ + 1) % size_;
2632 }
2633
2634 void CommandMessageQueue::Expand() {
2635 CommandMessageQueue new_queue(size_ * 2);
2636 while (!IsEmpty()) {
2637 new_queue.Put(Get());
2638 }
2639 CommandMessage* array_to_free = messages_;
2640 *this = new_queue;
2641 new_queue.messages_ = array_to_free;
2642 // Make the new_queue empty so that it doesn't call Dispose on any messages.
2643 new_queue.start_ = new_queue.end_;
2644 // Automatic destructor called on new_queue, freeing array_to_free.
2645 }
2646
2647 LockingCommandMessageQueue::LockingCommandMessageQueue(Logger* logger, int size)
2648 : logger_(logger), queue_(size) {}
2649
2650 bool LockingCommandMessageQueue::IsEmpty() const {
2651 base::LockGuard<base::Mutex> lock_guard(&mutex_);
2652 return queue_.IsEmpty();
2653 }
2654
2655 CommandMessage LockingCommandMessageQueue::Get() {
2656 base::LockGuard<base::Mutex> lock_guard(&mutex_);
2657 CommandMessage result = queue_.Get();
2658 logger_->DebugEvent("Get", result.text());
2659 return result;
2660 }
2661
2662 void LockingCommandMessageQueue::Put(const CommandMessage& message) {
2663 base::LockGuard<base::Mutex> lock_guard(&mutex_);
2664 queue_.Put(message);
2665 logger_->DebugEvent("Put", message.text());
2666 }
2667
2668 void LockingCommandMessageQueue::Clear() {
2669 base::LockGuard<base::Mutex> lock_guard(&mutex_);
2670 queue_.Clear();
2671 }
2672
2673 } // namespace internal 2276 } // namespace internal
2674 } // namespace v8 2277 } // 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