Chromium Code Reviews| Index: runtime/vm/service.cc |
| diff --git a/runtime/vm/service.cc b/runtime/vm/service.cc |
| index 19cd84a357b2edf1a3d9e7e4a6f0aac905e71d06..fff5ad5340e80373d0603b51e4eb03da02775f7e 100644 |
| --- a/runtime/vm/service.cc |
| +++ b/runtime/vm/service.cc |
| @@ -74,6 +74,54 @@ EmbedderServiceHandler* Service::root_service_handler_head_ = NULL; |
| struct ServiceMethodDescriptor; |
| ServiceMethodDescriptor* FindMethod(const char* method_name); |
| +// TODO(turnidge): Build a general framework later. For now, we have |
| +// a small set of well-known streams. |
| +bool Service::needs_isolate_events_ = false; |
| +bool Service::needs_debug_events_ = false; |
| +bool Service::needs_gc_events_ = false; |
| +bool Service::needs_echo_events_ = false; |
| +bool Service::needs_graph_events_ = false; |
| + |
| +void Service::ListenStream(const char* stream_id) { |
| + if (FLAG_trace_service) { |
| + OS::Print("vm-service: starting stream '%s'\n", |
| + stream_id); |
| + } |
| + if (strcmp(stream_id, "Isolate") == 0) { |
| + needs_isolate_events_ = true; |
| + } else if (strcmp(stream_id, "Debug") == 0) { |
| + needs_debug_events_ = true; |
| + } else if (strcmp(stream_id, "GC") == 0) { |
| + needs_gc_events_ = true; |
| + } else if (strcmp(stream_id, "_Echo") == 0) { |
| + needs_echo_events_ = true; |
| + } else if (strcmp(stream_id, "_Graph") == 0) { |
| + needs_graph_events_ = true; |
| + } else { |
| + UNREACHABLE(); |
| + } |
| +} |
| + |
| +void Service::CancelStream(const char* stream_id) { |
| + if (FLAG_trace_service) { |
| + OS::Print("vm-service: stopping stream '%s'\n", |
| + stream_id); |
| + } |
| + if (strcmp(stream_id, "Isolate") == 0) { |
|
Cutch
2015/05/26 20:37:42
would be nice to have these up with the flags:
co
|
| + needs_isolate_events_ = false; |
| + } else if (strcmp(stream_id, "Debug") == 0) { |
| + needs_debug_events_ = false; |
| + } else if (strcmp(stream_id, "GC") == 0) { |
| + needs_gc_events_ = false; |
| + } else if (strcmp(stream_id, "_Echo") == 0) { |
| + needs_echo_events_ = false; |
| + } else if (strcmp(stream_id, "_Graph") == 0) { |
| + needs_graph_events_ = false; |
| + } else { |
| + UNREACHABLE(); |
| + } |
| +} |
| + |
| static uint8_t* allocator(uint8_t* ptr, intptr_t old_size, intptr_t new_size) { |
| void* new_ptr = realloc(reinterpret_cast<void*>(ptr), new_size); |
| return reinterpret_cast<uint8_t*>(new_ptr); |
| @@ -492,13 +540,9 @@ void Service::HandleIsolateMessage(Isolate* isolate, const Array& msg) { |
| } |
| -bool Service::NeedsEvents() { |
| - return ServiceIsolate::IsRunning(); |
| -} |
| - |
| - |
| -void Service::SendEvent(intptr_t eventType, |
| - const Object& eventMessage) { |
| +void Service::SendEvent(const char* stream_id, |
| + const char* event_type, |
| + const Object& event_message) { |
| ASSERT(!ServiceIsolate::IsServiceIsolateDescendant(Isolate::Current())); |
| if (!ServiceIsolate::IsRunning()) { |
| return; |
| @@ -507,14 +551,21 @@ void Service::SendEvent(intptr_t eventType, |
| ASSERT(isolate != NULL); |
| HANDLESCOPE(isolate); |
| + const Array& list = Array::Handle(Array::New(2)); |
| + ASSERT(!list.IsNull()); |
| + const String& stream_id_str = String::Handle(String::New(stream_id)); |
| + list.SetAt(0, stream_id_str); |
| + list.SetAt(1, event_message); |
| + |
| // Push the event to port_. |
| uint8_t* data = NULL; |
| MessageWriter writer(&data, &allocator, false); |
| - writer.WriteMessage(eventMessage); |
| + writer.WriteMessage(list); |
| intptr_t len = writer.BytesWritten(); |
| if (FLAG_trace_service) { |
| - OS::Print("vm-service: Pushing event of type %" Pd ", len %" Pd "\n", |
| - eventType, len); |
| + OS::Print( |
| + "vm-service: Pushing event of type %s to stream %s, len %" Pd "\n", |
| + event_type, stream_id, len); |
| } |
| // TODO(turnidge): For now we ignore failure to send an event. Revisit? |
| PortMap::PostMessage( |
| @@ -522,9 +573,11 @@ void Service::SendEvent(intptr_t eventType, |
| } |
| -void Service::SendEvent(const String& meta, |
| - const uint8_t* data, |
| - intptr_t size) { |
| +void Service::SendEventWithData(const char* stream_id, |
| + const char* event_type, |
| + const String& meta, |
| + const uint8_t* data, |
| + intptr_t size) { |
| // Bitstream: [meta data size (big-endian 64 bit)] [meta data (UTF-8)] [data] |
| const intptr_t meta_bytes = Utf8::Length(meta); |
| const intptr_t total_bytes = sizeof(uint64_t) + meta_bytes + size; |
| @@ -547,8 +600,7 @@ void Service::SendEvent(const String& meta, |
| offset += size; |
| } |
| ASSERT(offset == total_bytes); |
| - // TODO(turnidge): Pass the real eventType here. |
| - SendEvent(0, message); |
| + SendEvent(stream_id, event_type, message); |
| } |
| @@ -557,12 +609,16 @@ void Service::HandleEvent(ServiceEvent* event) { |
| return; |
| } |
| JSONStream js; |
| + const char* stream_id = event->stream_id(); |
| + ASSERT(stream_id != NULL); |
| { |
| JSONObject jsobj(&js); |
| jsobj.AddProperty("event", event); |
| + jsobj.AddProperty("streamId", stream_id); |
| } |
| const String& message = String::Handle(String::New(js.ToCString())); |
| - SendEvent(event->type(), message); |
| + SendEvent(stream_id, ServiceEvent::EventTypeToCString(event->type()), |
| + message); |
| } |
| @@ -611,10 +667,10 @@ void Service::EmbedderHandleMessage(EmbedderServiceHandler* handler, |
| Dart_ServiceRequestCallback callback = handler->callback(); |
| ASSERT(callback != NULL); |
| const char* r = NULL; |
| - const char* name = js->method(); |
| + const char* method = js->method(); |
| const char** keys = js->param_keys(); |
| const char** values = js->param_values(); |
| - r = callback(name, keys, values, js->num_params(), handler->user_data()); |
| + r = callback(method, keys, values, js->num_params(), handler->user_data()); |
| ASSERT(r != NULL); |
| // TODO(johnmccutchan): Allow for NULL returns? |
| TextBuffer* buffer = js->buffer(); |
| @@ -771,10 +827,11 @@ void Service::SendEchoEvent(Isolate* isolate, const char* text) { |
| event.AddProperty("text", text); |
| } |
| } |
| + jsobj.AddProperty("streamId", "_Echo"); |
| } |
| const String& message = String::Handle(String::New(js.ToCString())); |
| uint8_t data[] = {0, 128, 255}; |
| - SendEvent(message, data, sizeof(data)); |
| + SendEventWithData("_Echo", "_Echo", message, data, sizeof(data)); |
| } |
| @@ -2066,7 +2123,7 @@ static bool Resume(Isolate* isolate, JSONStream* js) { |
| isolate->message_handler()->set_pause_on_start(false); |
| JSONObject jsobj(js); |
| jsobj.AddProperty("type", "Success"); |
| - { |
| + if (Service::NeedsDebugEvents()) { |
| ServiceEvent event(isolate, ServiceEvent::kResume); |
| Service::HandleEvent(&event); |
| } |
| @@ -2262,13 +2319,18 @@ void Service::SendGraphEvent(Isolate* isolate) { |
| event.AddProperty("eventType", "_Graph"); |
| event.AddProperty("isolate", isolate); |
| } |
| + jsobj.AddProperty("streamId", "_Graph"); |
| } |
| const String& message = String::Handle(String::New(js.ToCString())); |
| - SendEvent(message, buffer, stream.bytes_written()); |
| + SendEventWithData("_Graph", "_Graph", message, |
| + buffer, stream.bytes_written()); |
| } |
| void Service::SendInspectEvent(Isolate* isolate, const Object& inspectee) { |
| + if (!Service::NeedsDebugEvents()) { |
| + return; |
| + } |
| ServiceEvent event(isolate, ServiceEvent::kInspect); |
| event.set_inspectee(&inspectee); |
| Service::HandleEvent(&event); |
| @@ -2550,7 +2612,7 @@ static const MethodParameter* set_name_params[] = { |
| static bool SetName(Isolate* isolate, JSONStream* js) { |
| isolate->set_debugger_name(js->LookupParam("name")); |
| - { |
| + if (Service::NeedsIsolateEvents()) { |
| ServiceEvent event(isolate, ServiceEvent::kIsolateUpdate); |
| Service::HandleEvent(&event); |
| } |