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 24 matching lines...) Expand all Loading... | |
| 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), | 41 message_handler_(NULL), |
| 42 command_received_(0), | 42 command_received_(0), |
| 43 command_queue_(isolate->logger(), kQueueInitialSize), | 43 command_queue_(isolate->logger(), kQueueInitialSize), |
| 44 is_active_(false), | 44 is_active_(false), |
| 45 hook_on_function_call_(false), | |
| 45 is_suppressed_(false), | 46 is_suppressed_(false), |
| 46 live_edit_enabled_(true), // TODO(yangguo): set to false by default. | 47 live_edit_enabled_(true), // TODO(yangguo): set to false by default. |
| 47 break_disabled_(false), | 48 break_disabled_(false), |
| 48 break_points_active_(true), | 49 break_points_active_(true), |
| 49 in_debug_event_listener_(false), | 50 in_debug_event_listener_(false), |
| 50 break_on_exception_(false), | 51 break_on_exception_(false), |
| 51 break_on_uncaught_exception_(false), | 52 break_on_uncaught_exception_(false), |
| 53 needs_readonly_check_(false), | |
| 54 readonly_check_failed_(false), | |
| 52 debug_info_list_(NULL), | 55 debug_info_list_(NULL), |
| 53 feature_tracker_(isolate), | 56 feature_tracker_(isolate), |
| 54 isolate_(isolate) { | 57 isolate_(isolate) { |
| 55 ThreadInit(); | 58 ThreadInit(); |
| 56 } | 59 } |
| 57 | 60 |
| 58 BreakLocation BreakLocation::FromFrame(Handle<DebugInfo> debug_info, | 61 BreakLocation BreakLocation::FromFrame(Handle<DebugInfo> debug_info, |
| 59 JavaScriptFrame* frame) { | 62 JavaScriptFrame* frame) { |
| 60 FrameSummary summary = FrameSummary::GetFirst(frame); | 63 FrameSummary summary = FrameSummary::GetFirst(frame); |
| 61 int offset = summary.code_offset(); | 64 int offset = summary.code_offset(); |
| (...skipping 336 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 398 thread_local_.break_frame_id_ = StackFrame::NO_ID; | 401 thread_local_.break_frame_id_ = StackFrame::NO_ID; |
| 399 thread_local_.last_step_action_ = StepNone; | 402 thread_local_.last_step_action_ = StepNone; |
| 400 thread_local_.last_statement_position_ = kNoSourcePosition; | 403 thread_local_.last_statement_position_ = kNoSourcePosition; |
| 401 thread_local_.last_fp_ = 0; | 404 thread_local_.last_fp_ = 0; |
| 402 thread_local_.target_fp_ = 0; | 405 thread_local_.target_fp_ = 0; |
| 403 thread_local_.return_value_ = Handle<Object>(); | 406 thread_local_.return_value_ = Handle<Object>(); |
| 404 clear_suspended_generator(); | 407 clear_suspended_generator(); |
| 405 // TODO(isolates): frames_are_dropped_? | 408 // TODO(isolates): frames_are_dropped_? |
| 406 base::NoBarrier_Store(&thread_local_.current_debug_scope_, | 409 base::NoBarrier_Store(&thread_local_.current_debug_scope_, |
| 407 static_cast<base::AtomicWord>(0)); | 410 static_cast<base::AtomicWord>(0)); |
| 411 UpdateHookOnFunctionCall(); | |
| 408 } | 412 } |
| 409 | 413 |
| 410 | 414 |
| 411 char* Debug::ArchiveDebug(char* storage) { | 415 char* Debug::ArchiveDebug(char* storage) { |
| 412 // Simply reset state. Don't archive anything. | 416 // Simply reset state. Don't archive anything. |
| 413 ThreadInit(); | 417 ThreadInit(); |
| 414 return storage + ArchiveSpacePerThread(); | 418 return storage + ArchiveSpacePerThread(); |
| 415 } | 419 } |
| 416 | 420 |
| 417 | 421 |
| (...skipping 479 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 897 if (type == BreakUncaughtException) { | 901 if (type == BreakUncaughtException) { |
| 898 return break_on_uncaught_exception_; | 902 return break_on_uncaught_exception_; |
| 899 } else { | 903 } else { |
| 900 return break_on_exception_; | 904 return break_on_exception_; |
| 901 } | 905 } |
| 902 } | 906 } |
| 903 | 907 |
| 904 | 908 |
| 905 void Debug::PrepareStepIn(Handle<JSFunction> function) { | 909 void Debug::PrepareStepIn(Handle<JSFunction> function) { |
| 906 CHECK(last_step_action() >= StepIn); | 910 CHECK(last_step_action() >= StepIn); |
| 907 if (!is_active()) return; | 911 if (ignore_events()) return; |
| 908 if (in_debug_scope()) return; | 912 if (in_debug_scope()) return; |
| 913 if (break_disabled()) return; | |
| 909 FloodWithOneShot(function); | 914 FloodWithOneShot(function); |
| 910 } | 915 } |
| 911 | 916 |
| 912 void Debug::PrepareStepInSuspendedGenerator() { | 917 void Debug::PrepareStepInSuspendedGenerator() { |
| 913 CHECK(has_suspended_generator()); | 918 CHECK(has_suspended_generator()); |
| 914 if (!is_active()) return; | 919 if (ignore_events()) return; |
| 915 if (in_debug_scope()) return; | 920 if (in_debug_scope()) return; |
| 921 if (break_disabled()) return; | |
| 916 thread_local_.last_step_action_ = StepIn; | 922 thread_local_.last_step_action_ = StepIn; |
| 923 UpdateHookOnFunctionCall(); | |
| 917 Handle<JSFunction> function( | 924 Handle<JSFunction> function( |
| 918 JSGeneratorObject::cast(thread_local_.suspended_generator_)->function()); | 925 JSGeneratorObject::cast(thread_local_.suspended_generator_)->function()); |
| 919 FloodWithOneShot(function); | 926 FloodWithOneShot(function); |
| 920 clear_suspended_generator(); | 927 clear_suspended_generator(); |
| 921 } | 928 } |
| 922 | 929 |
| 923 void Debug::PrepareStepOnThrow() { | 930 void Debug::PrepareStepOnThrow() { |
| 924 if (!is_active()) return; | |
| 925 if (last_step_action() == StepNone) return; | 931 if (last_step_action() == StepNone) return; |
| 932 if (ignore_events()) return; | |
| 926 if (in_debug_scope()) return; | 933 if (in_debug_scope()) return; |
| 934 if (break_disabled()) return; | |
| 927 | 935 |
| 928 ClearOneShot(); | 936 ClearOneShot(); |
| 929 | 937 |
| 930 // Iterate through the JavaScript stack looking for handlers. | 938 // Iterate through the JavaScript stack looking for handlers. |
| 931 JavaScriptFrameIterator it(isolate_); | 939 JavaScriptFrameIterator it(isolate_); |
| 932 while (!it.done()) { | 940 while (!it.done()) { |
| 933 JavaScriptFrame* frame = it.frame(); | 941 JavaScriptFrame* frame = it.frame(); |
| 934 if (frame->LookupExceptionHandlerInTable(nullptr, nullptr) > 0) break; | 942 if (frame->LookupExceptionHandlerInTable(nullptr, nullptr) > 0) break; |
| 935 it.Advance(); | 943 it.Advance(); |
| 936 } | 944 } |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 967 StackFrame::Id frame_id = break_frame_id(); | 975 StackFrame::Id frame_id = break_frame_id(); |
| 968 // If there is no JavaScript stack don't do anything. | 976 // If there is no JavaScript stack don't do anything. |
| 969 if (frame_id == StackFrame::NO_ID) return; | 977 if (frame_id == StackFrame::NO_ID) return; |
| 970 | 978 |
| 971 JavaScriptFrameIterator frames_it(isolate_, frame_id); | 979 JavaScriptFrameIterator frames_it(isolate_, frame_id); |
| 972 JavaScriptFrame* frame = frames_it.frame(); | 980 JavaScriptFrame* frame = frames_it.frame(); |
| 973 | 981 |
| 974 feature_tracker()->Track(DebugFeatureTracker::kStepping); | 982 feature_tracker()->Track(DebugFeatureTracker::kStepping); |
| 975 | 983 |
| 976 thread_local_.last_step_action_ = step_action; | 984 thread_local_.last_step_action_ = step_action; |
| 985 UpdateHookOnFunctionCall(); | |
| 977 | 986 |
| 978 // If the function on the top frame is unresolved perform step out. This will | 987 // If the function on the top frame is unresolved perform step out. This will |
| 979 // be the case when calling unknown function and having the debugger stopped | 988 // be the case when calling unknown function and having the debugger stopped |
| 980 // in an unhandled exception. | 989 // in an unhandled exception. |
| 981 if (!frame->function()->IsJSFunction()) { | 990 if (!frame->function()->IsJSFunction()) { |
| 982 // Step out: Find the calling JavaScript frame and flood it with | 991 // Step out: Find the calling JavaScript frame and flood it with |
| 983 // breakpoints. | 992 // breakpoints. |
| 984 frames_it.Advance(); | 993 frames_it.Advance(); |
| 985 // Fill the function to return to with one-shot break points. | 994 // Fill the function to return to with one-shot break points. |
| 986 JSFunction* function = frames_it.frame()->function(); | 995 JSFunction* function = frames_it.frame()->function(); |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1097 } | 1106 } |
| 1098 | 1107 |
| 1099 void Debug::ClearStepping() { | 1108 void Debug::ClearStepping() { |
| 1100 // Clear the various stepping setup. | 1109 // Clear the various stepping setup. |
| 1101 ClearOneShot(); | 1110 ClearOneShot(); |
| 1102 | 1111 |
| 1103 thread_local_.last_step_action_ = StepNone; | 1112 thread_local_.last_step_action_ = StepNone; |
| 1104 thread_local_.last_statement_position_ = kNoSourcePosition; | 1113 thread_local_.last_statement_position_ = kNoSourcePosition; |
| 1105 thread_local_.last_fp_ = 0; | 1114 thread_local_.last_fp_ = 0; |
| 1106 thread_local_.target_fp_ = 0; | 1115 thread_local_.target_fp_ = 0; |
| 1116 UpdateHookOnFunctionCall(); | |
| 1107 } | 1117 } |
| 1108 | 1118 |
| 1109 | 1119 |
| 1110 // Clears all the one-shot break points that are currently set. Normally this | 1120 // Clears all the one-shot break points that are currently set. Normally this |
| 1111 // function is called each time a break point is hit as one shot break points | 1121 // function is called each time a break point is hit as one shot break points |
| 1112 // are used to support stepping. | 1122 // are used to support stepping. |
| 1113 void Debug::ClearOneShot() { | 1123 void Debug::ClearOneShot() { |
| 1114 // The current implementation just runs through all the breakpoints. When the | 1124 // The current implementation just runs through all the breakpoints. When the |
| 1115 // last break point for a function is removed that function is automatically | 1125 // last break point for a function is removed that function is automatically |
| 1116 // removed from the list. | 1126 // removed from the list. |
| (...skipping 954 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2071 // bootstrap test cases. | 2081 // bootstrap test cases. |
| 2072 isolate_->compilation_cache()->Disable(); | 2082 isolate_->compilation_cache()->Disable(); |
| 2073 is_active = Load(); | 2083 is_active = Load(); |
| 2074 } else if (is_loaded()) { | 2084 } else if (is_loaded()) { |
| 2075 isolate_->compilation_cache()->Enable(); | 2085 isolate_->compilation_cache()->Enable(); |
| 2076 Unload(); | 2086 Unload(); |
| 2077 } | 2087 } |
| 2078 is_active_ = is_active; | 2088 is_active_ = is_active; |
| 2079 } | 2089 } |
| 2080 | 2090 |
| 2091 void Debug::UpdateHookOnFunctionCall() { | |
| 2092 hook_on_function_call_ = | |
| 2093 thread_local_.last_step_action_ >= StepIn || needs_readonly_check_; | |
| 2094 } | |
| 2095 | |
| 2081 // Calls the registered debug message handler. This callback is part of the | 2096 // Calls the registered debug message handler. This callback is part of the |
| 2082 // public API. | 2097 // public API. |
| 2083 void Debug::InvokeMessageHandler(MessageImpl message) { | 2098 void Debug::InvokeMessageHandler(MessageImpl message) { |
| 2084 if (message_handler_ != NULL) message_handler_(message); | 2099 if (message_handler_ != NULL) message_handler_(message); |
| 2085 } | 2100 } |
| 2086 | 2101 |
| 2087 // Puts a command coming from the public API on the queue. Creates | 2102 // Puts a command coming from the public API on the queue. Creates |
| 2088 // a copy of the command string managed by the debugger. Up to this | 2103 // a copy of the command string managed by the debugger. Up to this |
| 2089 // point, the command data was managed by the API client. Called | 2104 // point, the command data was managed by the API client. Called |
| 2090 // by the API client thread. | 2105 // by the API client thread. |
| (...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2268 reinterpret_cast<base::AtomicWord>(prev_)); | 2283 reinterpret_cast<base::AtomicWord>(prev_)); |
| 2269 | 2284 |
| 2270 // Restore to the previous break state. | 2285 // Restore to the previous break state. |
| 2271 debug_->thread_local_.break_frame_id_ = break_frame_id_; | 2286 debug_->thread_local_.break_frame_id_ = break_frame_id_; |
| 2272 debug_->thread_local_.break_id_ = break_id_; | 2287 debug_->thread_local_.break_id_ = break_id_; |
| 2273 debug_->thread_local_.return_value_ = return_value_; | 2288 debug_->thread_local_.return_value_ = return_value_; |
| 2274 | 2289 |
| 2275 debug_->UpdateState(); | 2290 debug_->UpdateState(); |
| 2276 } | 2291 } |
| 2277 | 2292 |
| 2293 bool Debug::PerformReadOnlyCheck(Handle<JSFunction> function) { | |
| 2294 DCHECK(needs_readonly_check_); | |
| 2295 if (!Compiler::Compile(function, Compiler::KEEP_EXCEPTION)) return false; | |
| 2296 Deoptimizer::DeoptimizeFunction(*function); | |
| 2297 if (!function->shared()->IsReadOnly()) { | |
| 2298 if (FLAG_trace_readonly_debug_evaluate) { | |
| 2299 PrintF("[ro] Function %s failed read-only check.\n", | |
| 2300 function->shared()->DebugName()->ToCString().get()); | |
| 2301 } | |
| 2302 readonly_check_failed_ = true; | |
| 2303 // Throw an uncatchable termination exception. | |
| 2304 isolate_->TerminateExecution(); | |
| 2305 return false; | |
| 2306 } | |
| 2307 return true; | |
| 2308 } | |
| 2309 | |
| 2310 ReadOnlyEvaluate::~ReadOnlyEvaluate() { | |
| 2311 debug_->needs_readonly_check_ = old_state_; | |
| 2312 debug_->UpdateHookOnFunctionCall(); | |
| 2313 Isolate* isolate = debug_->isolate_; | |
| 2314 if (debug_->readonly_check_failed_ && isolate->has_pending_exception() && | |
|
jgruber
2017/01/10 12:46:37
Doesn't readonly_check_failed_ imply the remaining
Yang
2017/01/10 14:14:06
Done.
| |
| 2315 isolate->pending_exception() == | |
| 2316 isolate->heap()->termination_exception()) { | |
| 2317 // Convert the termination exception into a regular exception. | |
| 2318 isolate->CancelTerminateExecution(); | |
| 2319 isolate->Throw(*isolate->factory()->NewEvalError( | |
| 2320 MessageTemplate::kReadOnlyDebugEvaluate)); | |
| 2321 } | |
| 2322 debug_->readonly_check_failed_ = false; | |
| 2323 } | |
| 2324 | |
| 2278 MessageImpl MessageImpl::NewEvent(DebugEvent event, bool running, | 2325 MessageImpl MessageImpl::NewEvent(DebugEvent event, bool running, |
| 2279 Handle<JSObject> exec_state, | 2326 Handle<JSObject> exec_state, |
| 2280 Handle<JSObject> event_data) { | 2327 Handle<JSObject> event_data) { |
| 2281 MessageImpl message(true, event, running, exec_state, event_data, | 2328 MessageImpl message(true, event, running, exec_state, event_data, |
| 2282 Handle<String>(), NULL); | 2329 Handle<String>(), NULL); |
| 2283 return message; | 2330 return message; |
| 2284 } | 2331 } |
| 2285 | 2332 |
| 2286 MessageImpl MessageImpl::NewResponse(DebugEvent event, bool running, | 2333 MessageImpl MessageImpl::NewResponse(DebugEvent event, bool running, |
| 2287 Handle<JSObject> exec_state, | 2334 Handle<JSObject> exec_state, |
| (...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2496 logger_->DebugEvent("Put", message.text()); | 2543 logger_->DebugEvent("Put", message.text()); |
| 2497 } | 2544 } |
| 2498 | 2545 |
| 2499 void LockingCommandMessageQueue::Clear() { | 2546 void LockingCommandMessageQueue::Clear() { |
| 2500 base::LockGuard<base::Mutex> lock_guard(&mutex_); | 2547 base::LockGuard<base::Mutex> lock_guard(&mutex_); |
| 2501 queue_.Clear(); | 2548 queue_.Clear(); |
| 2502 } | 2549 } |
| 2503 | 2550 |
| 2504 } // namespace internal | 2551 } // namespace internal |
| 2505 } // namespace v8 | 2552 } // namespace v8 |
| OLD | NEW |