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

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

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

Powered by Google App Engine
This is Rietveld 408576698