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

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

Issue 2622863003: [debugger] infrastructure for side-effect-free debug-evaluate. (Closed)
Patch Set: fix mips one more time 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
« no previous file with comments | « src/debug/debug.h ('k') | src/debug/debug-evaluate.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 337 matching lines...) Expand 10 before | Expand all | Expand 10 after
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 thread_local_.async_task_count_ = 0; 407 thread_local_.async_task_count_ = 0;
405 clear_suspended_generator(); 408 clear_suspended_generator();
406 // TODO(isolates): frames_are_dropped_? 409 // TODO(isolates): frames_are_dropped_?
407 base::NoBarrier_Store(&thread_local_.current_debug_scope_, 410 base::NoBarrier_Store(&thread_local_.current_debug_scope_,
408 static_cast<base::AtomicWord>(0)); 411 static_cast<base::AtomicWord>(0));
412 UpdateHookOnFunctionCall();
409 } 413 }
410 414
411 415
412 char* Debug::ArchiveDebug(char* storage) { 416 char* Debug::ArchiveDebug(char* storage) {
413 // Simply reset state. Don't archive anything. 417 // Simply reset state. Don't archive anything.
414 ThreadInit(); 418 ThreadInit();
415 return storage + ArchiveSpacePerThread(); 419 return storage + ArchiveSpacePerThread();
416 } 420 }
417 421
418 422
(...skipping 479 matching lines...) Expand 10 before | Expand all | Expand 10 after
898 if (type == BreakUncaughtException) { 902 if (type == BreakUncaughtException) {
899 return break_on_uncaught_exception_; 903 return break_on_uncaught_exception_;
900 } else { 904 } else {
901 return break_on_exception_; 905 return break_on_exception_;
902 } 906 }
903 } 907 }
904 908
905 909
906 void Debug::PrepareStepIn(Handle<JSFunction> function) { 910 void Debug::PrepareStepIn(Handle<JSFunction> function) {
907 CHECK(last_step_action() >= StepIn); 911 CHECK(last_step_action() >= StepIn);
908 if (!is_active()) return; 912 if (ignore_events()) return;
909 if (in_debug_scope()) return; 913 if (in_debug_scope()) return;
914 if (break_disabled()) return;
910 FloodWithOneShot(function); 915 FloodWithOneShot(function);
911 } 916 }
912 917
913 void Debug::PrepareStepInSuspendedGenerator() { 918 void Debug::PrepareStepInSuspendedGenerator() {
914 CHECK(has_suspended_generator()); 919 CHECK(has_suspended_generator());
915 if (!is_active()) return; 920 if (ignore_events()) return;
916 if (in_debug_scope()) return; 921 if (in_debug_scope()) return;
922 if (break_disabled()) return;
917 thread_local_.last_step_action_ = StepIn; 923 thread_local_.last_step_action_ = StepIn;
924 UpdateHookOnFunctionCall();
918 Handle<JSFunction> function( 925 Handle<JSFunction> function(
919 JSGeneratorObject::cast(thread_local_.suspended_generator_)->function()); 926 JSGeneratorObject::cast(thread_local_.suspended_generator_)->function());
920 FloodWithOneShot(function); 927 FloodWithOneShot(function);
921 clear_suspended_generator(); 928 clear_suspended_generator();
922 } 929 }
923 930
924 void Debug::PrepareStepOnThrow() { 931 void Debug::PrepareStepOnThrow() {
925 if (!is_active()) return;
926 if (last_step_action() == StepNone) return; 932 if (last_step_action() == StepNone) return;
933 if (ignore_events()) return;
927 if (in_debug_scope()) return; 934 if (in_debug_scope()) return;
935 if (break_disabled()) return;
928 936
929 ClearOneShot(); 937 ClearOneShot();
930 938
931 // Iterate through the JavaScript stack looking for handlers. 939 // Iterate through the JavaScript stack looking for handlers.
932 JavaScriptFrameIterator it(isolate_); 940 JavaScriptFrameIterator it(isolate_);
933 while (!it.done()) { 941 while (!it.done()) {
934 JavaScriptFrame* frame = it.frame(); 942 JavaScriptFrame* frame = it.frame();
935 if (frame->LookupExceptionHandlerInTable(nullptr, nullptr) > 0) break; 943 if (frame->LookupExceptionHandlerInTable(nullptr, nullptr) > 0) break;
936 it.Advance(); 944 it.Advance();
937 } 945 }
(...skipping 30 matching lines...) Expand all
968 StackFrame::Id frame_id = break_frame_id(); 976 StackFrame::Id frame_id = break_frame_id();
969 // If there is no JavaScript stack don't do anything. 977 // If there is no JavaScript stack don't do anything.
970 if (frame_id == StackFrame::NO_ID) return; 978 if (frame_id == StackFrame::NO_ID) return;
971 979
972 JavaScriptFrameIterator frames_it(isolate_, frame_id); 980 JavaScriptFrameIterator frames_it(isolate_, frame_id);
973 JavaScriptFrame* frame = frames_it.frame(); 981 JavaScriptFrame* frame = frames_it.frame();
974 982
975 feature_tracker()->Track(DebugFeatureTracker::kStepping); 983 feature_tracker()->Track(DebugFeatureTracker::kStepping);
976 984
977 thread_local_.last_step_action_ = step_action; 985 thread_local_.last_step_action_ = step_action;
986 UpdateHookOnFunctionCall();
978 987
979 // If the function on the top frame is unresolved perform step out. This will 988 // If the function on the top frame is unresolved perform step out. This will
980 // be the case when calling unknown function and having the debugger stopped 989 // be the case when calling unknown function and having the debugger stopped
981 // in an unhandled exception. 990 // in an unhandled exception.
982 if (!frame->function()->IsJSFunction()) { 991 if (!frame->function()->IsJSFunction()) {
983 // Step out: Find the calling JavaScript frame and flood it with 992 // Step out: Find the calling JavaScript frame and flood it with
984 // breakpoints. 993 // breakpoints.
985 frames_it.Advance(); 994 frames_it.Advance();
986 // Fill the function to return to with one-shot break points. 995 // Fill the function to return to with one-shot break points.
987 JSFunction* function = frames_it.frame()->function(); 996 JSFunction* function = frames_it.frame()->function();
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after
1098 } 1107 }
1099 1108
1100 void Debug::ClearStepping() { 1109 void Debug::ClearStepping() {
1101 // Clear the various stepping setup. 1110 // Clear the various stepping setup.
1102 ClearOneShot(); 1111 ClearOneShot();
1103 1112
1104 thread_local_.last_step_action_ = StepNone; 1113 thread_local_.last_step_action_ = StepNone;
1105 thread_local_.last_statement_position_ = kNoSourcePosition; 1114 thread_local_.last_statement_position_ = kNoSourcePosition;
1106 thread_local_.last_fp_ = 0; 1115 thread_local_.last_fp_ = 0;
1107 thread_local_.target_fp_ = 0; 1116 thread_local_.target_fp_ = 0;
1117 UpdateHookOnFunctionCall();
1108 } 1118 }
1109 1119
1110 1120
1111 // Clears all the one-shot break points that are currently set. Normally this 1121 // Clears all the one-shot break points that are currently set. Normally this
1112 // function is called each time a break point is hit as one shot break points 1122 // function is called each time a break point is hit as one shot break points
1113 // are used to support stepping. 1123 // are used to support stepping.
1114 void Debug::ClearOneShot() { 1124 void Debug::ClearOneShot() {
1115 // The current implementation just runs through all the breakpoints. When the 1125 // The current implementation just runs through all the breakpoints. When the
1116 // last break point for a function is removed that function is automatically 1126 // last break point for a function is removed that function is automatically
1117 // removed from the list. 1127 // removed from the list.
(...skipping 1010 matching lines...) Expand 10 before | Expand all | Expand 10 after
2128 // bootstrap test cases. 2138 // bootstrap test cases.
2129 isolate_->compilation_cache()->Disable(); 2139 isolate_->compilation_cache()->Disable();
2130 is_active = Load(); 2140 is_active = Load();
2131 } else if (is_loaded()) { 2141 } else if (is_loaded()) {
2132 isolate_->compilation_cache()->Enable(); 2142 isolate_->compilation_cache()->Enable();
2133 Unload(); 2143 Unload();
2134 } 2144 }
2135 is_active_ = is_active; 2145 is_active_ = is_active;
2136 } 2146 }
2137 2147
2148 void Debug::UpdateHookOnFunctionCall() {
2149 STATIC_ASSERT(StepFrame > StepIn);
2150 STATIC_ASSERT(LastStepAction == StepFrame);
2151 hook_on_function_call_ = thread_local_.last_step_action_ >= StepIn ||
2152 isolate_->needs_side_effect_check();
2153 }
2154
2138 // Calls the registered debug message handler. This callback is part of the 2155 // Calls the registered debug message handler. This callback is part of the
2139 // public API. 2156 // public API.
2140 void Debug::InvokeMessageHandler(MessageImpl message) { 2157 void Debug::InvokeMessageHandler(MessageImpl message) {
2141 if (message_handler_ != NULL) message_handler_(message); 2158 if (message_handler_ != NULL) message_handler_(message);
2142 } 2159 }
2143 2160
2144 // Puts a command coming from the public API on the queue. Creates 2161 // Puts a command coming from the public API on the queue. Creates
2145 // a copy of the command string managed by the debugger. Up to this 2162 // a copy of the command string managed by the debugger. Up to this
2146 // point, the command data was managed by the API client. Called 2163 // point, the command data was managed by the API client. Called
2147 // by the API client thread. 2164 // by the API client thread.
(...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after
2325 reinterpret_cast<base::AtomicWord>(prev_)); 2342 reinterpret_cast<base::AtomicWord>(prev_));
2326 2343
2327 // Restore to the previous break state. 2344 // Restore to the previous break state.
2328 debug_->thread_local_.break_frame_id_ = break_frame_id_; 2345 debug_->thread_local_.break_frame_id_ = break_frame_id_;
2329 debug_->thread_local_.break_id_ = break_id_; 2346 debug_->thread_local_.break_id_ = break_id_;
2330 debug_->thread_local_.return_value_ = return_value_; 2347 debug_->thread_local_.return_value_ = return_value_;
2331 2348
2332 debug_->UpdateState(); 2349 debug_->UpdateState();
2333 } 2350 }
2334 2351
2352 bool Debug::PerformSideEffectCheck(Handle<JSFunction> function) {
2353 DCHECK(isolate_->needs_side_effect_check());
2354 DisallowJavascriptExecution no_js(isolate_);
2355 if (!Compiler::Compile(function, Compiler::KEEP_EXCEPTION)) return false;
2356 Deoptimizer::DeoptimizeFunction(*function);
2357 if (!function->shared()->HasNoSideEffect()) {
2358 if (FLAG_trace_side_effect_free_debug_evaluate) {
2359 PrintF("[debug-evaluate] Function %s failed side effect check.\n",
2360 function->shared()->DebugName()->ToCString().get());
2361 }
2362 side_effect_check_failed_ = true;
2363 // Throw an uncatchable termination exception.
2364 isolate_->TerminateExecution();
2365 return false;
2366 }
2367 return true;
2368 }
2369
2370 bool Debug::PerformSideEffectCheckForCallback(Address function) {
2371 DCHECK(isolate_->needs_side_effect_check());
2372 if (DebugEvaluate::CallbackHasNoSideEffect(function)) return true;
2373 side_effect_check_failed_ = true;
2374 // Throw an uncatchable termination exception.
2375 isolate_->TerminateExecution();
2376 isolate_->OptionalRescheduleException(false);
2377 return false;
2378 }
2379
2380 NoSideEffectScope::~NoSideEffectScope() {
2381 if (isolate_->needs_side_effect_check() &&
2382 isolate_->debug()->side_effect_check_failed_) {
2383 DCHECK(isolate_->has_pending_exception());
2384 DCHECK_EQ(isolate_->heap()->termination_exception(),
2385 isolate_->pending_exception());
2386 // Convert the termination exception into a regular exception.
2387 isolate_->CancelTerminateExecution();
2388 isolate_->Throw(*isolate_->factory()->NewEvalError(
2389 MessageTemplate::kNoSideEffectDebugEvaluate));
2390 }
2391 isolate_->set_needs_side_effect_check(old_needs_side_effect_check_);
2392 isolate_->debug()->UpdateHookOnFunctionCall();
2393 isolate_->debug()->side_effect_check_failed_ = false;
2394 }
2395
2335 MessageImpl MessageImpl::NewEvent(DebugEvent event, bool running, 2396 MessageImpl MessageImpl::NewEvent(DebugEvent event, bool running,
2336 Handle<JSObject> exec_state, 2397 Handle<JSObject> exec_state,
2337 Handle<JSObject> event_data) { 2398 Handle<JSObject> event_data) {
2338 MessageImpl message(true, event, running, exec_state, event_data, 2399 MessageImpl message(true, event, running, exec_state, event_data,
2339 Handle<String>(), NULL); 2400 Handle<String>(), NULL);
2340 return message; 2401 return message;
2341 } 2402 }
2342 2403
2343 MessageImpl MessageImpl::NewResponse(DebugEvent event, bool running, 2404 MessageImpl MessageImpl::NewResponse(DebugEvent event, bool running,
2344 Handle<JSObject> exec_state, 2405 Handle<JSObject> exec_state,
(...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after
2553 logger_->DebugEvent("Put", message.text()); 2614 logger_->DebugEvent("Put", message.text());
2554 } 2615 }
2555 2616
2556 void LockingCommandMessageQueue::Clear() { 2617 void LockingCommandMessageQueue::Clear() {
2557 base::LockGuard<base::Mutex> lock_guard(&mutex_); 2618 base::LockGuard<base::Mutex> lock_guard(&mutex_);
2558 queue_.Clear(); 2619 queue_.Clear();
2559 } 2620 }
2560 2621
2561 } // namespace internal 2622 } // namespace internal
2562 } // namespace v8 2623 } // namespace v8
OLDNEW
« no previous file with comments | « src/debug/debug.h ('k') | src/debug/debug-evaluate.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698