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 |