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

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

Issue 1166433008: 2nd attempt at adding streamListen/streamCancel to the service protocol. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: fix context objects Created 5 years, 6 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 | « runtime/vm/service.h ('k') | runtime/vm/service/client.dart » ('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 (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, 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/service.h" 5 #include "vm/service.h"
6 6
7 #include "include/dart_api.h" 7 #include "include/dart_api.h"
8 #include "platform/globals.h" 8 #include "platform/globals.h"
9 9
10 #include "vm/compiler.h" 10 #include "vm/compiler.h"
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
67 return zone->PrintToString("objects/%" Pd "", id); 67 return zone->PrintToString("objects/%" Pd "", id);
68 } 68 }
69 69
70 70
71 // TODO(johnmccutchan): Unify embedder service handler lists and their APIs. 71 // TODO(johnmccutchan): Unify embedder service handler lists and their APIs.
72 EmbedderServiceHandler* Service::isolate_service_handler_head_ = NULL; 72 EmbedderServiceHandler* Service::isolate_service_handler_head_ = NULL;
73 EmbedderServiceHandler* Service::root_service_handler_head_ = NULL; 73 EmbedderServiceHandler* Service::root_service_handler_head_ = NULL;
74 struct ServiceMethodDescriptor; 74 struct ServiceMethodDescriptor;
75 ServiceMethodDescriptor* FindMethod(const char* method_name); 75 ServiceMethodDescriptor* FindMethod(const char* method_name);
76 76
77 // TODO(turnidge): Build a general framework later. For now, we have
78 // a small set of well-known streams.
79 bool Service::needs_isolate_events_ = false;
80 bool Service::needs_debug_events_ = false;
81 bool Service::needs_gc_events_ = false;
82 bool Service::needs_echo_events_ = false;
83 bool Service::needs_graph_events_ = false;
84
85 void Service::ListenStream(const char* stream_id) {
86 if (FLAG_trace_service) {
87 OS::Print("vm-service: starting stream '%s'\n",
88 stream_id);
89 }
90 if (strcmp(stream_id, "Isolate") == 0) {
91 needs_isolate_events_ = true;
92 } else if (strcmp(stream_id, "Debug") == 0) {
93 needs_debug_events_ = true;
94 } else if (strcmp(stream_id, "GC") == 0) {
95 needs_gc_events_ = true;
96 } else if (strcmp(stream_id, "_Echo") == 0) {
97 needs_echo_events_ = true;
98 } else if (strcmp(stream_id, "_Graph") == 0) {
99 needs_graph_events_ = true;
100 } else {
101 UNREACHABLE();
102 }
103 }
104
105 void Service::CancelStream(const char* stream_id) {
106 if (FLAG_trace_service) {
107 OS::Print("vm-service: stopping stream '%s'\n",
108 stream_id);
109 }
110 if (strcmp(stream_id, "Isolate") == 0) {
111 needs_isolate_events_ = false;
112 } else if (strcmp(stream_id, "Debug") == 0) {
113 needs_debug_events_ = false;
114 } else if (strcmp(stream_id, "GC") == 0) {
115 needs_gc_events_ = false;
116 } else if (strcmp(stream_id, "_Echo") == 0) {
117 needs_echo_events_ = false;
118 } else if (strcmp(stream_id, "_Graph") == 0) {
119 needs_graph_events_ = false;
120 } else {
121 UNREACHABLE();
122 }
123 }
124
77 static uint8_t* allocator(uint8_t* ptr, intptr_t old_size, intptr_t new_size) { 125 static uint8_t* allocator(uint8_t* ptr, intptr_t old_size, intptr_t new_size) {
78 void* new_ptr = realloc(reinterpret_cast<void*>(ptr), new_size); 126 void* new_ptr = realloc(reinterpret_cast<void*>(ptr), new_size);
79 return reinterpret_cast<uint8_t*>(new_ptr); 127 return reinterpret_cast<uint8_t*>(new_ptr);
80 } 128 }
81 129
82 static void PrintMissingParamError(JSONStream* js, 130 static void PrintMissingParamError(JSONStream* js,
83 const char* param) { 131 const char* param) {
84 js->PrintError(kInvalidParams, 132 js->PrintError(kInvalidParams,
85 "%s expects the '%s' parameter", js->method(), param); 133 "%s expects the '%s' parameter", js->method(), param);
86 } 134 }
(...skipping 403 matching lines...) Expand 10 before | Expand all | Expand 10 after
490 InvokeMethod(isolate, msg_instance); 538 InvokeMethod(isolate, msg_instance);
491 } 539 }
492 540
493 541
494 void Service::HandleIsolateMessage(Isolate* isolate, const Array& msg) { 542 void Service::HandleIsolateMessage(Isolate* isolate, const Array& msg) {
495 ASSERT(isolate != NULL); 543 ASSERT(isolate != NULL);
496 InvokeMethod(isolate, msg); 544 InvokeMethod(isolate, msg);
497 } 545 }
498 546
499 547
500 bool Service::NeedsEvents() { 548 void Service::SendEvent(const char* stream_id,
501 return ServiceIsolate::IsRunning(); 549 const char* event_type,
502 } 550 const Object& event_message) {
503
504
505 void Service::SendEvent(intptr_t eventType,
506 const Object& eventMessage) {
507 ASSERT(!ServiceIsolate::IsServiceIsolateDescendant(Isolate::Current())); 551 ASSERT(!ServiceIsolate::IsServiceIsolateDescendant(Isolate::Current()));
508 if (!ServiceIsolate::IsRunning()) { 552 if (!ServiceIsolate::IsRunning()) {
509 return; 553 return;
510 } 554 }
511 Isolate* isolate = Isolate::Current(); 555 Isolate* isolate = Isolate::Current();
512 ASSERT(isolate != NULL); 556 ASSERT(isolate != NULL);
513 HANDLESCOPE(isolate); 557 HANDLESCOPE(isolate);
514 558
559 const Array& list = Array::Handle(Array::New(2));
560 ASSERT(!list.IsNull());
561 const String& stream_id_str = String::Handle(String::New(stream_id));
562 list.SetAt(0, stream_id_str);
563 list.SetAt(1, event_message);
564
515 // Push the event to port_. 565 // Push the event to port_.
516 uint8_t* data = NULL; 566 uint8_t* data = NULL;
517 MessageWriter writer(&data, &allocator, false); 567 MessageWriter writer(&data, &allocator, false);
518 writer.WriteMessage(eventMessage); 568 writer.WriteMessage(list);
519 intptr_t len = writer.BytesWritten(); 569 intptr_t len = writer.BytesWritten();
520 if (FLAG_trace_service) { 570 if (FLAG_trace_service) {
521 OS::Print("vm-service: Pushing event of type %" Pd ", len %" Pd "\n", 571 OS::Print(
522 eventType, len); 572 "vm-service: Pushing event of type %s to stream %s, len %" Pd "\n",
573 event_type, stream_id, len);
523 } 574 }
524 // TODO(turnidge): For now we ignore failure to send an event. Revisit? 575 // TODO(turnidge): For now we ignore failure to send an event. Revisit?
525 PortMap::PostMessage( 576 PortMap::PostMessage(
526 new Message(ServiceIsolate::Port(), data, len, Message::kNormalPriority)); 577 new Message(ServiceIsolate::Port(), data, len, Message::kNormalPriority));
527 } 578 }
528 579
529 580
530 void Service::SendEvent(const String& meta, 581 void Service::SendEventWithData(const char* stream_id,
531 const uint8_t* data, 582 const char* event_type,
532 intptr_t size) { 583 const String& meta,
584 const uint8_t* data,
585 intptr_t size) {
533 // Bitstream: [meta data size (big-endian 64 bit)] [meta data (UTF-8)] [data] 586 // Bitstream: [meta data size (big-endian 64 bit)] [meta data (UTF-8)] [data]
534 const intptr_t meta_bytes = Utf8::Length(meta); 587 const intptr_t meta_bytes = Utf8::Length(meta);
535 const intptr_t total_bytes = sizeof(uint64_t) + meta_bytes + size; 588 const intptr_t total_bytes = sizeof(uint64_t) + meta_bytes + size;
536 const TypedData& message = TypedData::Handle( 589 const TypedData& message = TypedData::Handle(
537 TypedData::New(kTypedDataUint8ArrayCid, total_bytes)); 590 TypedData::New(kTypedDataUint8ArrayCid, total_bytes));
538 intptr_t offset = 0; 591 intptr_t offset = 0;
539 // TODO(koda): Rename these methods SetHostUint64, etc. 592 // TODO(koda): Rename these methods SetHostUint64, etc.
540 message.SetUint64(0, Utils::HostToBigEndian64(meta_bytes)); 593 message.SetUint64(0, Utils::HostToBigEndian64(meta_bytes));
541 offset += sizeof(uint64_t); 594 offset += sizeof(uint64_t);
542 { 595 {
543 NoSafepointScope no_safepoint; 596 NoSafepointScope no_safepoint;
544 meta.ToUTF8(static_cast<uint8_t*>(message.DataAddr(offset)), meta_bytes); 597 meta.ToUTF8(static_cast<uint8_t*>(message.DataAddr(offset)), meta_bytes);
545 offset += meta_bytes; 598 offset += meta_bytes;
546 } 599 }
547 // TODO(koda): It would be nice to avoid this copy (requires changes to 600 // TODO(koda): It would be nice to avoid this copy (requires changes to
548 // MessageWriter code). 601 // MessageWriter code).
549 { 602 {
550 NoSafepointScope no_safepoint; 603 NoSafepointScope no_safepoint;
551 memmove(message.DataAddr(offset), data, size); 604 memmove(message.DataAddr(offset), data, size);
552 offset += size; 605 offset += size;
553 } 606 }
554 ASSERT(offset == total_bytes); 607 ASSERT(offset == total_bytes);
555 // TODO(turnidge): Pass the real eventType here. 608 SendEvent(stream_id, event_type, message);
556 SendEvent(0, message);
557 } 609 }
558 610
559 611
560 void Service::HandleEvent(ServiceEvent* event) { 612 void Service::HandleEvent(ServiceEvent* event) {
561 if (ServiceIsolate::IsServiceIsolateDescendant(event->isolate())) { 613 if (ServiceIsolate::IsServiceIsolateDescendant(event->isolate())) {
562 return; 614 return;
563 } 615 }
564 JSONStream js; 616 JSONStream js;
617 const char* stream_id = event->stream_id();
618 ASSERT(stream_id != NULL);
565 { 619 {
566 JSONObject jsobj(&js); 620 JSONObject jsobj(&js);
567 jsobj.AddProperty("event", event); 621 jsobj.AddProperty("event", event);
622 jsobj.AddProperty("streamId", stream_id);
568 } 623 }
569 const String& message = String::Handle(String::New(js.ToCString())); 624 const String& message = String::Handle(String::New(js.ToCString()));
570 SendEvent(event->type(), message); 625 SendEvent(stream_id, ServiceEvent::EventTypeToCString(event->type()),
626 message);
571 } 627 }
572 628
573 629
574 class EmbedderServiceHandler { 630 class EmbedderServiceHandler {
575 public: 631 public:
576 explicit EmbedderServiceHandler(const char* name) : name_(NULL), 632 explicit EmbedderServiceHandler(const char* name) : name_(NULL),
577 callback_(NULL), 633 callback_(NULL),
578 user_data_(NULL), 634 user_data_(NULL),
579 next_(NULL) { 635 next_(NULL) {
580 ASSERT(name != NULL); 636 ASSERT(name != NULL);
(...skipping 28 matching lines...) Expand all
609 EmbedderServiceHandler* next_; 665 EmbedderServiceHandler* next_;
610 }; 666 };
611 667
612 668
613 void Service::EmbedderHandleMessage(EmbedderServiceHandler* handler, 669 void Service::EmbedderHandleMessage(EmbedderServiceHandler* handler,
614 JSONStream* js) { 670 JSONStream* js) {
615 ASSERT(handler != NULL); 671 ASSERT(handler != NULL);
616 Dart_ServiceRequestCallback callback = handler->callback(); 672 Dart_ServiceRequestCallback callback = handler->callback();
617 ASSERT(callback != NULL); 673 ASSERT(callback != NULL);
618 const char* r = NULL; 674 const char* r = NULL;
619 const char* name = js->method(); 675 const char* method = js->method();
620 const char** keys = js->param_keys(); 676 const char** keys = js->param_keys();
621 const char** values = js->param_values(); 677 const char** values = js->param_values();
622 r = callback(name, keys, values, js->num_params(), handler->user_data()); 678 r = callback(method, keys, values, js->num_params(), handler->user_data());
623 ASSERT(r != NULL); 679 ASSERT(r != NULL);
624 // TODO(johnmccutchan): Allow for NULL returns? 680 // TODO(johnmccutchan): Allow for NULL returns?
625 TextBuffer* buffer = js->buffer(); 681 TextBuffer* buffer = js->buffer();
626 buffer->AddString(r); 682 buffer->AddString(r);
627 free(const_cast<char*>(r)); 683 free(const_cast<char*>(r));
628 } 684 }
629 685
630 686
631 void Service::RegisterIsolateEmbedderCallback( 687 void Service::RegisterIsolateEmbedderCallback(
632 const char* name, 688 const char* name,
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after
767 JSONObject jsobj(&js); 823 JSONObject jsobj(&js);
768 { 824 {
769 JSONObject event(&jsobj, "event"); 825 JSONObject event(&jsobj, "event");
770 event.AddProperty("type", "Event"); 826 event.AddProperty("type", "Event");
771 event.AddProperty("kind", "_Echo"); 827 event.AddProperty("kind", "_Echo");
772 event.AddProperty("isolate", isolate); 828 event.AddProperty("isolate", isolate);
773 if (text != NULL) { 829 if (text != NULL) {
774 event.AddProperty("text", text); 830 event.AddProperty("text", text);
775 } 831 }
776 } 832 }
833 jsobj.AddProperty("streamId", "_Echo");
777 } 834 }
778 const String& message = String::Handle(String::New(js.ToCString())); 835 const String& message = String::Handle(String::New(js.ToCString()));
779 uint8_t data[] = {0, 128, 255}; 836 uint8_t data[] = {0, 128, 255};
780 SendEvent(message, data, sizeof(data)); 837 SendEventWithData("_Echo", "_Echo", message, data, sizeof(data));
781 } 838 }
782 839
783 840
784 static bool TriggerEchoEvent(Isolate* isolate, JSONStream* js) { 841 static bool TriggerEchoEvent(Isolate* isolate, JSONStream* js) {
785 Service::SendEchoEvent(isolate, js->LookupParam("text")); 842 if (Service::NeedsEchoEvents()) {
843 Service::SendEchoEvent(isolate, js->LookupParam("text"));
844 }
786 JSONObject jsobj(js); 845 JSONObject jsobj(js);
787 return HandleCommonEcho(&jsobj, js); 846 return HandleCommonEcho(&jsobj, js);
788 } 847 }
789 848
790 849
791 static bool DumpIdZone(Isolate* isolate, JSONStream* js) { 850 static bool DumpIdZone(Isolate* isolate, JSONStream* js) {
792 // TODO(johnmccutchan): Respect _idZone parameter passed to RPC. For now, 851 // TODO(johnmccutchan): Respect _idZone parameter passed to RPC. For now,
793 // always send the ObjectIdRing. 852 // always send the ObjectIdRing.
794 // 853 //
795 ObjectIdRing* ring = isolate->object_id_ring(); 854 ObjectIdRing* ring = isolate->object_id_ring();
(...skipping 1288 matching lines...) Expand 10 before | Expand all | Expand 10 after
2084 static const MethodParameter* resume_params[] = { 2143 static const MethodParameter* resume_params[] = {
2085 ISOLATE_PARAMETER, 2144 ISOLATE_PARAMETER,
2086 NULL, 2145 NULL,
2087 }; 2146 };
2088 2147
2089 2148
2090 static bool Resume(Isolate* isolate, JSONStream* js) { 2149 static bool Resume(Isolate* isolate, JSONStream* js) {
2091 const char* step_param = js->LookupParam("step"); 2150 const char* step_param = js->LookupParam("step");
2092 if (isolate->message_handler()->paused_on_start()) { 2151 if (isolate->message_handler()->paused_on_start()) {
2093 isolate->message_handler()->set_pause_on_start(false); 2152 isolate->message_handler()->set_pause_on_start(false);
2094 { 2153 if (Service::NeedsDebugEvents()) {
2095 ServiceEvent event(isolate, ServiceEvent::kResume); 2154 ServiceEvent event(isolate, ServiceEvent::kResume);
2096 Service::HandleEvent(&event); 2155 Service::HandleEvent(&event);
2097 } 2156 }
2098 PrintSuccess(js); 2157 PrintSuccess(js);
2099 return true; 2158 return true;
2100 } 2159 }
2101 if (isolate->message_handler()->paused_on_exit()) { 2160 if (isolate->message_handler()->paused_on_exit()) {
2102 isolate->message_handler()->set_pause_on_exit(false); 2161 isolate->message_handler()->set_pause_on_exit(false);
2103 // We don't send a resume event because we will be exiting. 2162 // We don't send a resume event because we will be exiting.
2104 PrintSuccess(js); 2163 PrintSuccess(js);
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after
2253 } 2312 }
2254 2313
2255 2314
2256 static const MethodParameter* request_heap_snapshot_params[] = { 2315 static const MethodParameter* request_heap_snapshot_params[] = {
2257 ISOLATE_PARAMETER, 2316 ISOLATE_PARAMETER,
2258 NULL, 2317 NULL,
2259 }; 2318 };
2260 2319
2261 2320
2262 static bool RequestHeapSnapshot(Isolate* isolate, JSONStream* js) { 2321 static bool RequestHeapSnapshot(Isolate* isolate, JSONStream* js) {
2263 Service::SendGraphEvent(isolate); 2322 if (Service::NeedsGraphEvents()) {
2323 Service::SendGraphEvent(isolate);
2324 }
2264 // TODO(koda): Provide some id that ties this request to async response(s). 2325 // TODO(koda): Provide some id that ties this request to async response(s).
2265 JSONObject jsobj(js); 2326 JSONObject jsobj(js);
2266 jsobj.AddProperty("type", "OK"); 2327 jsobj.AddProperty("type", "OK");
2267 return true; 2328 return true;
2268 } 2329 }
2269 2330
2270 2331
2271 void Service::SendGraphEvent(Isolate* isolate) { 2332 void Service::SendGraphEvent(Isolate* isolate) {
2272 uint8_t* buffer = NULL; 2333 uint8_t* buffer = NULL;
2273 WriteStream stream(&buffer, &allocator, 1 * MB); 2334 WriteStream stream(&buffer, &allocator, 1 * MB);
(...skipping 22 matching lines...) Expand all
2296 jsobj.AddProperty("streamId", "_Graph"); 2357 jsobj.AddProperty("streamId", "_Graph");
2297 } 2358 }
2298 2359
2299 const String& message = String::Handle(String::New(js.ToCString())); 2360 const String& message = String::Handle(String::New(js.ToCString()));
2300 2361
2301 uint8_t* chunk_start = buffer + (i * kChunkSize); 2362 uint8_t* chunk_start = buffer + (i * kChunkSize);
2302 intptr_t chunk_size = (i + 1 == num_chunks) 2363 intptr_t chunk_size = (i + 1 == num_chunks)
2303 ? stream.bytes_written() - (i * kChunkSize) 2364 ? stream.bytes_written() - (i * kChunkSize)
2304 : kChunkSize; 2365 : kChunkSize;
2305 2366
2306 SendEvent(message, chunk_start, chunk_size); 2367 SendEventWithData("_Graph", "_Graph", message, chunk_start, chunk_size);
2307 } 2368 }
2308 } 2369 }
2309 2370
2310 2371
2311 void Service::SendInspectEvent(Isolate* isolate, const Object& inspectee) { 2372 void Service::SendInspectEvent(Isolate* isolate, const Object& inspectee) {
2373 if (!Service::NeedsDebugEvents()) {
2374 return;
2375 }
2312 ServiceEvent event(isolate, ServiceEvent::kInspect); 2376 ServiceEvent event(isolate, ServiceEvent::kInspect);
2313 event.set_inspectee(&inspectee); 2377 event.set_inspectee(&inspectee);
2314 Service::HandleEvent(&event); 2378 Service::HandleEvent(&event);
2315 } 2379 }
2316 2380
2317 2381
2318 class ContainsAddressVisitor : public FindObjectVisitor { 2382 class ContainsAddressVisitor : public FindObjectVisitor {
2319 public: 2383 public:
2320 ContainsAddressVisitor(Isolate* isolate, uword addr) 2384 ContainsAddressVisitor(Isolate* isolate, uword addr)
2321 : FindObjectVisitor(isolate), addr_(addr) { } 2385 : FindObjectVisitor(isolate), addr_(addr) { }
(...skipping 304 matching lines...) Expand 10 before | Expand all | Expand 10 after
2626 2690
2627 static const MethodParameter* set_name_params[] = { 2691 static const MethodParameter* set_name_params[] = {
2628 ISOLATE_PARAMETER, 2692 ISOLATE_PARAMETER,
2629 new MethodParameter("name", true), 2693 new MethodParameter("name", true),
2630 NULL, 2694 NULL,
2631 }; 2695 };
2632 2696
2633 2697
2634 static bool SetName(Isolate* isolate, JSONStream* js) { 2698 static bool SetName(Isolate* isolate, JSONStream* js) {
2635 isolate->set_debugger_name(js->LookupParam("name")); 2699 isolate->set_debugger_name(js->LookupParam("name"));
2636 { 2700 if (Service::NeedsIsolateEvents()) {
2637 ServiceEvent event(isolate, ServiceEvent::kIsolateUpdate); 2701 ServiceEvent event(isolate, ServiceEvent::kIsolateUpdate);
2638 Service::HandleEvent(&event); 2702 Service::HandleEvent(&event);
2639 } 2703 }
2640 PrintSuccess(js); 2704 PrintSuccess(js);
2641 return true; 2705 return true;
2642 } 2706 }
2643 2707
2644 2708
2645 static ServiceMethodDescriptor service_methods_[] = { 2709 static ServiceMethodDescriptor service_methods_[] = {
2646 { "_dumpIdZone", DumpIdZone, NULL }, 2710 { "_dumpIdZone", DumpIdZone, NULL },
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
2734 ServiceMethodDescriptor& method = service_methods_[i]; 2798 ServiceMethodDescriptor& method = service_methods_[i];
2735 if (strcmp(method_name, method.name) == 0) { 2799 if (strcmp(method_name, method.name) == 0) {
2736 return &method; 2800 return &method;
2737 } 2801 }
2738 } 2802 }
2739 return NULL; 2803 return NULL;
2740 } 2804 }
2741 2805
2742 2806
2743 } // namespace dart 2807 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/service.h ('k') | runtime/vm/service/client.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698