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