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

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

Issue 2633803002: [inspector] implemented blackboxing inside v8 (Closed)
Patch Set: fixed tests Created 3 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
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 825 matching lines...) Expand 10 before | Expand all | Expand 10 after
836 while (debug_info_list_ != NULL) { 836 while (debug_info_list_ != NULL) {
837 RemoveDebugInfoAndClearFromShared(debug_info_list_->debug_info()); 837 RemoveDebugInfoAndClearFromShared(debug_info_list_->debug_info());
838 } 838 }
839 } 839 }
840 840
841 void Debug::FloodWithOneShot(Handle<JSFunction> function, 841 void Debug::FloodWithOneShot(Handle<JSFunction> function,
842 BreakLocatorType type) { 842 BreakLocatorType type) {
843 // Debug utility functions are not subject to debugging. 843 // Debug utility functions are not subject to debugging.
844 if (function->native_context() == *debug_context()) return; 844 if (function->native_context() == *debug_context()) return;
845 845
846 if (!function->shared()->IsSubjectToDebugging()) { 846 if (!function->shared()->IsSubjectToDebugging() ||
847 function->shared()->DebugIsBlackboxed()) {
847 // Builtin functions are not subject to stepping, but need to be 848 // Builtin functions are not subject to stepping, but need to be
848 // deoptimized, because optimized code does not check for debug 849 // deoptimized, because optimized code does not check for debug
849 // step in at call sites. 850 // step in at call sites.
850 Deoptimizer::DeoptimizeFunction(*function); 851 Deoptimizer::DeoptimizeFunction(*function);
851 return; 852 return;
852 } 853 }
853 // Make sure the function is compiled and has set up the debug info. 854 // Make sure the function is compiled and has set up the debug info.
854 Handle<SharedFunctionInfo> shared(function->shared()); 855 Handle<SharedFunctionInfo> shared(function->shared());
855 if (!EnsureDebugInfo(shared, function)) { 856 if (!EnsureDebugInfo(shared, function)) {
856 // Return if we failed to retrieve the debug info. 857 // Return if we failed to retrieve the debug info.
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
955 if (last_step_action() == StepNext || last_step_action() == StepOut) { 956 if (last_step_action() == StepNext || last_step_action() == StepOut) {
956 while (!it.done()) { 957 while (!it.done()) {
957 Address current_fp = it.frame()->UnpaddedFP(); 958 Address current_fp = it.frame()->UnpaddedFP();
958 if (current_fp >= thread_local_.target_fp_) break; 959 if (current_fp >= thread_local_.target_fp_) break;
959 it.Advance(); 960 it.Advance();
960 } 961 }
961 } 962 }
962 963
963 // Find the closest Javascript frame we can flood with one-shots. 964 // Find the closest Javascript frame we can flood with one-shots.
964 while (!it.done() && 965 while (!it.done() &&
965 !it.frame()->function()->shared()->IsSubjectToDebugging()) { 966 (!it.frame()->function()->shared()->IsSubjectToDebugging() ||
967 it.frame()->function()->shared()->DebugIsBlackboxed())) {
966 it.Advance(); 968 it.Advance();
967 } 969 }
968 970
969 if (it.done()) return; // No suitable Javascript catch handler. 971 if (it.done()) return; // No suitable Javascript catch handler.
970 972
971 FloodWithOneShot(Handle<JSFunction>(it.frame()->function())); 973 FloodWithOneShot(Handle<JSFunction>(it.frame()->function()));
972 } 974 }
973 975
974 976
975 void Debug::PrepareStep(StepAction step_action) { 977 void Debug::PrepareStep(StepAction step_action) {
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
1015 return; 1017 return;
1016 } 1018 }
1017 1019
1018 Handle<DebugInfo> debug_info(shared->GetDebugInfo()); 1020 Handle<DebugInfo> debug_info(shared->GetDebugInfo());
1019 BreakLocation location = BreakLocation::FromFrame(debug_info, frame); 1021 BreakLocation location = BreakLocation::FromFrame(debug_info, frame);
1020 1022
1021 // Any step at a return is a step-out. 1023 // Any step at a return is a step-out.
1022 if (location.IsReturn()) step_action = StepOut; 1024 if (location.IsReturn()) step_action = StepOut;
1023 // A step-next at a tail call is a step-out. 1025 // A step-next at a tail call is a step-out.
1024 if (location.IsTailCall() && step_action == StepNext) step_action = StepOut; 1026 if (location.IsTailCall() && step_action == StepNext) step_action = StepOut;
1027 // A step-next in blackboxed function is a step-out.
1028 if (step_action == StepNext && shared->DebugIsBlackboxed()) {
1029 step_action = StepOut;
1030 }
1025 1031
1026 thread_local_.last_statement_position_ = 1032 thread_local_.last_statement_position_ =
1027 summary.abstract_code()->SourceStatementPosition(summary.code_offset()); 1033 summary.abstract_code()->SourceStatementPosition(summary.code_offset());
1028 thread_local_.last_fp_ = frame->UnpaddedFP(); 1034 thread_local_.last_fp_ = frame->UnpaddedFP();
1029 // No longer perform the current async step. 1035 // No longer perform the current async step.
1030 clear_suspended_generator(); 1036 clear_suspended_generator();
1031 1037
1032 switch (step_action) { 1038 switch (step_action) {
1033 case StepNone: 1039 case StepNone:
1034 UNREACHABLE(); 1040 UNREACHABLE();
1035 break; 1041 break;
1036 case StepOut: 1042 case StepOut:
1037 // Advance to caller frame. 1043 // Advance to caller frame.
1038 frames_it.Advance(); 1044 frames_it.Advance();
1039 // Skip native and extension functions on the stack. 1045 // Skip native and extension functions on the stack.
1040 while (!frames_it.done() && 1046 while (
1041 !frames_it.frame()->function()->shared()->IsSubjectToDebugging()) { 1047 !frames_it.done() &&
1048 (!frames_it.frame()->function()->shared()->IsSubjectToDebugging() ||
1049 frames_it.frame()->function()->shared()->DebugIsBlackboxed())) {
1042 // Builtin functions are not subject to stepping, but need to be 1050 // Builtin functions are not subject to stepping, but need to be
1043 // deoptimized to include checks for step-in at call sites. 1051 // deoptimized to include checks for step-in at call sites.
1044 Deoptimizer::DeoptimizeFunction(frames_it.frame()->function()); 1052 Deoptimizer::DeoptimizeFunction(frames_it.frame()->function());
1045 frames_it.Advance(); 1053 frames_it.Advance();
1046 } 1054 }
1047 if (!frames_it.done()) { 1055 if (!frames_it.done()) {
1048 // Fill the caller function to return to with one-shot break points. 1056 // Fill the caller function to return to with one-shot break points.
1049 Handle<JSFunction> caller_function(frames_it.frame()->function()); 1057 Handle<JSFunction> caller_function(frames_it.frame()->function());
1050 FloodWithOneShot(caller_function); 1058 FloodWithOneShot(caller_function);
1051 thread_local_.target_fp_ = frames_it.frame()->UnpaddedFP(); 1059 thread_local_.target_fp_ = frames_it.frame()->UnpaddedFP();
(...skipping 695 matching lines...) Expand 10 before | Expand all | Expand 10 after
1747 // Bail out if exception breaks are not active 1755 // Bail out if exception breaks are not active
1748 if (uncaught) { 1756 if (uncaught) {
1749 // Uncaught exceptions are reported by either flags. 1757 // Uncaught exceptions are reported by either flags.
1750 if (!(break_on_uncaught_exception_ || break_on_exception_)) return; 1758 if (!(break_on_uncaught_exception_ || break_on_exception_)) return;
1751 } else { 1759 } else {
1752 // Caught exceptions are reported is activated. 1760 // Caught exceptions are reported is activated.
1753 if (!break_on_exception_) return; 1761 if (!break_on_exception_) return;
1754 } 1762 }
1755 1763
1756 { 1764 {
1757 // Check whether the break location is muted.
1758 JavaScriptFrameIterator it(isolate_); 1765 JavaScriptFrameIterator it(isolate_);
1759 if (!it.done() && IsMutedAtCurrentLocation(it.frame())) return; 1766 // Check whether the top frame is blackboxed or the break location is muted.
1767 if (!it.done() && (it.frame()->function()->shared()->DebugIsBlackboxed() ||
1768 IsMutedAtCurrentLocation(it.frame()))) {
1769 return;
1770 }
1760 } 1771 }
1761 1772
1762 DebugScope debug_scope(this); 1773 DebugScope debug_scope(this);
1763 if (debug_scope.failed()) return; 1774 if (debug_scope.failed()) return;
1764 1775
1765 if (debug_event_listener_) { 1776 if (debug_delegate_) {
1766 HandleScope scope(isolate_); 1777 HandleScope scope(isolate_);
1767 1778
1768 // Create the execution state. 1779 // Create the execution state.
1769 Handle<Object> exec_state; 1780 Handle<Object> exec_state;
1770 // Bail out and don't call debugger if exception. 1781 // Bail out and don't call debugger if exception.
1771 if (!MakeExecutionState().ToHandle(&exec_state)) return; 1782 if (!MakeExecutionState().ToHandle(&exec_state)) return;
1772 1783
1773 debug_event_listener_->ExceptionThrown( 1784 debug_delegate_->ExceptionThrown(
1774 GetDebugEventContext(isolate_), 1785 GetDebugEventContext(isolate_),
1775 v8::Utils::ToLocal(Handle<JSObject>::cast(exec_state)), 1786 v8::Utils::ToLocal(Handle<JSObject>::cast(exec_state)),
1776 v8::Utils::ToLocal(exception), promise->IsJSObject(), uncaught); 1787 v8::Utils::ToLocal(exception), promise->IsJSObject(), uncaught);
1777 if (!non_inspector_listener_exists()) return; 1788 if (!non_inspector_listener_exists()) return;
1778 } 1789 }
1779 1790
1780 // Create the event data object. 1791 // Create the event data object.
1781 Handle<Object> event_data; 1792 Handle<Object> event_data;
1782 // Bail out and don't call debugger if exception. 1793 // Bail out and don't call debugger if exception.
1783 if (!MakeExceptionEvent( 1794 if (!MakeExceptionEvent(
1784 exception, uncaught, promise).ToHandle(&event_data)) { 1795 exception, uncaught, promise).ToHandle(&event_data)) {
1785 return; 1796 return;
1786 } 1797 }
1787 1798
1788 // Process debug event. 1799 // Process debug event.
1789 ProcessDebugEvent(v8::Exception, Handle<JSObject>::cast(event_data), false); 1800 ProcessDebugEvent(v8::Exception, Handle<JSObject>::cast(event_data), false);
1790 // Return to continue execution from where the exception was thrown. 1801 // Return to continue execution from where the exception was thrown.
1791 } 1802 }
1792 1803
1793 void Debug::OnDebugBreak(Handle<Object> break_points_hit, bool auto_continue) { 1804 void Debug::OnDebugBreak(Handle<Object> break_points_hit, bool auto_continue) {
1794 // The caller provided for DebugScope. 1805 // The caller provided for DebugScope.
1795 AssertDebugContext(); 1806 AssertDebugContext();
1796 // Bail out if there is no listener for this event 1807 // Bail out if there is no listener for this event
1797 if (ignore_events()) return; 1808 if (ignore_events()) return;
1798 1809
1799 #ifdef DEBUG 1810 #ifdef DEBUG
1800 PrintBreakLocation(); 1811 PrintBreakLocation();
1801 #endif // DEBUG 1812 #endif // DEBUG
1802 1813
1803 if (debug_event_listener_) { 1814 if (debug_delegate_) {
1804 HandleScope scope(isolate_); 1815 HandleScope scope(isolate_);
1805 1816
1806 // Create the execution state. 1817 // Create the execution state.
1807 Handle<Object> exec_state; 1818 Handle<Object> exec_state;
1808 // Bail out and don't call debugger if exception. 1819 // Bail out and don't call debugger if exception.
1809 if (!MakeExecutionState().ToHandle(&exec_state)) return; 1820 if (!MakeExecutionState().ToHandle(&exec_state)) return;
1810 1821
1811 bool previous = in_debug_event_listener_; 1822 bool previous = in_debug_event_listener_;
1812 in_debug_event_listener_ = true; 1823 in_debug_event_listener_ = true;
1813 debug_event_listener_->BreakProgramRequested( 1824 debug_delegate_->BreakProgramRequested(
1814 GetDebugEventContext(isolate_), 1825 GetDebugEventContext(isolate_),
1815 v8::Utils::ToLocal(Handle<JSObject>::cast(exec_state)), 1826 v8::Utils::ToLocal(Handle<JSObject>::cast(exec_state)),
1816 v8::Utils::ToLocal(break_points_hit)); 1827 v8::Utils::ToLocal(break_points_hit));
1817 in_debug_event_listener_ = previous; 1828 in_debug_event_listener_ = previous;
1818 if (!non_inspector_listener_exists()) return; 1829 if (!non_inspector_listener_exists()) return;
1819 } 1830 }
1820 1831
1821 HandleScope scope(isolate_); 1832 HandleScope scope(isolate_);
1822 // Create the event data object. 1833 // Create the event data object.
1823 Handle<Object> event_data; 1834 Handle<Object> event_data;
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
1888 // Since we holding promise when at least one microtask is scheduled (inside 1899 // Since we holding promise when at least one microtask is scheduled (inside
1889 // PromiseReactionJobInfo), we can send cancel event in weak callback. 1900 // PromiseReactionJobInfo), we can send cancel event in weak callback.
1890 GlobalHandles::MakeWeak( 1901 GlobalHandles::MakeWeak(
1891 global_handle.location(), 1902 global_handle.location(),
1892 new CollectedCallbackData(global_handle.location(), async_id->value(), 1903 new CollectedCallbackData(global_handle.location(), async_id->value(),
1893 this, isolate_), 1904 this, isolate_),
1894 &ResetPromiseHandle, v8::WeakCallbackType::kParameter); 1905 &ResetPromiseHandle, v8::WeakCallbackType::kParameter);
1895 return async_id->value(); 1906 return async_id->value();
1896 } 1907 }
1897 1908
1909 namespace {
1910 debug::Location GetDebugLocation(Handle<Script> script, int source_position) {
1911 Script::PositionInfo info;
1912 Script::GetPositionInfo(script, source_position, &info, Script::WITH_OFFSET);
1913 return debug::Location(info.line, info.column);
1914 }
1915 } // namespace
1916
1917 bool Debug::IsBlackboxed(Handle<SharedFunctionInfo> shared) {
1918 if (!debug_delegate_) return false;
1919 if (!shared->script()->IsScript()) return false;
1920 Handle<Script> script(Script::cast(shared->script()));
1921 if (script->type() != i::Script::TYPE_NORMAL) return false;
1922 debug::Location start = GetDebugLocation(script, shared->start_position());
1923 debug::Location end = GetDebugLocation(script, shared->end_position());
1924 return debug_delegate_->IsBlackboxed(ToApiHandle<debug::Script>(script),
1925 start, end);
1926 }
1927
1898 void Debug::OnAsyncTaskEvent(debug::PromiseDebugActionType type, int id) { 1928 void Debug::OnAsyncTaskEvent(debug::PromiseDebugActionType type, int id) {
1899 if (in_debug_scope() || ignore_events()) return; 1929 if (in_debug_scope() || ignore_events()) return;
1900 1930
1901 if (debug_event_listener_) { 1931 if (debug_delegate_) {
1902 debug_event_listener_->PromiseEventOccurred(type, id); 1932 debug_delegate_->PromiseEventOccurred(type, id);
1903 if (!non_inspector_listener_exists()) return; 1933 if (!non_inspector_listener_exists()) return;
1904 } 1934 }
1905 1935
1906 HandleScope scope(isolate_); 1936 HandleScope scope(isolate_);
1907 DebugScope debug_scope(this); 1937 DebugScope debug_scope(this);
1908 if (debug_scope.failed()) return; 1938 if (debug_scope.failed()) return;
1909 1939
1910 // Create the script collected state object. 1940 // Create the script collected state object.
1911 Handle<Object> event_data; 1941 Handle<Object> event_data;
1912 // Bail out and don't call debugger if exception. 1942 // Bail out and don't call debugger if exception.
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
1983 if (ignore_events()) return; 2013 if (ignore_events()) return;
1984 if (script->type() != i::Script::TYPE_NORMAL && 2014 if (script->type() != i::Script::TYPE_NORMAL &&
1985 script->type() != i::Script::TYPE_WASM) { 2015 script->type() != i::Script::TYPE_WASM) {
1986 return; 2016 return;
1987 } 2017 }
1988 SuppressDebug while_processing(this); 2018 SuppressDebug while_processing(this);
1989 bool in_nested_debug_scope = in_debug_scope(); 2019 bool in_nested_debug_scope = in_debug_scope();
1990 DebugScope debug_scope(this); 2020 DebugScope debug_scope(this);
1991 if (debug_scope.failed()) return; 2021 if (debug_scope.failed()) return;
1992 2022
1993 if (debug_event_listener_) { 2023 if (debug_delegate_) {
1994 debug_event_listener_->ScriptCompiled(ToApiHandle<debug::Script>(script), 2024 debug_delegate_->ScriptCompiled(ToApiHandle<debug::Script>(script),
1995 event != v8::AfterCompile); 2025 event != v8::AfterCompile);
1996 if (!non_inspector_listener_exists()) return; 2026 if (!non_inspector_listener_exists()) return;
1997 } 2027 }
1998 2028
1999 HandleScope scope(isolate_); 2029 HandleScope scope(isolate_);
2000 // Create the compile state object. 2030 // Create the compile state object.
2001 Handle<Object> event_data; 2031 Handle<Object> event_data;
2002 // Bail out and don't call debugger if exception. 2032 // Bail out and don't call debugger if exception.
2003 if (!MakeCompileEvent(script, event).ToHandle(&event_data)) return; 2033 if (!MakeCompileEvent(script, event).ToHandle(&event_data)) return;
2004 2034
2005 // Don't call NotifyMessageHandler if already in debug scope to avoid running 2035 // Don't call NotifyMessageHandler if already in debug scope to avoid running
(...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after
2181 void Debug::SetMessageHandler(v8::Debug::MessageHandler handler) { 2211 void Debug::SetMessageHandler(v8::Debug::MessageHandler handler) {
2182 message_handler_ = handler; 2212 message_handler_ = handler;
2183 UpdateState(); 2213 UpdateState();
2184 if (handler == NULL && in_debug_scope()) { 2214 if (handler == NULL && in_debug_scope()) {
2185 // Send an empty command to the debugger if in a break to make JavaScript 2215 // Send an empty command to the debugger if in a break to make JavaScript
2186 // run again if the debugger is closed. 2216 // run again if the debugger is closed.
2187 EnqueueCommandMessage(Vector<const uint16_t>::empty()); 2217 EnqueueCommandMessage(Vector<const uint16_t>::empty());
2188 } 2218 }
2189 } 2219 }
2190 2220
2191 void Debug::SetDebugEventListener(debug::DebugEventListener* listener) { 2221 void Debug::SetDebugDelegate(debug::DebugDelegate* delegate) {
2192 debug_event_listener_ = listener; 2222 debug_delegate_ = delegate;
2193 UpdateState(); 2223 UpdateState();
2194 } 2224 }
2195 2225
2196 void Debug::UpdateState() { 2226 void Debug::UpdateState() {
2197 bool is_active = message_handler_ != nullptr || !event_listener_.is_null() || 2227 bool is_active = message_handler_ != nullptr || !event_listener_.is_null() ||
2198 debug_event_listener_ != nullptr; 2228 debug_delegate_ != nullptr;
2199 if (is_active || in_debug_scope()) { 2229 if (is_active || in_debug_scope()) {
2200 // Note that the debug context could have already been loaded to 2230 // Note that the debug context could have already been loaded to
2201 // bootstrap test cases. 2231 // bootstrap test cases.
2202 isolate_->compilation_cache()->Disable(); 2232 isolate_->compilation_cache()->Disable();
2203 is_active = Load(); 2233 is_active = Load();
2204 } else if (is_loaded()) { 2234 } else if (is_loaded()) {
2205 isolate_->compilation_cache()->Enable(); 2235 isolate_->compilation_cache()->Enable();
2206 Unload(); 2236 Unload();
2207 } 2237 }
2208 is_active_ = is_active; 2238 is_active_ = is_active;
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
2270 2300
2271 StackLimitCheck check(isolate_); 2301 StackLimitCheck check(isolate_);
2272 if (check.HasOverflowed()) return; 2302 if (check.HasOverflowed()) return;
2273 2303
2274 { JavaScriptFrameIterator it(isolate_); 2304 { JavaScriptFrameIterator it(isolate_);
2275 DCHECK(!it.done()); 2305 DCHECK(!it.done());
2276 Object* fun = it.frame()->function(); 2306 Object* fun = it.frame()->function();
2277 if (fun && fun->IsJSFunction()) { 2307 if (fun && fun->IsJSFunction()) {
2278 // Don't stop in builtin functions. 2308 // Don't stop in builtin functions.
2279 if (!JSFunction::cast(fun)->shared()->IsSubjectToDebugging()) return; 2309 if (!JSFunction::cast(fun)->shared()->IsSubjectToDebugging()) return;
2310 if (isolate_->stack_guard()->CheckDebugBreak() &&
2311 JSFunction::cast(fun)->shared()->DebugIsBlackboxed()) {
2312 Deoptimizer::DeoptimizeFunction(JSFunction::cast(fun));
2313 return;
2314 }
2280 JSGlobalObject* global = 2315 JSGlobalObject* global =
2281 JSFunction::cast(fun)->context()->global_object(); 2316 JSFunction::cast(fun)->context()->global_object();
2282 // Don't stop in debugger functions. 2317 // Don't stop in debugger functions.
2283 if (IsDebugGlobal(global)) return; 2318 if (IsDebugGlobal(global)) return;
2284 // Don't stop if the break location is muted. 2319 // Don't stop if the break location is muted.
2285 if (IsMutedAtCurrentLocation(it.frame())) return; 2320 if (IsMutedAtCurrentLocation(it.frame())) return;
2286 } 2321 }
2287 } 2322 }
2288 2323
2289 // Collect the break state before clearing the flags. 2324 // Collect the break state before clearing the flags.
(...skipping 375 matching lines...) Expand 10 before | Expand all | Expand 10 after
2665 logger_->DebugEvent("Put", message.text()); 2700 logger_->DebugEvent("Put", message.text());
2666 } 2701 }
2667 2702
2668 void LockingCommandMessageQueue::Clear() { 2703 void LockingCommandMessageQueue::Clear() {
2669 base::LockGuard<base::Mutex> lock_guard(&mutex_); 2704 base::LockGuard<base::Mutex> lock_guard(&mutex_);
2670 queue_.Clear(); 2705 queue_.Clear();
2671 } 2706 }
2672 2707
2673 } // namespace internal 2708 } // namespace internal
2674 } // namespace v8 2709 } // namespace v8
OLDNEW
« no previous file with comments | « src/debug/debug.h ('k') | src/debug/debug-interface.h » ('j') | src/objects.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698