Chromium Code Reviews| 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 825 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 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 Loading... | |
| 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())) { | |
|
dgozman
2017/01/19 21:49:14
Should we make IsSubjectToDebugging() to check for
kozy
2017/01/20 02:32:37
Acknowledged.
Yang
2017/01/20 09:30:48
I think the reason we don't is because we want bla
| |
| 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 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1030 clear_suspended_generator(); | 1032 clear_suspended_generator(); |
| 1031 | 1033 |
| 1032 switch (step_action) { | 1034 switch (step_action) { |
| 1033 case StepNone: | 1035 case StepNone: |
| 1034 UNREACHABLE(); | 1036 UNREACHABLE(); |
| 1035 break; | 1037 break; |
| 1036 case StepOut: | 1038 case StepOut: |
| 1037 // Advance to caller frame. | 1039 // Advance to caller frame. |
| 1038 frames_it.Advance(); | 1040 frames_it.Advance(); |
| 1039 // Skip native and extension functions on the stack. | 1041 // Skip native and extension functions on the stack. |
| 1040 while (!frames_it.done() && | 1042 while ( |
| 1041 !frames_it.frame()->function()->shared()->IsSubjectToDebugging()) { | 1043 !frames_it.done() && |
| 1044 (!frames_it.frame()->function()->shared()->IsSubjectToDebugging() || | |
| 1045 frames_it.frame()->function()->shared()->DebugIsBlackboxed())) { | |
| 1042 // Builtin functions are not subject to stepping, but need to be | 1046 // Builtin functions are not subject to stepping, but need to be |
| 1043 // deoptimized to include checks for step-in at call sites. | 1047 // deoptimized to include checks for step-in at call sites. |
| 1044 Deoptimizer::DeoptimizeFunction(frames_it.frame()->function()); | 1048 Deoptimizer::DeoptimizeFunction(frames_it.frame()->function()); |
| 1045 frames_it.Advance(); | 1049 frames_it.Advance(); |
| 1046 } | 1050 } |
| 1047 if (!frames_it.done()) { | 1051 if (!frames_it.done()) { |
| 1048 // Fill the caller function to return to with one-shot break points. | 1052 // Fill the caller function to return to with one-shot break points. |
| 1049 Handle<JSFunction> caller_function(frames_it.frame()->function()); | 1053 Handle<JSFunction> caller_function(frames_it.frame()->function()); |
| 1050 FloodWithOneShot(caller_function); | 1054 FloodWithOneShot(caller_function); |
| 1051 thread_local_.target_fp_ = frames_it.frame()->UnpaddedFP(); | 1055 thread_local_.target_fp_ = frames_it.frame()->UnpaddedFP(); |
| (...skipping 695 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1747 // Bail out if exception breaks are not active | 1751 // Bail out if exception breaks are not active |
| 1748 if (uncaught) { | 1752 if (uncaught) { |
| 1749 // Uncaught exceptions are reported by either flags. | 1753 // Uncaught exceptions are reported by either flags. |
| 1750 if (!(break_on_uncaught_exception_ || break_on_exception_)) return; | 1754 if (!(break_on_uncaught_exception_ || break_on_exception_)) return; |
| 1751 } else { | 1755 } else { |
| 1752 // Caught exceptions are reported is activated. | 1756 // Caught exceptions are reported is activated. |
| 1753 if (!break_on_exception_) return; | 1757 if (!break_on_exception_) return; |
| 1754 } | 1758 } |
| 1755 | 1759 |
| 1756 { | 1760 { |
| 1757 // Check whether the break location is muted. | |
| 1758 JavaScriptFrameIterator it(isolate_); | 1761 JavaScriptFrameIterator it(isolate_); |
| 1759 if (!it.done() && IsMutedAtCurrentLocation(it.frame())) return; | 1762 // Check whether the top frame is blackboxed or the break location is muted. |
| 1763 if (!it.done() && (it.frame()->function()->shared()->DebugIsBlackboxed() || | |
| 1764 IsMutedAtCurrentLocation(it.frame()))) { | |
| 1765 return; | |
| 1766 } | |
| 1760 } | 1767 } |
| 1761 | 1768 |
| 1762 DebugScope debug_scope(this); | 1769 DebugScope debug_scope(this); |
| 1763 if (debug_scope.failed()) return; | 1770 if (debug_scope.failed()) return; |
| 1764 | 1771 |
| 1765 if (debug_event_listener_) { | 1772 if (debug_event_listener_) { |
| 1766 HandleScope scope(isolate_); | 1773 HandleScope scope(isolate_); |
| 1767 | 1774 |
| 1768 // Create the execution state. | 1775 // Create the execution state. |
| 1769 Handle<Object> exec_state; | 1776 Handle<Object> exec_state; |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1888 // Since we holding promise when at least one microtask is scheduled (inside | 1895 // Since we holding promise when at least one microtask is scheduled (inside |
| 1889 // PromiseReactionJobInfo), we can send cancel event in weak callback. | 1896 // PromiseReactionJobInfo), we can send cancel event in weak callback. |
| 1890 GlobalHandles::MakeWeak( | 1897 GlobalHandles::MakeWeak( |
| 1891 global_handle.location(), | 1898 global_handle.location(), |
| 1892 new CollectedCallbackData(global_handle.location(), async_id->value(), | 1899 new CollectedCallbackData(global_handle.location(), async_id->value(), |
| 1893 this, isolate_), | 1900 this, isolate_), |
| 1894 &ResetPromiseHandle, v8::WeakCallbackType::kParameter); | 1901 &ResetPromiseHandle, v8::WeakCallbackType::kParameter); |
| 1895 return async_id->value(); | 1902 return async_id->value(); |
| 1896 } | 1903 } |
| 1897 | 1904 |
| 1905 void Debug::SetIsBlackboxedCallback(debug::IsBlackboxedCallback callback, | |
| 1906 void* data) { | |
| 1907 is_blackboxed_callback_ = callback; | |
| 1908 is_blackboxed_callback_data_ = data; | |
| 1909 } | |
| 1910 | |
| 1911 namespace { | |
| 1912 debug::Location GetDebugLocation(Handle<Script> script, int source_position) { | |
| 1913 Script::InitLineEnds(script); | |
| 1914 int line = Script::GetLineNumber(script, source_position); | |
|
dgozman
2017/01/19 22:34:20
GetPositionInfo
kozy
2017/01/20 02:32:37
Done.
| |
| 1915 int column = Script::GetColumnNumber(script, source_position); | |
| 1916 return debug::Location(line, column); | |
| 1917 } | |
| 1918 } // namespace | |
| 1919 | |
| 1920 bool Debug::IsBlackboxed(Handle<SharedFunctionInfo> shared) { | |
| 1921 if (!is_blackboxed_callback_) return false; | |
| 1922 Handle<Script> script(Script::cast(shared->script())); | |
| 1923 if (script->type() != i::Script::TYPE_NORMAL) return false; | |
| 1924 | |
| 1925 debug::Location start = GetDebugLocation(script, shared->start_position()); | |
| 1926 debug::Location end = GetDebugLocation(script, shared->end_position()); | |
| 1927 | |
| 1928 return is_blackboxed_callback_(ToApiHandle<debug::Script>(script), start, end, | |
| 1929 is_blackboxed_callback_data_); | |
| 1930 } | |
| 1931 | |
| 1898 void Debug::OnAsyncTaskEvent(debug::PromiseDebugActionType type, int id) { | 1932 void Debug::OnAsyncTaskEvent(debug::PromiseDebugActionType type, int id) { |
| 1899 if (in_debug_scope() || ignore_events()) return; | 1933 if (in_debug_scope() || ignore_events()) return; |
| 1900 | 1934 |
| 1901 if (debug_event_listener_) { | 1935 if (debug_event_listener_) { |
| 1902 debug_event_listener_->PromiseEventOccurred(type, id); | 1936 debug_event_listener_->PromiseEventOccurred(type, id); |
| 1903 if (!non_inspector_listener_exists()) return; | 1937 if (!non_inspector_listener_exists()) return; |
| 1904 } | 1938 } |
| 1905 | 1939 |
| 1906 HandleScope scope(isolate_); | 1940 HandleScope scope(isolate_); |
| 1907 DebugScope debug_scope(this); | 1941 DebugScope debug_scope(this); |
| (...skipping 362 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2270 | 2304 |
| 2271 StackLimitCheck check(isolate_); | 2305 StackLimitCheck check(isolate_); |
| 2272 if (check.HasOverflowed()) return; | 2306 if (check.HasOverflowed()) return; |
| 2273 | 2307 |
| 2274 { JavaScriptFrameIterator it(isolate_); | 2308 { JavaScriptFrameIterator it(isolate_); |
| 2275 DCHECK(!it.done()); | 2309 DCHECK(!it.done()); |
| 2276 Object* fun = it.frame()->function(); | 2310 Object* fun = it.frame()->function(); |
| 2277 if (fun && fun->IsJSFunction()) { | 2311 if (fun && fun->IsJSFunction()) { |
| 2278 // Don't stop in builtin functions. | 2312 // Don't stop in builtin functions. |
| 2279 if (!JSFunction::cast(fun)->shared()->IsSubjectToDebugging()) return; | 2313 if (!JSFunction::cast(fun)->shared()->IsSubjectToDebugging()) return; |
| 2314 if (isolate_->stack_guard()->CheckDebugBreak() && | |
| 2315 JSFunction::cast(fun)->shared()->DebugIsBlackboxed()) | |
| 2316 return; | |
| 2280 JSGlobalObject* global = | 2317 JSGlobalObject* global = |
| 2281 JSFunction::cast(fun)->context()->global_object(); | 2318 JSFunction::cast(fun)->context()->global_object(); |
| 2282 // Don't stop in debugger functions. | 2319 // Don't stop in debugger functions. |
| 2283 if (IsDebugGlobal(global)) return; | 2320 if (IsDebugGlobal(global)) return; |
| 2284 // Don't stop if the break location is muted. | 2321 // Don't stop if the break location is muted. |
| 2285 if (IsMutedAtCurrentLocation(it.frame())) return; | 2322 if (IsMutedAtCurrentLocation(it.frame())) return; |
| 2286 } | 2323 } |
| 2287 } | 2324 } |
| 2288 | 2325 |
| 2289 // Collect the break state before clearing the flags. | 2326 // Collect the break state before clearing the flags. |
| (...skipping 377 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2667 logger_->DebugEvent("Put", message.text()); | 2704 logger_->DebugEvent("Put", message.text()); |
| 2668 } | 2705 } |
| 2669 | 2706 |
| 2670 void LockingCommandMessageQueue::Clear() { | 2707 void LockingCommandMessageQueue::Clear() { |
| 2671 base::LockGuard<base::Mutex> lock_guard(&mutex_); | 2708 base::LockGuard<base::Mutex> lock_guard(&mutex_); |
| 2672 queue_.Clear(); | 2709 queue_.Clear(); |
| 2673 } | 2710 } |
| 2674 | 2711 |
| 2675 } // namespace internal | 2712 } // namespace internal |
| 2676 } // namespace v8 | 2713 } // namespace v8 |
| OLD | NEW |