| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 1156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1739 | 1736 |
| 1740 // Create the event data object. | 1737 // Create the event data object. |
| 1741 Handle<Object> event_data; | 1738 Handle<Object> event_data; |
| 1742 // Bail out and don't call debugger if exception. | 1739 // Bail out and don't call debugger if exception. |
| 1743 if (!MakeExceptionEvent( | 1740 if (!MakeExceptionEvent( |
| 1744 exception, uncaught, promise).ToHandle(&event_data)) { | 1741 exception, uncaught, promise).ToHandle(&event_data)) { |
| 1745 return; | 1742 return; |
| 1746 } | 1743 } |
| 1747 | 1744 |
| 1748 // Process debug event. | 1745 // Process debug event. |
| 1749 ProcessDebugEvent(v8::Exception, Handle<JSObject>::cast(event_data), false); | 1746 ProcessDebugEvent(v8::Exception, Handle<JSObject>::cast(event_data)); |
| 1750 // Return to continue execution from where the exception was thrown. | 1747 // Return to continue execution from where the exception was thrown. |
| 1751 } | 1748 } |
| 1752 | 1749 |
| 1753 | 1750 void Debug::OnDebugBreak(Handle<Object> break_points_hit) { |
| 1754 void Debug::OnDebugBreak(Handle<Object> break_points_hit, bool auto_continue) { | |
| 1755 // The caller provided for DebugScope. | 1751 // The caller provided for DebugScope. |
| 1756 AssertDebugContext(); | 1752 AssertDebugContext(); |
| 1757 // Bail out if there is no listener for this event | 1753 // Bail out if there is no listener for this event |
| 1758 if (ignore_events()) return; | 1754 if (ignore_events()) return; |
| 1759 | 1755 |
| 1760 #ifdef DEBUG | 1756 #ifdef DEBUG |
| 1761 PrintBreakLocation(); | 1757 PrintBreakLocation(); |
| 1762 #endif // DEBUG | 1758 #endif // DEBUG |
| 1763 | 1759 |
| 1764 HandleScope scope(isolate_); | 1760 HandleScope scope(isolate_); |
| 1765 // Create the event data object. | 1761 // Create the event data object. |
| 1766 Handle<Object> event_data; | 1762 Handle<Object> event_data; |
| 1767 // Bail out and don't call debugger if exception. | 1763 // Bail out and don't call debugger if exception. |
| 1768 if (!MakeBreakEvent(break_points_hit).ToHandle(&event_data)) return; | 1764 if (!MakeBreakEvent(break_points_hit).ToHandle(&event_data)) return; |
| 1769 | 1765 |
| 1770 // Process debug event. | 1766 // Process debug event. |
| 1771 ProcessDebugEvent(v8::Break, | 1767 ProcessDebugEvent(v8::Break, Handle<JSObject>::cast(event_data)); |
| 1772 Handle<JSObject>::cast(event_data), | |
| 1773 auto_continue); | |
| 1774 } | 1768 } |
| 1775 | 1769 |
| 1776 | 1770 |
| 1777 void Debug::OnCompileError(Handle<Script> script) { | 1771 void Debug::OnCompileError(Handle<Script> script) { |
| 1778 ProcessCompileEvent(v8::CompileError, script); | 1772 ProcessCompileEvent(v8::CompileError, script); |
| 1779 } | 1773 } |
| 1780 | 1774 |
| 1781 | 1775 |
| 1782 void Debug::OnBeforeCompile(Handle<Script> script) { | 1776 void Debug::OnBeforeCompile(Handle<Script> script) { |
| 1783 ProcessCompileEvent(v8::BeforeCompile, script); | 1777 ProcessCompileEvent(v8::BeforeCompile, script); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 1797 HandleScope scope(isolate_); | 1791 HandleScope scope(isolate_); |
| 1798 DebugScope debug_scope(this); | 1792 DebugScope debug_scope(this); |
| 1799 if (debug_scope.failed()) return; | 1793 if (debug_scope.failed()) return; |
| 1800 | 1794 |
| 1801 // Create the script collected state object. | 1795 // Create the script collected state object. |
| 1802 Handle<Object> event_data; | 1796 Handle<Object> event_data; |
| 1803 // Bail out and don't call debugger if exception. | 1797 // Bail out and don't call debugger if exception. |
| 1804 if (!MakeAsyncTaskEvent(type, id, name).ToHandle(&event_data)) return; | 1798 if (!MakeAsyncTaskEvent(type, id, name).ToHandle(&event_data)) return; |
| 1805 | 1799 |
| 1806 // Process debug event. | 1800 // Process debug event. |
| 1807 ProcessDebugEvent(v8::AsyncTaskEvent, | 1801 ProcessDebugEvent(v8::AsyncTaskEvent, Handle<JSObject>::cast(event_data)); |
| 1808 Handle<JSObject>::cast(event_data), | |
| 1809 true); | |
| 1810 } | 1802 } |
| 1811 | 1803 |
| 1812 | |
| 1813 void Debug::ProcessDebugEvent(v8::DebugEvent event, | 1804 void Debug::ProcessDebugEvent(v8::DebugEvent event, |
| 1814 Handle<JSObject> event_data, | 1805 Handle<JSObject> event_data) { |
| 1815 bool auto_continue) { | |
| 1816 HandleScope scope(isolate_); | 1806 HandleScope scope(isolate_); |
| 1817 | 1807 |
| 1818 // Create the execution state. | 1808 // Create the execution state. |
| 1819 Handle<Object> exec_state; | 1809 Handle<Object> exec_state; |
| 1820 // Bail out and don't call debugger if exception. | 1810 // Bail out and don't call debugger if exception. |
| 1821 if (!MakeExecutionState().ToHandle(&exec_state)) return; | 1811 if (!MakeExecutionState().ToHandle(&exec_state)) return; |
| 1822 | 1812 |
| 1823 // First notify the message handler if any. | 1813 // Notify registered debug event listener. |
| 1824 if (message_handler_ != NULL) { | 1814 if (!event_listener_.is_null()) { |
| 1825 NotifyMessageHandler(event, | |
| 1826 Handle<JSObject>::cast(exec_state), | |
| 1827 event_data, | |
| 1828 auto_continue); | |
| 1829 } | |
| 1830 // Notify registered debug event listener. This can be either a C or | |
| 1831 // a JavaScript function. Don't call event listener for v8::Break | |
| 1832 // here, if it's only a debug command -- they will be processed later. | |
| 1833 if ((event != v8::Break || !auto_continue) && !event_listener_.is_null()) { | |
| 1834 CallEventCallback(event, exec_state, event_data, NULL); | 1815 CallEventCallback(event, exec_state, event_data, NULL); |
| 1835 } | 1816 } |
| 1836 } | 1817 } |
| 1837 | 1818 |
| 1838 | 1819 |
| 1839 void Debug::CallEventCallback(v8::DebugEvent event, | 1820 void Debug::CallEventCallback(v8::DebugEvent event, |
| 1840 Handle<Object> exec_state, | 1821 Handle<Object> exec_state, |
| 1841 Handle<Object> event_data, | 1822 Handle<Object> event_data, |
| 1842 v8::Debug::ClientData* client_data) { | 1823 v8::Debug::ClientData* client_data) { |
| 1843 // Prevent other interrupts from triggering, for example API callbacks, | 1824 // Prevent other interrupts from triggering, for example API callbacks, |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1875 | 1856 |
| 1876 | 1857 |
| 1877 void Debug::ProcessCompileEvent(v8::DebugEvent event, Handle<Script> script) { | 1858 void Debug::ProcessCompileEvent(v8::DebugEvent event, Handle<Script> script) { |
| 1878 if (ignore_events()) return; | 1859 if (ignore_events()) return; |
| 1879 if (script->type() != i::Script::TYPE_NORMAL && | 1860 if (script->type() != i::Script::TYPE_NORMAL && |
| 1880 script->type() != i::Script::TYPE_WASM) { | 1861 script->type() != i::Script::TYPE_WASM) { |
| 1881 return; | 1862 return; |
| 1882 } | 1863 } |
| 1883 SuppressDebug while_processing(this); | 1864 SuppressDebug while_processing(this); |
| 1884 | 1865 |
| 1885 bool in_nested_debug_scope = in_debug_scope(); | |
| 1886 HandleScope scope(isolate_); | 1866 HandleScope scope(isolate_); |
| 1887 DebugScope debug_scope(this); | 1867 DebugScope debug_scope(this); |
| 1888 if (debug_scope.failed()) return; | 1868 if (debug_scope.failed()) return; |
| 1889 | 1869 |
| 1890 if (event == v8::AfterCompile) { | 1870 if (event == v8::AfterCompile) { |
| 1891 // If debugging there might be script break points registered for this | 1871 // If debugging there might be script break points registered for this |
| 1892 // script. Make sure that these break points are set. | 1872 // script. Make sure that these break points are set. |
| 1893 Handle<Object> argv[] = {Script::GetWrapper(script)}; | 1873 Handle<Object> argv[] = {Script::GetWrapper(script)}; |
| 1894 if (CallFunction("UpdateScriptBreakPoints", arraysize(argv), argv) | 1874 if (CallFunction("UpdateScriptBreakPoints", arraysize(argv), argv) |
| 1895 .is_null()) { | 1875 .is_null()) { |
| 1896 return; | 1876 return; |
| 1897 } | 1877 } |
| 1898 } | 1878 } |
| 1899 | 1879 |
| 1900 // Create the compile state object. | 1880 // Create the compile state object. |
| 1901 Handle<Object> event_data; | 1881 Handle<Object> event_data; |
| 1902 // Bail out and don't call debugger if exception. | 1882 // Bail out and don't call debugger if exception. |
| 1903 if (!MakeCompileEvent(script, event).ToHandle(&event_data)) return; | 1883 if (!MakeCompileEvent(script, event).ToHandle(&event_data)) return; |
| 1904 | 1884 |
| 1905 // Don't call NotifyMessageHandler if already in debug scope to avoid running | 1885 ProcessDebugEvent(event, Handle<JSObject>::cast(event_data)); |
| 1906 // nested command loop. | |
| 1907 if (in_nested_debug_scope) { | |
| 1908 if (event_listener_.is_null()) return; | |
| 1909 // Create the execution state. | |
| 1910 Handle<Object> exec_state; | |
| 1911 // Bail out and don't call debugger if exception. | |
| 1912 if (!MakeExecutionState().ToHandle(&exec_state)) return; | |
| 1913 | |
| 1914 CallEventCallback(event, exec_state, event_data, NULL); | |
| 1915 } else { | |
| 1916 // Process debug event. | |
| 1917 ProcessDebugEvent(event, Handle<JSObject>::cast(event_data), true); | |
| 1918 } | |
| 1919 } | 1886 } |
| 1920 | 1887 |
| 1921 | 1888 |
| 1922 Handle<Context> Debug::GetDebugContext() { | 1889 Handle<Context> Debug::GetDebugContext() { |
| 1923 if (!is_loaded()) return Handle<Context>(); | 1890 if (!is_loaded()) return Handle<Context>(); |
| 1924 DebugScope debug_scope(this); | 1891 DebugScope debug_scope(this); |
| 1925 if (debug_scope.failed()) return Handle<Context>(); | 1892 if (debug_scope.failed()) return Handle<Context>(); |
| 1926 // The global handle may be destroyed soon after. Return it reboxed. | 1893 // The global handle may be destroyed soon after. Return it reboxed. |
| 1927 return handle(*debug_context(), isolate_); | 1894 return handle(*debug_context(), isolate_); |
| 1928 } | 1895 } |
| 1929 | 1896 |
| 1930 | 1897 |
| 1931 void Debug::NotifyMessageHandler(v8::DebugEvent event, | |
| 1932 Handle<JSObject> exec_state, | |
| 1933 Handle<JSObject> event_data, | |
| 1934 bool auto_continue) { | |
| 1935 // Prevent other interrupts from triggering, for example API callbacks, | |
| 1936 // while dispatching message handler callbacks. | |
| 1937 PostponeInterruptsScope no_interrupts(isolate_); | |
| 1938 DCHECK(is_active_); | |
| 1939 HandleScope scope(isolate_); | |
| 1940 // Process the individual events. | |
| 1941 bool sendEventMessage = false; | |
| 1942 switch (event) { | |
| 1943 case v8::Break: | |
| 1944 sendEventMessage = !auto_continue; | |
| 1945 break; | |
| 1946 case v8::NewFunction: | |
| 1947 case v8::BeforeCompile: | |
| 1948 case v8::CompileError: | |
| 1949 case v8::AsyncTaskEvent: | |
| 1950 break; | |
| 1951 case v8::Exception: | |
| 1952 case v8::AfterCompile: | |
| 1953 sendEventMessage = true; | |
| 1954 break; | |
| 1955 } | |
| 1956 | |
| 1957 // The debug command interrupt flag might have been set when the command was | |
| 1958 // added. It should be enough to clear the flag only once while we are in the | |
| 1959 // debugger. | |
| 1960 DCHECK(in_debug_scope()); | |
| 1961 isolate_->stack_guard()->ClearDebugCommand(); | |
| 1962 | |
| 1963 // Notify the debugger that a debug event has occurred unless auto continue is | |
| 1964 // active in which case no event is send. | |
| 1965 if (sendEventMessage) { | |
| 1966 MessageImpl message = MessageImpl::NewEvent( | |
| 1967 event, | |
| 1968 auto_continue, | |
| 1969 Handle<JSObject>::cast(exec_state), | |
| 1970 Handle<JSObject>::cast(event_data)); | |
| 1971 InvokeMessageHandler(message); | |
| 1972 } | |
| 1973 | |
| 1974 // If auto continue don't make the event cause a break, but process messages | |
| 1975 // in the queue if any. For script collected events don't even process | |
| 1976 // messages in the queue as the execution state might not be what is expected | |
| 1977 // by the client. | |
| 1978 if (auto_continue && !has_commands()) return; | |
| 1979 | |
| 1980 // DebugCommandProcessor goes here. | |
| 1981 bool running = auto_continue; | |
| 1982 | |
| 1983 Handle<Object> cmd_processor_ctor = | |
| 1984 JSReceiver::GetProperty(isolate_, exec_state, "debugCommandProcessor") | |
| 1985 .ToHandleChecked(); | |
| 1986 Handle<Object> ctor_args[] = { isolate_->factory()->ToBoolean(running) }; | |
| 1987 Handle<JSReceiver> cmd_processor = Handle<JSReceiver>::cast( | |
| 1988 Execution::Call(isolate_, cmd_processor_ctor, exec_state, 1, ctor_args) | |
| 1989 .ToHandleChecked()); | |
| 1990 Handle<JSFunction> process_debug_request = Handle<JSFunction>::cast( | |
| 1991 JSReceiver::GetProperty(isolate_, cmd_processor, "processDebugRequest") | |
| 1992 .ToHandleChecked()); | |
| 1993 Handle<Object> is_running = | |
| 1994 JSReceiver::GetProperty(isolate_, cmd_processor, "isRunning") | |
| 1995 .ToHandleChecked(); | |
| 1996 | |
| 1997 // Process requests from the debugger. | |
| 1998 do { | |
| 1999 // Wait for new command in the queue. | |
| 2000 command_received_.Wait(); | |
| 2001 | |
| 2002 // Get the command from the queue. | |
| 2003 CommandMessage command = command_queue_.Get(); | |
| 2004 isolate_->logger()->DebugTag( | |
| 2005 "Got request from command queue, in interactive loop."); | |
| 2006 if (!is_active()) { | |
| 2007 // Delete command text and user data. | |
| 2008 command.Dispose(); | |
| 2009 return; | |
| 2010 } | |
| 2011 | |
| 2012 Vector<const uc16> command_text( | |
| 2013 const_cast<const uc16*>(command.text().start()), | |
| 2014 command.text().length()); | |
| 2015 Handle<String> request_text = isolate_->factory()->NewStringFromTwoByte( | |
| 2016 command_text).ToHandleChecked(); | |
| 2017 Handle<Object> request_args[] = { request_text }; | |
| 2018 Handle<Object> answer_value; | |
| 2019 Handle<String> answer; | |
| 2020 MaybeHandle<Object> maybe_exception; | |
| 2021 MaybeHandle<Object> maybe_result = | |
| 2022 Execution::TryCall(isolate_, process_debug_request, cmd_processor, 1, | |
| 2023 request_args, &maybe_exception); | |
| 2024 | |
| 2025 if (maybe_result.ToHandle(&answer_value)) { | |
| 2026 if (answer_value->IsUndefined(isolate_)) { | |
| 2027 answer = isolate_->factory()->empty_string(); | |
| 2028 } else { | |
| 2029 answer = Handle<String>::cast(answer_value); | |
| 2030 } | |
| 2031 | |
| 2032 // Log the JSON request/response. | |
| 2033 if (FLAG_trace_debug_json) { | |
| 2034 PrintF("%s\n", request_text->ToCString().get()); | |
| 2035 PrintF("%s\n", answer->ToCString().get()); | |
| 2036 } | |
| 2037 | |
| 2038 Handle<Object> is_running_args[] = { answer }; | |
| 2039 maybe_result = Execution::Call( | |
| 2040 isolate_, is_running, cmd_processor, 1, is_running_args); | |
| 2041 Handle<Object> result; | |
| 2042 if (!maybe_result.ToHandle(&result)) break; | |
| 2043 running = result->IsTrue(isolate_); | |
| 2044 } else { | |
| 2045 Handle<Object> exception; | |
| 2046 if (!maybe_exception.ToHandle(&exception)) break; | |
| 2047 Handle<Object> result; | |
| 2048 if (!Object::ToString(isolate_, exception).ToHandle(&result)) break; | |
| 2049 answer = Handle<String>::cast(result); | |
| 2050 } | |
| 2051 | |
| 2052 // Return the result. | |
| 2053 MessageImpl message = MessageImpl::NewResponse( | |
| 2054 event, running, exec_state, event_data, answer, command.client_data()); | |
| 2055 InvokeMessageHandler(message); | |
| 2056 command.Dispose(); | |
| 2057 | |
| 2058 // Return from debug event processing if either the VM is put into the | |
| 2059 // running state (through a continue command) or auto continue is active | |
| 2060 // and there are no more commands queued. | |
| 2061 } while (!running || has_commands()); | |
| 2062 command_queue_.Clear(); | |
| 2063 } | |
| 2064 | |
| 2065 | |
| 2066 void Debug::SetEventListener(Handle<Object> callback, | 1898 void Debug::SetEventListener(Handle<Object> callback, |
| 2067 Handle<Object> data) { | 1899 Handle<Object> data) { |
| 2068 GlobalHandles* global_handles = isolate_->global_handles(); | 1900 GlobalHandles* global_handles = isolate_->global_handles(); |
| 2069 | 1901 |
| 2070 // Remove existing entry. | 1902 // Remove existing entry. |
| 2071 GlobalHandles::Destroy(event_listener_.location()); | 1903 GlobalHandles::Destroy(event_listener_.location()); |
| 2072 event_listener_ = Handle<Object>(); | 1904 event_listener_ = Handle<Object>(); |
| 2073 GlobalHandles::Destroy(event_listener_data_.location()); | 1905 GlobalHandles::Destroy(event_listener_data_.location()); |
| 2074 event_listener_data_ = Handle<Object>(); | 1906 event_listener_data_ = Handle<Object>(); |
| 2075 | 1907 |
| 2076 // Set new entry. | 1908 // Set new entry. |
| 2077 if (!callback->IsUndefined(isolate_) && !callback->IsNull(isolate_)) { | 1909 if (!callback->IsUndefined(isolate_) && !callback->IsNull(isolate_)) { |
| 2078 event_listener_ = global_handles->Create(*callback); | 1910 event_listener_ = global_handles->Create(*callback); |
| 2079 if (data.is_null()) data = isolate_->factory()->undefined_value(); | 1911 if (data.is_null()) data = isolate_->factory()->undefined_value(); |
| 2080 event_listener_data_ = global_handles->Create(*data); | 1912 event_listener_data_ = global_handles->Create(*data); |
| 2081 } | 1913 } |
| 2082 | 1914 |
| 2083 UpdateState(); | 1915 UpdateState(); |
| 2084 } | 1916 } |
| 2085 | 1917 |
| 2086 | 1918 |
| 2087 void Debug::SetMessageHandler(v8::Debug::MessageHandler handler) { | |
| 2088 message_handler_ = handler; | |
| 2089 UpdateState(); | |
| 2090 if (handler == NULL && in_debug_scope()) { | |
| 2091 // Send an empty command to the debugger if in a break to make JavaScript | |
| 2092 // run again if the debugger is closed. | |
| 2093 EnqueueCommandMessage(Vector<const uint16_t>::empty()); | |
| 2094 } | |
| 2095 } | |
| 2096 | |
| 2097 | |
| 2098 | |
| 2099 void Debug::UpdateState() { | 1919 void Debug::UpdateState() { |
| 2100 bool is_active = message_handler_ != NULL || !event_listener_.is_null(); | 1920 bool is_active = !event_listener_.is_null(); |
| 2101 if (is_active || in_debug_scope()) { | 1921 if (is_active || in_debug_scope()) { |
| 2102 // Note that the debug context could have already been loaded to | 1922 // Note that the debug context could have already been loaded to |
| 2103 // bootstrap test cases. | 1923 // bootstrap test cases. |
| 2104 isolate_->compilation_cache()->Disable(); | 1924 isolate_->compilation_cache()->Disable(); |
| 2105 is_active = Load(); | 1925 is_active = Load(); |
| 2106 } else if (is_loaded()) { | 1926 } else if (is_loaded()) { |
| 2107 isolate_->compilation_cache()->Enable(); | 1927 isolate_->compilation_cache()->Enable(); |
| 2108 Unload(); | 1928 Unload(); |
| 2109 } | 1929 } |
| 2110 is_active_ = is_active; | 1930 is_active_ = is_active; |
| 2111 } | 1931 } |
| 2112 | 1932 |
| 2113 | 1933 |
| 2114 // Calls the registered debug message handler. This callback is part of the | |
| 2115 // public API. | |
| 2116 void Debug::InvokeMessageHandler(MessageImpl message) { | |
| 2117 if (message_handler_ != NULL) message_handler_(message); | |
| 2118 } | |
| 2119 | |
| 2120 | |
| 2121 // Puts a command coming from the public API on the queue. Creates | |
| 2122 // a copy of the command string managed by the debugger. Up to this | |
| 2123 // point, the command data was managed by the API client. Called | |
| 2124 // by the API client thread. | |
| 2125 void Debug::EnqueueCommandMessage(Vector<const uint16_t> command, | |
| 2126 v8::Debug::ClientData* client_data) { | |
| 2127 // Need to cast away const. | |
| 2128 CommandMessage message = CommandMessage::New( | |
| 2129 Vector<uint16_t>(const_cast<uint16_t*>(command.start()), | |
| 2130 command.length()), | |
| 2131 client_data); | |
| 2132 isolate_->logger()->DebugTag("Put command on command_queue."); | |
| 2133 command_queue_.Put(message); | |
| 2134 command_received_.Signal(); | |
| 2135 | |
| 2136 // Set the debug command break flag to have the command processed. | |
| 2137 if (!in_debug_scope()) isolate_->stack_guard()->RequestDebugCommand(); | |
| 2138 } | |
| 2139 | |
| 2140 | |
| 2141 MaybeHandle<Object> Debug::Call(Handle<Object> fun, Handle<Object> data) { | 1934 MaybeHandle<Object> Debug::Call(Handle<Object> fun, Handle<Object> data) { |
| 2142 DebugScope debug_scope(this); | 1935 DebugScope debug_scope(this); |
| 2143 if (debug_scope.failed()) return isolate_->factory()->undefined_value(); | 1936 if (debug_scope.failed()) return isolate_->factory()->undefined_value(); |
| 2144 | 1937 |
| 2145 // Create the execution state. | 1938 // Create the execution state. |
| 2146 Handle<Object> exec_state; | 1939 Handle<Object> exec_state; |
| 2147 if (!MakeExecutionState().ToHandle(&exec_state)) { | 1940 if (!MakeExecutionState().ToHandle(&exec_state)) { |
| 2148 return isolate_->factory()->undefined_value(); | 1941 return isolate_->factory()->undefined_value(); |
| 2149 } | 1942 } |
| 2150 | 1943 |
| (...skipping 26 matching lines...) Expand all Loading... |
| 2177 if (!JSFunction::cast(fun)->shared()->IsSubjectToDebugging()) return; | 1970 if (!JSFunction::cast(fun)->shared()->IsSubjectToDebugging()) return; |
| 2178 JSGlobalObject* global = | 1971 JSGlobalObject* global = |
| 2179 JSFunction::cast(fun)->context()->global_object(); | 1972 JSFunction::cast(fun)->context()->global_object(); |
| 2180 // Don't stop in debugger functions. | 1973 // Don't stop in debugger functions. |
| 2181 if (IsDebugGlobal(global)) return; | 1974 if (IsDebugGlobal(global)) return; |
| 2182 // Don't stop if the break location is muted. | 1975 // Don't stop if the break location is muted. |
| 2183 if (IsMutedAtCurrentLocation(it.frame())) return; | 1976 if (IsMutedAtCurrentLocation(it.frame())) return; |
| 2184 } | 1977 } |
| 2185 } | 1978 } |
| 2186 | 1979 |
| 2187 // Collect the break state before clearing the flags. | |
| 2188 bool debug_command_only = isolate_->stack_guard()->CheckDebugCommand() && | |
| 2189 !isolate_->stack_guard()->CheckDebugBreak(); | |
| 2190 | |
| 2191 isolate_->stack_guard()->ClearDebugBreak(); | 1980 isolate_->stack_guard()->ClearDebugBreak(); |
| 2192 | 1981 |
| 2193 // Clear stepping to avoid duplicate breaks. | 1982 // Clear stepping to avoid duplicate breaks. |
| 2194 ClearStepping(); | 1983 ClearStepping(); |
| 2195 | 1984 |
| 2196 ProcessDebugMessages(debug_command_only); | |
| 2197 } | |
| 2198 | |
| 2199 | |
| 2200 void Debug::ProcessDebugMessages(bool debug_command_only) { | |
| 2201 isolate_->stack_guard()->ClearDebugCommand(); | |
| 2202 | |
| 2203 StackLimitCheck check(isolate_); | |
| 2204 if (check.HasOverflowed()) return; | |
| 2205 | |
| 2206 HandleScope scope(isolate_); | 1985 HandleScope scope(isolate_); |
| 2207 DebugScope debug_scope(this); | 1986 DebugScope debug_scope(this); |
| 2208 if (debug_scope.failed()) return; | 1987 if (debug_scope.failed()) return; |
| 2209 | 1988 |
| 2210 // Notify the debug event listeners. Indicate auto continue if the break was | 1989 // Notify the debug event listeners. |
| 2211 // a debug command break. | 1990 OnDebugBreak(isolate_->factory()->undefined_value()); |
| 2212 OnDebugBreak(isolate_->factory()->undefined_value(), debug_command_only); | |
| 2213 } | 1991 } |
| 2214 | 1992 |
| 2215 #ifdef DEBUG | 1993 #ifdef DEBUG |
| 2216 void Debug::PrintBreakLocation() { | 1994 void Debug::PrintBreakLocation() { |
| 2217 if (!FLAG_print_break_location) return; | 1995 if (!FLAG_print_break_location) return; |
| 2218 HandleScope scope(isolate_); | 1996 HandleScope scope(isolate_); |
| 2219 JavaScriptFrameIterator iterator(isolate_); | 1997 JavaScriptFrameIterator iterator(isolate_); |
| 2220 if (iterator.done()) return; | 1998 if (iterator.done()) return; |
| 2221 JavaScriptFrame* frame = iterator.frame(); | 1999 JavaScriptFrame* frame = iterator.frame(); |
| 2222 FrameSummary summary = FrameSummary::GetFirst(frame); | 2000 FrameSummary summary = FrameSummary::GetFirst(frame); |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2286 } | 2064 } |
| 2287 | 2065 |
| 2288 | 2066 |
| 2289 DebugScope::~DebugScope() { | 2067 DebugScope::~DebugScope() { |
| 2290 if (!failed_ && prev_ == NULL) { | 2068 if (!failed_ && prev_ == NULL) { |
| 2291 // Clear mirror cache when leaving the debugger. Skip this if there is a | 2069 // Clear mirror cache when leaving the debugger. Skip this if there is a |
| 2292 // pending exception as clearing the mirror cache calls back into | 2070 // pending exception as clearing the mirror cache calls back into |
| 2293 // JavaScript. This can happen if the v8::Debug::Call is used in which | 2071 // JavaScript. This can happen if the v8::Debug::Call is used in which |
| 2294 // case the exception should end up in the calling code. | 2072 // case the exception should end up in the calling code. |
| 2295 if (!isolate()->has_pending_exception()) debug_->ClearMirrorCache(); | 2073 if (!isolate()->has_pending_exception()) debug_->ClearMirrorCache(); |
| 2296 | |
| 2297 // If there are commands in the queue when leaving the debugger request | |
| 2298 // that these commands are processed. | |
| 2299 if (debug_->has_commands()) isolate()->stack_guard()->RequestDebugCommand(); | |
| 2300 } | 2074 } |
| 2301 | 2075 |
| 2302 // Leaving this debugger entry. | 2076 // Leaving this debugger entry. |
| 2303 base::NoBarrier_Store(&debug_->thread_local_.current_debug_scope_, | 2077 base::NoBarrier_Store(&debug_->thread_local_.current_debug_scope_, |
| 2304 reinterpret_cast<base::AtomicWord>(prev_)); | 2078 reinterpret_cast<base::AtomicWord>(prev_)); |
| 2305 | 2079 |
| 2306 // Restore to the previous break state. | 2080 // Restore to the previous break state. |
| 2307 debug_->thread_local_.break_frame_id_ = break_frame_id_; | 2081 debug_->thread_local_.break_frame_id_ = break_frame_id_; |
| 2308 debug_->thread_local_.break_id_ = break_id_; | 2082 debug_->thread_local_.break_id_ = break_id_; |
| 2309 debug_->thread_local_.return_value_ = return_value_; | 2083 debug_->thread_local_.return_value_ = return_value_; |
| 2310 | 2084 |
| 2311 debug_->UpdateState(); | 2085 debug_->UpdateState(); |
| 2312 } | 2086 } |
| 2313 | 2087 |
| 2314 | 2088 |
| 2315 MessageImpl MessageImpl::NewEvent(DebugEvent event, | |
| 2316 bool running, | |
| 2317 Handle<JSObject> exec_state, | |
| 2318 Handle<JSObject> event_data) { | |
| 2319 MessageImpl message(true, event, running, | |
| 2320 exec_state, event_data, Handle<String>(), NULL); | |
| 2321 return message; | |
| 2322 } | |
| 2323 | |
| 2324 | |
| 2325 MessageImpl MessageImpl::NewResponse(DebugEvent event, | |
| 2326 bool running, | |
| 2327 Handle<JSObject> exec_state, | |
| 2328 Handle<JSObject> event_data, | |
| 2329 Handle<String> response_json, | |
| 2330 v8::Debug::ClientData* client_data) { | |
| 2331 MessageImpl message(false, event, running, | |
| 2332 exec_state, event_data, response_json, client_data); | |
| 2333 return message; | |
| 2334 } | |
| 2335 | |
| 2336 | |
| 2337 MessageImpl::MessageImpl(bool is_event, | |
| 2338 DebugEvent event, | |
| 2339 bool running, | |
| 2340 Handle<JSObject> exec_state, | |
| 2341 Handle<JSObject> event_data, | |
| 2342 Handle<String> response_json, | |
| 2343 v8::Debug::ClientData* client_data) | |
| 2344 : is_event_(is_event), | |
| 2345 event_(event), | |
| 2346 running_(running), | |
| 2347 exec_state_(exec_state), | |
| 2348 event_data_(event_data), | |
| 2349 response_json_(response_json), | |
| 2350 client_data_(client_data) {} | |
| 2351 | |
| 2352 | |
| 2353 bool MessageImpl::IsEvent() const { | |
| 2354 return is_event_; | |
| 2355 } | |
| 2356 | |
| 2357 | |
| 2358 bool MessageImpl::IsResponse() const { | |
| 2359 return !is_event_; | |
| 2360 } | |
| 2361 | |
| 2362 | |
| 2363 DebugEvent MessageImpl::GetEvent() const { | |
| 2364 return event_; | |
| 2365 } | |
| 2366 | |
| 2367 | |
| 2368 bool MessageImpl::WillStartRunning() const { | |
| 2369 return running_; | |
| 2370 } | |
| 2371 | |
| 2372 | |
| 2373 v8::Local<v8::Object> MessageImpl::GetExecutionState() const { | |
| 2374 return v8::Utils::ToLocal(exec_state_); | |
| 2375 } | |
| 2376 | |
| 2377 | |
| 2378 v8::Isolate* MessageImpl::GetIsolate() const { | |
| 2379 return reinterpret_cast<v8::Isolate*>(exec_state_->GetIsolate()); | |
| 2380 } | |
| 2381 | |
| 2382 | |
| 2383 v8::Local<v8::Object> MessageImpl::GetEventData() const { | |
| 2384 return v8::Utils::ToLocal(event_data_); | |
| 2385 } | |
| 2386 | |
| 2387 | |
| 2388 v8::Local<v8::String> MessageImpl::GetJSON() const { | |
| 2389 Isolate* isolate = event_data_->GetIsolate(); | |
| 2390 v8::EscapableHandleScope scope(reinterpret_cast<v8::Isolate*>(isolate)); | |
| 2391 | |
| 2392 if (IsEvent()) { | |
| 2393 // Call toJSONProtocol on the debug event object. | |
| 2394 Handle<Object> fun = | |
| 2395 JSReceiver::GetProperty(isolate, event_data_, "toJSONProtocol") | |
| 2396 .ToHandleChecked(); | |
| 2397 if (!fun->IsJSFunction()) { | |
| 2398 return v8::Local<v8::String>(); | |
| 2399 } | |
| 2400 | |
| 2401 MaybeHandle<Object> maybe_json = | |
| 2402 Execution::TryCall(isolate, fun, event_data_, 0, NULL); | |
| 2403 Handle<Object> json; | |
| 2404 if (!maybe_json.ToHandle(&json) || !json->IsString()) { | |
| 2405 return v8::Local<v8::String>(); | |
| 2406 } | |
| 2407 return scope.Escape(v8::Utils::ToLocal(Handle<String>::cast(json))); | |
| 2408 } else { | |
| 2409 return v8::Utils::ToLocal(response_json_); | |
| 2410 } | |
| 2411 } | |
| 2412 | |
| 2413 namespace { | |
| 2414 v8::Local<v8::Context> GetDebugEventContext(Isolate* isolate) { | |
| 2415 Handle<Context> context = isolate->debug()->debugger_entry()->GetContext(); | |
| 2416 // Isolate::context() may have been NULL when "script collected" event | |
| 2417 // occured. | |
| 2418 if (context.is_null()) return v8::Local<v8::Context>(); | |
| 2419 Handle<Context> native_context(context->native_context()); | |
| 2420 return v8::Utils::ToLocal(native_context); | |
| 2421 } | |
| 2422 } // anonymous namespace | |
| 2423 | |
| 2424 v8::Local<v8::Context> MessageImpl::GetEventContext() const { | |
| 2425 Isolate* isolate = event_data_->GetIsolate(); | |
| 2426 v8::Local<v8::Context> context = GetDebugEventContext(isolate); | |
| 2427 // Isolate::context() may be NULL when "script collected" event occurs. | |
| 2428 DCHECK(!context.IsEmpty()); | |
| 2429 return context; | |
| 2430 } | |
| 2431 | |
| 2432 | |
| 2433 v8::Debug::ClientData* MessageImpl::GetClientData() const { | |
| 2434 return client_data_; | |
| 2435 } | |
| 2436 | |
| 2437 | |
| 2438 EventDetailsImpl::EventDetailsImpl(DebugEvent event, | 2089 EventDetailsImpl::EventDetailsImpl(DebugEvent event, |
| 2439 Handle<JSObject> exec_state, | 2090 Handle<JSObject> exec_state, |
| 2440 Handle<JSObject> event_data, | 2091 Handle<JSObject> event_data, |
| 2441 Handle<Object> callback_data, | 2092 Handle<Object> callback_data, |
| 2442 v8::Debug::ClientData* client_data) | 2093 v8::Debug::ClientData* client_data) |
| 2443 : event_(event), | 2094 : event_(event), |
| 2444 exec_state_(exec_state), | 2095 exec_state_(exec_state), |
| 2445 event_data_(event_data), | 2096 event_data_(event_data), |
| 2446 callback_data_(callback_data), | 2097 callback_data_(callback_data), |
| 2447 client_data_(client_data) {} | 2098 client_data_(client_data) {} |
| 2448 | 2099 |
| 2449 | 2100 |
| 2450 DebugEvent EventDetailsImpl::GetEvent() const { | 2101 DebugEvent EventDetailsImpl::GetEvent() const { |
| 2451 return event_; | 2102 return event_; |
| 2452 } | 2103 } |
| 2453 | 2104 |
| 2454 | 2105 |
| 2455 v8::Local<v8::Object> EventDetailsImpl::GetExecutionState() const { | 2106 v8::Local<v8::Object> EventDetailsImpl::GetExecutionState() const { |
| 2456 return v8::Utils::ToLocal(exec_state_); | 2107 return v8::Utils::ToLocal(exec_state_); |
| 2457 } | 2108 } |
| 2458 | 2109 |
| 2459 | 2110 |
| 2460 v8::Local<v8::Object> EventDetailsImpl::GetEventData() const { | 2111 v8::Local<v8::Object> EventDetailsImpl::GetEventData() const { |
| 2461 return v8::Utils::ToLocal(event_data_); | 2112 return v8::Utils::ToLocal(event_data_); |
| 2462 } | 2113 } |
| 2463 | 2114 |
| 2464 | 2115 |
| 2465 v8::Local<v8::Context> EventDetailsImpl::GetEventContext() const { | 2116 v8::Local<v8::Context> EventDetailsImpl::GetEventContext() const { |
| 2466 return GetDebugEventContext(exec_state_->GetIsolate()); | 2117 Handle<Context> context = |
| 2118 exec_state_->GetIsolate()->debug()->debugger_entry()->GetContext(); |
| 2119 if (context.is_null()) return v8::Local<v8::Context>(); |
| 2120 Handle<Context> native_context(context->native_context()); |
| 2121 return v8::Utils::ToLocal(native_context); |
| 2467 } | 2122 } |
| 2468 | 2123 |
| 2469 | 2124 |
| 2470 v8::Local<v8::Value> EventDetailsImpl::GetCallbackData() const { | 2125 v8::Local<v8::Value> EventDetailsImpl::GetCallbackData() const { |
| 2471 return v8::Utils::ToLocal(callback_data_); | 2126 return v8::Utils::ToLocal(callback_data_); |
| 2472 } | 2127 } |
| 2473 | 2128 |
| 2474 | 2129 |
| 2475 v8::Debug::ClientData* EventDetailsImpl::GetClientData() const { | 2130 v8::Debug::ClientData* EventDetailsImpl::GetClientData() const { |
| 2476 return client_data_; | 2131 return client_data_; |
| 2477 } | 2132 } |
| 2478 | 2133 |
| 2479 v8::Isolate* EventDetailsImpl::GetIsolate() const { | 2134 v8::Isolate* EventDetailsImpl::GetIsolate() const { |
| 2480 return reinterpret_cast<v8::Isolate*>(exec_state_->GetIsolate()); | 2135 return reinterpret_cast<v8::Isolate*>(exec_state_->GetIsolate()); |
| 2481 } | 2136 } |
| 2482 | 2137 |
| 2483 CommandMessage::CommandMessage() : text_(Vector<uint16_t>::empty()), | |
| 2484 client_data_(NULL) { | |
| 2485 } | |
| 2486 | |
| 2487 | |
| 2488 CommandMessage::CommandMessage(const Vector<uint16_t>& text, | |
| 2489 v8::Debug::ClientData* data) | |
| 2490 : text_(text), | |
| 2491 client_data_(data) { | |
| 2492 } | |
| 2493 | |
| 2494 | |
| 2495 void CommandMessage::Dispose() { | |
| 2496 text_.Dispose(); | |
| 2497 delete client_data_; | |
| 2498 client_data_ = NULL; | |
| 2499 } | |
| 2500 | |
| 2501 | |
| 2502 CommandMessage CommandMessage::New(const Vector<uint16_t>& command, | |
| 2503 v8::Debug::ClientData* data) { | |
| 2504 return CommandMessage(command.Clone(), data); | |
| 2505 } | |
| 2506 | |
| 2507 | |
| 2508 CommandMessageQueue::CommandMessageQueue(int size) : start_(0), end_(0), | |
| 2509 size_(size) { | |
| 2510 messages_ = NewArray<CommandMessage>(size); | |
| 2511 } | |
| 2512 | |
| 2513 | |
| 2514 CommandMessageQueue::~CommandMessageQueue() { | |
| 2515 while (!IsEmpty()) Get().Dispose(); | |
| 2516 DeleteArray(messages_); | |
| 2517 } | |
| 2518 | |
| 2519 | |
| 2520 CommandMessage CommandMessageQueue::Get() { | |
| 2521 DCHECK(!IsEmpty()); | |
| 2522 int result = start_; | |
| 2523 start_ = (start_ + 1) % size_; | |
| 2524 return messages_[result]; | |
| 2525 } | |
| 2526 | |
| 2527 | |
| 2528 void CommandMessageQueue::Put(const CommandMessage& message) { | |
| 2529 if ((end_ + 1) % size_ == start_) { | |
| 2530 Expand(); | |
| 2531 } | |
| 2532 messages_[end_] = message; | |
| 2533 end_ = (end_ + 1) % size_; | |
| 2534 } | |
| 2535 | |
| 2536 | |
| 2537 void CommandMessageQueue::Expand() { | |
| 2538 CommandMessageQueue new_queue(size_ * 2); | |
| 2539 while (!IsEmpty()) { | |
| 2540 new_queue.Put(Get()); | |
| 2541 } | |
| 2542 CommandMessage* array_to_free = messages_; | |
| 2543 *this = new_queue; | |
| 2544 new_queue.messages_ = array_to_free; | |
| 2545 // Make the new_queue empty so that it doesn't call Dispose on any messages. | |
| 2546 new_queue.start_ = new_queue.end_; | |
| 2547 // Automatic destructor called on new_queue, freeing array_to_free. | |
| 2548 } | |
| 2549 | |
| 2550 | |
| 2551 LockingCommandMessageQueue::LockingCommandMessageQueue(Logger* logger, int size) | |
| 2552 : logger_(logger), queue_(size) {} | |
| 2553 | |
| 2554 | |
| 2555 bool LockingCommandMessageQueue::IsEmpty() const { | |
| 2556 base::LockGuard<base::Mutex> lock_guard(&mutex_); | |
| 2557 return queue_.IsEmpty(); | |
| 2558 } | |
| 2559 | |
| 2560 | |
| 2561 CommandMessage LockingCommandMessageQueue::Get() { | |
| 2562 base::LockGuard<base::Mutex> lock_guard(&mutex_); | |
| 2563 CommandMessage result = queue_.Get(); | |
| 2564 logger_->DebugEvent("Get", result.text()); | |
| 2565 return result; | |
| 2566 } | |
| 2567 | |
| 2568 | |
| 2569 void LockingCommandMessageQueue::Put(const CommandMessage& message) { | |
| 2570 base::LockGuard<base::Mutex> lock_guard(&mutex_); | |
| 2571 queue_.Put(message); | |
| 2572 logger_->DebugEvent("Put", message.text()); | |
| 2573 } | |
| 2574 | |
| 2575 | |
| 2576 void LockingCommandMessageQueue::Clear() { | |
| 2577 base::LockGuard<base::Mutex> lock_guard(&mutex_); | |
| 2578 queue_.Clear(); | |
| 2579 } | |
| 2580 | |
| 2581 } // namespace internal | 2138 } // namespace internal |
| 2582 } // namespace v8 | 2139 } // namespace v8 |
| OLD | NEW |