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

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

Issue 2622863003: [debugger] infrastructure for side-effect-free debug-evaluate. (Closed)
Patch Set: clean ups. 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"
11 #include "src/bootstrapper.h" 11 #include "src/bootstrapper.h"
12 #include "src/code-stubs.h" 12 #include "src/code-stubs.h"
13 #include "src/codegen.h" 13 #include "src/codegen.h"
14 #include "src/compilation-cache.h" 14 #include "src/compilation-cache.h"
15 #include "src/compiler-dispatcher/optimizing-compile-dispatcher.h" 15 #include "src/compiler-dispatcher/optimizing-compile-dispatcher.h"
16 #include "src/compiler.h" 16 #include "src/compiler.h"
17 #include "src/debug/debug-evaluate.h"
17 #include "src/debug/liveedit.h" 18 #include "src/debug/liveedit.h"
18 #include "src/deoptimizer.h" 19 #include "src/deoptimizer.h"
19 #include "src/execution.h" 20 #include "src/execution.h"
20 #include "src/frames-inl.h" 21 #include "src/frames-inl.h"
21 #include "src/full-codegen/full-codegen.h" 22 #include "src/full-codegen/full-codegen.h"
22 #include "src/global-handles.h" 23 #include "src/global-handles.h"
23 #include "src/globals.h" 24 #include "src/globals.h"
24 #include "src/interpreter/interpreter.h" 25 #include "src/interpreter/interpreter.h"
25 #include "src/isolate-inl.h" 26 #include "src/isolate-inl.h"
26 #include "src/list.h" 27 #include "src/list.h"
27 #include "src/log.h" 28 #include "src/log.h"
28 #include "src/messages.h" 29 #include "src/messages.h"
29 #include "src/snapshot/natives.h" 30 #include "src/snapshot/natives.h"
30 #include "src/wasm/wasm-module.h" 31 #include "src/wasm/wasm-module.h"
31 32
32 #include "include/v8-debug.h" 33 #include "include/v8-debug.h"
33 34
34 namespace v8 { 35 namespace v8 {
35 namespace internal { 36 namespace internal {
36 37
37 Debug::Debug(Isolate* isolate) 38 Debug::Debug(Isolate* isolate)
38 : debug_context_(Handle<Context>()), 39 : debug_context_(Handle<Context>()),
39 event_listener_(Handle<Object>()), 40 event_listener_(Handle<Object>()),
40 event_listener_data_(Handle<Object>()), 41 event_listener_data_(Handle<Object>()),
41 message_handler_(NULL), 42 message_handler_(NULL),
42 command_received_(0), 43 command_received_(0),
43 command_queue_(isolate->logger(), kQueueInitialSize), 44 command_queue_(isolate->logger(), kQueueInitialSize),
44 is_active_(false), 45 is_active_(false),
46 hook_on_function_call_(false),
45 is_suppressed_(false), 47 is_suppressed_(false),
46 live_edit_enabled_(true), // TODO(yangguo): set to false by default. 48 live_edit_enabled_(true), // TODO(yangguo): set to false by default.
47 break_disabled_(false), 49 break_disabled_(false),
48 break_points_active_(true), 50 break_points_active_(true),
49 in_debug_event_listener_(false), 51 in_debug_event_listener_(false),
50 break_on_exception_(false), 52 break_on_exception_(false),
51 break_on_uncaught_exception_(false), 53 break_on_uncaught_exception_(false),
54 side_effect_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
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
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
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
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
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 STATIC_ASSERT(StepFrame > StepIn);
2093 STATIC_ASSERT(LastStepAction == StepFrame);
2094 hook_on_function_call_ = thread_local_.last_step_action_ >= StepIn ||
2095 isolate_->needs_side_effect_check();
2096 }
2097
2081 // Calls the registered debug message handler. This callback is part of the 2098 // Calls the registered debug message handler. This callback is part of the
2082 // public API. 2099 // public API.
2083 void Debug::InvokeMessageHandler(MessageImpl message) { 2100 void Debug::InvokeMessageHandler(MessageImpl message) {
2084 if (message_handler_ != NULL) message_handler_(message); 2101 if (message_handler_ != NULL) message_handler_(message);
2085 } 2102 }
2086 2103
2087 // Puts a command coming from the public API on the queue. Creates 2104 // 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 2105 // 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 2106 // point, the command data was managed by the API client. Called
2090 // by the API client thread. 2107 // by the API client thread.
(...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after
2268 reinterpret_cast<base::AtomicWord>(prev_)); 2285 reinterpret_cast<base::AtomicWord>(prev_));
2269 2286
2270 // Restore to the previous break state. 2287 // Restore to the previous break state.
2271 debug_->thread_local_.break_frame_id_ = break_frame_id_; 2288 debug_->thread_local_.break_frame_id_ = break_frame_id_;
2272 debug_->thread_local_.break_id_ = break_id_; 2289 debug_->thread_local_.break_id_ = break_id_;
2273 debug_->thread_local_.return_value_ = return_value_; 2290 debug_->thread_local_.return_value_ = return_value_;
2274 2291
2275 debug_->UpdateState(); 2292 debug_->UpdateState();
2276 } 2293 }
2277 2294
2295 bool Debug::PerformSideEffectCheck(Handle<JSFunction> function) {
jgruber 2017/01/11 16:12:39 Double-checking: I suppose this can never be enter
Yang 2017/01/12 06:04:51 Yup. Now guarding that too.
2296 DCHECK(isolate_->needs_side_effect_check());
2297 if (!Compiler::Compile(function, Compiler::KEEP_EXCEPTION)) return false;
2298 Deoptimizer::DeoptimizeFunction(*function);
2299 if (!function->shared()->HasNoSideEffect()) {
2300 if (FLAG_trace_side_effect_free_debug_evaluate) {
2301 PrintF("[debug-evaluate] Function %s failed side effect check.\n",
2302 function->shared()->DebugName()->ToCString().get());
2303 }
2304 side_effect_check_failed_ = true;
2305 // Throw an uncatchable termination exception.
2306 isolate_->TerminateExecution();
2307 return false;
2308 }
2309 return true;
2310 }
2311
2312 bool Debug::PerformSideEffectCheckForCallback(Address function) {
2313 DCHECK(isolate_->needs_side_effect_check());
2314 if (DebugEvaluate::CallbackHasNoSideEffect(function)) return true;
2315 side_effect_check_failed_ = true;
2316 // Throw an uncatchable termination exception.
2317 isolate_->TerminateExecution();
2318 isolate_->OptionalRescheduleException(false);
2319 return false;
2320 }
2321
2322 NoSideEffectScope::~NoSideEffectScope() {
2323 if (isolate_->needs_side_effect_check() &&
2324 isolate_->debug()->side_effect_check_failed_) {
2325 DCHECK(isolate_->has_pending_exception());
2326 DCHECK_EQ(isolate_->heap()->termination_exception(),
2327 isolate_->pending_exception());
2328 // Convert the termination exception into a regular exception.
2329 isolate_->CancelTerminateExecution();
2330 isolate_->Throw(*isolate_->factory()->NewEvalError(
2331 MessageTemplate::kNoSideEffectDebugEvaluate));
2332 }
2333 isolate_->set_needs_side_effect_check(old_needs_side_effect_check_);
2334 isolate_->debug()->UpdateHookOnFunctionCall();
2335 isolate_->debug()->side_effect_check_failed_ = false;
2336 }
2337
2278 MessageImpl MessageImpl::NewEvent(DebugEvent event, bool running, 2338 MessageImpl MessageImpl::NewEvent(DebugEvent event, bool running,
2279 Handle<JSObject> exec_state, 2339 Handle<JSObject> exec_state,
2280 Handle<JSObject> event_data) { 2340 Handle<JSObject> event_data) {
2281 MessageImpl message(true, event, running, exec_state, event_data, 2341 MessageImpl message(true, event, running, exec_state, event_data,
2282 Handle<String>(), NULL); 2342 Handle<String>(), NULL);
2283 return message; 2343 return message;
2284 } 2344 }
2285 2345
2286 MessageImpl MessageImpl::NewResponse(DebugEvent event, bool running, 2346 MessageImpl MessageImpl::NewResponse(DebugEvent event, bool running,
2287 Handle<JSObject> exec_state, 2347 Handle<JSObject> exec_state,
(...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after
2496 logger_->DebugEvent("Put", message.text()); 2556 logger_->DebugEvent("Put", message.text());
2497 } 2557 }
2498 2558
2499 void LockingCommandMessageQueue::Clear() { 2559 void LockingCommandMessageQueue::Clear() {
2500 base::LockGuard<base::Mutex> lock_guard(&mutex_); 2560 base::LockGuard<base::Mutex> lock_guard(&mutex_);
2501 queue_.Clear(); 2561 queue_.Clear();
2502 } 2562 }
2503 2563
2504 } // namespace internal 2564 } // namespace internal
2505 } // namespace v8 2565 } // namespace v8
OLDNEW
« no previous file with comments | « src/debug/debug.h ('k') | src/debug/debug-evaluate.h » ('j') | src/debug/debug-evaluate.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698