| Index: runtime/vm/debugger.cc
|
| diff --git a/runtime/vm/debugger.cc b/runtime/vm/debugger.cc
|
| index 41b1f173ada0d3848c2dfe2505d37bf24332dbad..057e8f34a0433d74c9f753f6f8d0a8e2a80c4536 100644
|
| --- a/runtime/vm/debugger.cc
|
| +++ b/runtime/vm/debugger.cc
|
| @@ -19,6 +19,7 @@
|
| #include "vm/object_store.h"
|
| #include "vm/os.h"
|
| #include "vm/port.h"
|
| +#include "vm/service.h"
|
| #include "vm/stack_frame.h"
|
| #include "vm/stub_code.h"
|
| #include "vm/symbols.h"
|
| @@ -192,10 +193,29 @@ ActivationFrame::ActivationFrame(
|
| }
|
|
|
|
|
| -void Debugger::SignalIsolateEvent(DebuggerEvent::EventType type) {
|
| +bool Debugger::HasEventHandler() {
|
| + return (event_handler_ != NULL) || Service::NeedsDebuggerEvents();
|
| +}
|
| +
|
| +
|
| +void Debugger::InvokeEventHandler(DebuggerEvent* event) {
|
| + ASSERT(HasEventHandler());
|
| +
|
| + // Give the event to the Service first, as the debugger event handler
|
| + // may go into a message loop and the Service will not.
|
| + if (Service::NeedsDebuggerEvents()) {
|
| + Service::HandleDebuggerEvent(event);
|
| + }
|
| +
|
| if (event_handler_ != NULL) {
|
| - DebuggerEvent event(type);
|
| - event.set_isolate_id(isolate_id_);
|
| + (*event_handler_)(event);
|
| + }
|
| +}
|
| +
|
| +
|
| +void Debugger::SignalIsolateEvent(DebuggerEvent::EventType type) {
|
| + if (HasEventHandler()) {
|
| + DebuggerEvent event(isolate_, type);
|
| ASSERT(event.isolate_id() != ILLEGAL_ISOLATE_ID);
|
| if (type == DebuggerEvent::kIsolateInterrupted) {
|
| DebuggerStackTrace* trace = CollectStackTrace();
|
| @@ -207,14 +227,14 @@ void Debugger::SignalIsolateEvent(DebuggerEvent::EventType type) {
|
| HandleSteppingRequest(trace);
|
| stack_trace_ = NULL;
|
| } else {
|
| - (*event_handler_)(&event);
|
| + InvokeEventHandler(&event);
|
| }
|
| }
|
| }
|
|
|
|
|
| void Debugger::SignalIsolateInterrupted() {
|
| - if (event_handler_ != NULL) {
|
| + if (HasEventHandler()) {
|
| Debugger* debugger = Isolate::Current()->debugger();
|
| ASSERT(debugger != NULL);
|
| debugger->SignalIsolateEvent(DebuggerEvent::kIsolateInterrupted);
|
| @@ -510,11 +530,11 @@ const char* DebuggerEvent::EventTypeToCString(EventType type) {
|
|
|
| void DebuggerEvent::PrintJSON(JSONStream* js) const {
|
| JSONObject jsobj(js);
|
| - jsobj.AddProperty("type", "DebuggerEvent");
|
| + jsobj.AddProperty("type", "ServiceEvent");
|
| // TODO(turnidge): Drop the 'id' for things like DebuggerEvent.
|
| jsobj.AddProperty("id", "");
|
| - // TODO(turnidge): Add 'isolate'.
|
| jsobj.AddProperty("eventType", EventTypeToCString(type()));
|
| + jsobj.AddProperty("isolate", isolate());
|
| if (type() == kBreakpointResolved || type() == kBreakpointReached) {
|
| jsobj.AddProperty("breakpoint", breakpoint());
|
| }
|
| @@ -1212,10 +1232,10 @@ void Debugger::SetInternalBreakpoints(const Function& target_function) {
|
|
|
|
|
| void Debugger::SignalBpResolved(SourceBreakpoint* bpt) {
|
| - if (event_handler_ != NULL) {
|
| - DebuggerEvent event(DebuggerEvent::kBreakpointResolved);
|
| + if (HasEventHandler()) {
|
| + DebuggerEvent event(isolate_, DebuggerEvent::kBreakpointResolved);
|
| event.set_breakpoint(bpt);
|
| - (*event_handler_)(&event);
|
| + InvokeEventHandler(&event);
|
| }
|
| }
|
|
|
| @@ -1500,7 +1520,7 @@ void Debugger::SignalExceptionThrown(const Instance& exc) {
|
| // interested in exception events.
|
| if (ignore_breakpoints_ ||
|
| IsPaused() ||
|
| - (event_handler_ == NULL) ||
|
| + (!HasEventHandler()) ||
|
| (exc_pause_info_ == kNoPauseOnExceptions)) {
|
| return;
|
| }
|
| @@ -1508,7 +1528,7 @@ void Debugger::SignalExceptionThrown(const Instance& exc) {
|
| if (!ShouldPauseOnException(stack_trace, exc)) {
|
| return;
|
| }
|
| - DebuggerEvent event(DebuggerEvent::kExceptionThrown);
|
| + DebuggerEvent event(isolate_, DebuggerEvent::kExceptionThrown);
|
| event.set_exception(&exc);
|
| ASSERT(stack_trace_ == NULL);
|
| stack_trace_ = stack_trace;
|
| @@ -2138,6 +2158,7 @@ RawArray* Debugger::GetGlobalFields(const Library& lib) {
|
| }
|
|
|
|
|
| +// static
|
| void Debugger::VisitObjectPointers(ObjectPointerVisitor* visitor) {
|
| ASSERT(visitor != NULL);
|
| SourceBreakpoint* bpt = src_breakpoints_;
|
| @@ -2153,6 +2174,7 @@ void Debugger::VisitObjectPointers(ObjectPointerVisitor* visitor) {
|
| }
|
|
|
|
|
| +// static
|
| void Debugger::SetEventHandler(EventHandler* handler) {
|
| event_handler_ = handler;
|
| }
|
| @@ -2165,7 +2187,7 @@ void Debugger::Pause(DebuggerEvent* event) {
|
| pause_event_ = event;
|
| obj_cache_ = new RemoteObjectCache(64);
|
|
|
| - (*event_handler_)(event);
|
| + InvokeEventHandler(event);
|
|
|
| pause_event_ = NULL;
|
| obj_cache_ = NULL; // Zone allocated
|
| @@ -2212,7 +2234,7 @@ void Debugger::SignalPausedEvent(ActivationFrame* top_frame,
|
| isolate_->set_single_step(false);
|
| ASSERT(!IsPaused());
|
| ASSERT(obj_cache_ == NULL);
|
| - DebuggerEvent event(DebuggerEvent::kBreakpointReached);
|
| + DebuggerEvent event(isolate_, DebuggerEvent::kBreakpointReached);
|
| event.set_top_frame(top_frame);
|
| event.set_breakpoint(bpt);
|
| Pause(&event);
|
| @@ -2223,7 +2245,7 @@ void Debugger::DebuggerStepCallback() {
|
| ASSERT(isolate_->single_step());
|
| // We can't get here unless the debugger event handler enabled
|
| // single stepping.
|
| - ASSERT(event_handler_ != NULL);
|
| + ASSERT(HasEventHandler());
|
| // Don't pause recursively.
|
| if (IsPaused()) return;
|
|
|
| @@ -2283,7 +2305,7 @@ void Debugger::SignalBpReached() {
|
| // We ignore this breakpoint when the VM is executing code invoked
|
| // by the debugger to evaluate variables values, or when we see a nested
|
| // breakpoint or exception event.
|
| - if (ignore_breakpoints_ || IsPaused() || (event_handler_ == NULL)) {
|
| + if (ignore_breakpoints_ || IsPaused() || !HasEventHandler()) {
|
| return;
|
| }
|
| DebuggerStackTrace* stack_trace = CollectStackTrace();
|
|
|