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

Side by Side Diff: runtime/vm/debugger.cc

Issue 1344993002: Refactor isolate interrupts to use OOB messages instead of interrupt bits. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 5 years, 3 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 (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "vm/debugger.h" 5 #include "vm/debugger.h"
6 6
7 #include "include/dart_api.h" 7 #include "include/dart_api.h"
8 8
9 #include "vm/code_generator.h" 9 #include "vm/code_generator.h"
10 #include "vm/code_patcher.h" 10 #include "vm/code_patcher.h"
(...skipping 24 matching lines...) Expand all
35 "Show invisible frames in debugger stack traces"); 35 "Show invisible frames in debugger stack traces");
36 DEFINE_FLAG(bool, trace_debugger_stacktrace, false, 36 DEFINE_FLAG(bool, trace_debugger_stacktrace, false,
37 "Trace debugger stacktrace collection"); 37 "Trace debugger stacktrace collection");
38 DEFINE_FLAG(bool, verbose_debug, false, "Verbose debugger messages"); 38 DEFINE_FLAG(bool, verbose_debug, false, "Verbose debugger messages");
39 DEFINE_FLAG(bool, steal_breakpoints, false, 39 DEFINE_FLAG(bool, steal_breakpoints, false,
40 "Intercept breakpoints and other pause events before they " 40 "Intercept breakpoints and other pause events before they "
41 "are sent to the embedder and use a generic VM breakpoint " 41 "are sent to the embedder and use a generic VM breakpoint "
42 "handler instead. This handler dispatches breakpoints to " 42 "handler instead. This handler dispatches breakpoints to "
43 "the VM service."); 43 "the VM service.");
44 44
45 DECLARE_FLAG(bool, trace_isolates);
46
45 47
46 Debugger::EventHandler* Debugger::event_handler_ = NULL; 48 Debugger::EventHandler* Debugger::event_handler_ = NULL;
47 49
48 50
49 class RemoteObjectCache : public ZoneAllocated { 51 class RemoteObjectCache : public ZoneAllocated {
50 public: 52 public:
51 explicit RemoteObjectCache(intptr_t initial_size); 53 explicit RemoteObjectCache(intptr_t initial_size);
52 intptr_t AddObject(const Object& obj); 54 intptr_t AddObject(const Object& obj);
53 RawObject* GetObj(intptr_t obj_id) const; 55 RawObject* GetObj(intptr_t obj_id) const;
54 bool IsValidId(intptr_t obj_id) const { 56 bool IsValidId(intptr_t obj_id) const {
(...skipping 257 matching lines...) Expand 10 before | Expand all | Expand 10 after
312 } 314 }
313 } 315 }
314 316
315 317
316 void Debugger::SignalIsolateEvent(DebuggerEvent::EventType type) { 318 void Debugger::SignalIsolateEvent(DebuggerEvent::EventType type) {
317 if (HasEventHandler()) { 319 if (HasEventHandler()) {
318 DebuggerEvent event(isolate_, type); 320 DebuggerEvent event(isolate_, type);
319 ASSERT(event.isolate_id() != ILLEGAL_ISOLATE_ID); 321 ASSERT(event.isolate_id() != ILLEGAL_ISOLATE_ID);
320 if (type == DebuggerEvent::kIsolateInterrupted) { 322 if (type == DebuggerEvent::kIsolateInterrupted) {
321 DebuggerStackTrace* trace = CollectStackTrace(); 323 DebuggerStackTrace* trace = CollectStackTrace();
322 ASSERT(trace->Length() > 0); 324 if (trace->Length() > 0) {
323 event.set_top_frame(trace->FrameAt(0)); 325 event.set_top_frame(trace->FrameAt(0));
326 }
324 ASSERT(stack_trace_ == NULL); 327 ASSERT(stack_trace_ == NULL);
325 stack_trace_ = trace; 328 stack_trace_ = trace;
326 resume_action_ = kContinue; 329 resume_action_ = kContinue;
327 Pause(&event); 330 Pause(&event);
328 HandleSteppingRequest(trace); 331 HandleSteppingRequest(trace);
329 stack_trace_ = NULL; 332 stack_trace_ = NULL;
330 } else { 333 } else {
331 InvokeEventHandler(&event); 334 InvokeEventHandler(&event);
332 } 335 }
333 } 336 }
334 } 337 }
335 338
336 339
337 void Debugger::SignalIsolateInterrupted() { 340 RawError* Debugger::SignalIsolateInterrupted() {
338 if (HasEventHandler()) { 341 if (HasEventHandler()) {
339 Debugger* debugger = Isolate::Current()->debugger(); 342 SignalIsolateEvent(DebuggerEvent::kIsolateInterrupted);
340 debugger->SignalIsolateEvent(DebuggerEvent::kIsolateInterrupted);
341 } 343 }
344 Dart_IsolateInterruptCallback callback = isolate_->InterruptCallback();
345 if (callback) {
346 if (!(*callback)()) {
347 if (FLAG_trace_isolates) {
348 OS::Print("[!] Embedder api: terminating isolate:\n"
349 "\tisolate: %s\n", isolate_->name());
350 }
351 const String& msg = String::Handle(String::New("isolate terminated"));
352 return UnwindError::New(msg);
353 }
354 }
355
356 // If any error occurred while in the debug message loop, return it here.
turnidge 2015/09/15 22:14:10 This could happen, for example, if the isolate rec
357 const Error& error =
358 Error::Handle(isolate_, isolate_->object_store()->sticky_error());
359 isolate_->object_store()->clear_sticky_error();
360 return error.raw();
342 } 361 }
343 362
344 363
345 // The vm service handles breakpoint notifications in a different way 364 // The vm service handles breakpoint notifications in a different way
346 // than the regular debugger breakpoint notifications. 365 // than the regular debugger breakpoint notifications.
347 static void SendServiceBreakpointEvent(ServiceEvent::EventKind kind, 366 static void SendServiceBreakpointEvent(ServiceEvent::EventKind kind,
348 Breakpoint* bpt) { 367 Breakpoint* bpt) {
349 if (Service::debug_stream.enabled()) { 368 if (Service::debug_stream.enabled()) {
350 ServiceEvent service_event(Isolate::Current(), kind); 369 ServiceEvent service_event(Isolate::Current(), kind);
351 service_event.set_breakpoint(bpt); 370 service_event.set_breakpoint(bpt);
(...skipping 2191 matching lines...) Expand 10 before | Expand all | Expand 10 after
2543 if ((iter.CurrentTokenKind() == Token::kIDENT) && 2562 if ((iter.CurrentTokenKind() == Token::kIDENT) &&
2544 ((iter.CurrentLiteral() == Symbols::Await().raw()) || 2563 ((iter.CurrentLiteral() == Symbols::Await().raw()) ||
2545 (iter.CurrentLiteral() == Symbols::YieldKw().raw()))) { 2564 (iter.CurrentLiteral() == Symbols::YieldKw().raw()))) {
2546 event.set_at_async_jump(true); 2565 event.set_at_async_jump(true);
2547 } 2566 }
2548 } 2567 }
2549 Pause(&event); 2568 Pause(&event);
2550 } 2569 }
2551 2570
2552 2571
2553 void Debugger::DebuggerStepCallback() { 2572 RawError* Debugger::DebuggerStepCallback() {
2554 ASSERT(isolate_->single_step()); 2573 ASSERT(isolate_->single_step());
2555 // We can't get here unless the debugger event handler enabled 2574 // We can't get here unless the debugger event handler enabled
2556 // single stepping. 2575 // single stepping.
2557 ASSERT(HasEventHandler()); 2576 ASSERT(HasEventHandler());
2558 // Don't pause recursively. 2577 // Don't pause recursively.
2559 if (IsPaused()) return; 2578 if (IsPaused()) {
2579 return Error::null();
2580 }
2560 2581
2561 // Check whether we are in a Dart function that the user is 2582 // Check whether we are in a Dart function that the user is
2562 // interested in. If we saved the frame pointer of a stack frame 2583 // interested in. If we saved the frame pointer of a stack frame
2563 // the user is interested in, we ignore the single step if we are 2584 // the user is interested in, we ignore the single step if we are
2564 // in a callee of that frame. Note that we assume that the stack 2585 // in a callee of that frame. Note that we assume that the stack
2565 // grows towards lower addresses. 2586 // grows towards lower addresses.
2566 ActivationFrame* frame = TopDartFrame(); 2587 ActivationFrame* frame = TopDartFrame();
2567 ASSERT(frame != NULL); 2588 ASSERT(frame != NULL);
2568 2589
2569 if (stepping_fp_ != 0) { 2590 if (stepping_fp_ != 0) {
2570 // There is an "interesting frame" set. Only pause at appropriate 2591 // There is an "interesting frame" set. Only pause at appropriate
2571 // locations in this frame. 2592 // locations in this frame.
2572 if (stepping_fp_ > frame->fp()) { 2593 if (stepping_fp_ > frame->fp()) {
2573 // We are in a callee of the frame we're interested in. 2594 // We are in a callee of the frame we're interested in.
2574 // Ignore this stepping break. 2595 // Ignore this stepping break.
2575 return; 2596 return Error::null();
2576 } else if (frame->fp() > stepping_fp_) { 2597 } else if (frame->fp() > stepping_fp_) {
2577 // We returned from the "interesting frame", there can be no more 2598 // We returned from the "interesting frame", there can be no more
2578 // stepping breaks for it. Pause at the next appropriate location 2599 // stepping breaks for it. Pause at the next appropriate location
2579 // and let the user set the "interesting" frame again. 2600 // and let the user set the "interesting" frame again.
2580 stepping_fp_ = 0; 2601 stepping_fp_ = 0;
2581 } 2602 }
2582 } 2603 }
2583 2604
2584 if (!frame->IsDebuggable()) { 2605 if (!frame->IsDebuggable()) {
2585 return; 2606 return Error::null();
2586 } 2607 }
2587 if (frame->TokenPos() == Scanner::kNoSourcePos) { 2608 if (frame->TokenPos() == Scanner::kNoSourcePos) {
2588 return; 2609 return Error::null();
2589 } 2610 }
2590 2611
2591 // Don't pause for a single step if there is a breakpoint set 2612 // Don't pause for a single step if there is a breakpoint set
2592 // at this location. 2613 // at this location.
2593 if (HasActiveBreakpoint(frame->pc())) { 2614 if (HasActiveBreakpoint(frame->pc())) {
2594 return; 2615 return Error::null();
2595 } 2616 }
2596 2617
2597 if (FLAG_verbose_debug) { 2618 if (FLAG_verbose_debug) {
2598 OS::Print(">>> single step break at %s:%" Pd " (func %s token %" Pd ")\n", 2619 OS::Print(">>> single step break at %s:%" Pd " (func %s token %" Pd ")\n",
2599 String::Handle(frame->SourceUrl()).ToCString(), 2620 String::Handle(frame->SourceUrl()).ToCString(),
2600 frame->LineNumber(), 2621 frame->LineNumber(),
2601 String::Handle(frame->QualifiedFunctionName()).ToCString(), 2622 String::Handle(frame->QualifiedFunctionName()).ToCString(),
2602 frame->TokenPos()); 2623 frame->TokenPos());
2603 } 2624 }
2604 2625
2605 ASSERT(stack_trace_ == NULL); 2626 ASSERT(stack_trace_ == NULL);
2606 stack_trace_ = CollectStackTrace(); 2627 stack_trace_ = CollectStackTrace();
2607 SignalPausedEvent(frame, NULL); 2628 SignalPausedEvent(frame, NULL);
2608 HandleSteppingRequest(stack_trace_); 2629 HandleSteppingRequest(stack_trace_);
2609 stack_trace_ = NULL; 2630 stack_trace_ = NULL;
2631
2632 // If any error occurred while in the debug message loop, return it here.
2633 const Error& error =
2634 Error::Handle(isolate_, isolate_->object_store()->sticky_error());
2635 isolate_->object_store()->clear_sticky_error();
2636 return error.raw();
2610 } 2637 }
2611 2638
2612 2639
2613 void Debugger::SignalBpReached() { 2640 RawError* Debugger::SignalBpReached() {
2614 // We ignore this breakpoint when the VM is executing code invoked 2641 // We ignore this breakpoint when the VM is executing code invoked
2615 // by the debugger to evaluate variables values, or when we see a nested 2642 // by the debugger to evaluate variables values, or when we see a nested
2616 // breakpoint or exception event. 2643 // breakpoint or exception event.
2617 if (ignore_breakpoints_ || IsPaused() || !HasEventHandler()) { 2644 if (ignore_breakpoints_ || IsPaused() || !HasEventHandler()) {
2618 return; 2645 return Error::null();
2619 } 2646 }
2620 DebuggerStackTrace* stack_trace = CollectStackTrace(); 2647 DebuggerStackTrace* stack_trace = CollectStackTrace();
2621 ASSERT(stack_trace->Length() > 0); 2648 ASSERT(stack_trace->Length() > 0);
2622 ActivationFrame* top_frame = stack_trace->FrameAt(0); 2649 ActivationFrame* top_frame = stack_trace->FrameAt(0);
2623 ASSERT(top_frame != NULL); 2650 ASSERT(top_frame != NULL);
2624 CodeBreakpoint* cbpt = GetCodeBreakpoint(top_frame->pc()); 2651 CodeBreakpoint* cbpt = GetCodeBreakpoint(top_frame->pc());
2625 ASSERT(cbpt != NULL); 2652 ASSERT(cbpt != NULL);
2626 2653
2627 BreakpointLocation* bpt_location = cbpt->bpt_location_; 2654 BreakpointLocation* bpt_location = cbpt->bpt_location_;
2628 Breakpoint* bpt_hit = NULL; 2655 Breakpoint* bpt_hit = NULL;
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
2662 if (bpt->IsRepeated()) { 2689 if (bpt->IsRepeated()) {
2663 bpt_hit = bpt; 2690 bpt_hit = bpt;
2664 break; 2691 break;
2665 } 2692 }
2666 bpt = bpt->next(); 2693 bpt = bpt->next();
2667 } 2694 }
2668 } 2695 }
2669 } 2696 }
2670 2697
2671 if (bpt_hit == NULL) { 2698 if (bpt_hit == NULL) {
2672 return; 2699 return Error::null();
2673 } 2700 }
2674 2701
2675 if (FLAG_verbose_debug) { 2702 if (FLAG_verbose_debug) {
2676 OS::Print(">>> hit %s breakpoint at %s:%" Pd " " 2703 OS::Print(">>> hit %s breakpoint at %s:%" Pd " "
2677 "(token %" Pd ") (address %#" Px ")\n", 2704 "(token %" Pd ") (address %#" Px ")\n",
2678 cbpt->IsInternal() ? "internal" : "user", 2705 cbpt->IsInternal() ? "internal" : "user",
2679 String::Handle(cbpt->SourceUrl()).ToCString(), 2706 String::Handle(cbpt->SourceUrl()).ToCString(),
2680 cbpt->LineNumber(), 2707 cbpt->LineNumber(),
2681 cbpt->token_pos(), 2708 cbpt->token_pos(),
2682 top_frame->pc()); 2709 top_frame->pc());
2683 } 2710 }
2684 2711
2685 ASSERT(stack_trace_ == NULL); 2712 ASSERT(stack_trace_ == NULL);
2686 stack_trace_ = stack_trace; 2713 stack_trace_ = stack_trace;
2687 SignalPausedEvent(top_frame, bpt_hit); 2714 SignalPausedEvent(top_frame, bpt_hit);
2688 HandleSteppingRequest(stack_trace_); 2715 HandleSteppingRequest(stack_trace_);
2689 stack_trace_ = NULL; 2716 stack_trace_ = NULL;
2690 if (cbpt->IsInternal()) { 2717 if (cbpt->IsInternal()) {
2691 RemoveInternalBreakpoints(); 2718 RemoveInternalBreakpoints();
2692 } 2719 }
2720
2721 // If any error occurred while in the debug message loop, return it here.
2722 const Error& error =
2723 Error::Handle(isolate_, isolate_->object_store()->sticky_error());
2724 isolate_->object_store()->clear_sticky_error();
2725 return error.raw();
2693 } 2726 }
2694 2727
2695 2728
2696 void Debugger::BreakHere(const String& msg) { 2729 void Debugger::BreakHere(const String& msg) {
2697 // We ignore this breakpoint when the VM is executing code invoked 2730 // We ignore this breakpoint when the VM is executing code invoked
2698 // by the debugger to evaluate variables values, or when we see a nested 2731 // by the debugger to evaluate variables values, or when we see a nested
2699 // breakpoint or exception event. 2732 // breakpoint or exception event.
2700 if (ignore_breakpoints_ || IsPaused() || !HasEventHandler()) { 2733 if (ignore_breakpoints_ || IsPaused() || !HasEventHandler()) {
2701 return; 2734 return;
2702 } 2735 }
(...skipping 469 matching lines...) Expand 10 before | Expand all | Expand 10 after
3172 } 3205 }
3173 3206
3174 3207
3175 void Debugger::RegisterCodeBreakpoint(CodeBreakpoint* bpt) { 3208 void Debugger::RegisterCodeBreakpoint(CodeBreakpoint* bpt) {
3176 ASSERT(bpt->next() == NULL); 3209 ASSERT(bpt->next() == NULL);
3177 bpt->set_next(code_breakpoints_); 3210 bpt->set_next(code_breakpoints_);
3178 code_breakpoints_ = bpt; 3211 code_breakpoints_ = bpt;
3179 } 3212 }
3180 3213
3181 } // namespace dart 3214 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/debugger.h ('k') | runtime/vm/isolate.h » ('j') | runtime/vm/isolate.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698