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

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

Issue 1232193003: Provide stdout and stderr output in the Observatory debugger. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: tidy up Created 5 years, 5 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) 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 "include/dart_native_api.h"
8 #include "platform/globals.h" 9 #include "platform/globals.h"
9 10
10 #include "vm/compiler.h" 11 #include "vm/compiler.h"
11 #include "vm/coverage.h" 12 #include "vm/coverage.h"
12 #include "vm/cpu.h" 13 #include "vm/cpu.h"
13 #include "vm/dart_api_impl.h" 14 #include "vm/dart_api_impl.h"
14 #include "vm/dart_entry.h" 15 #include "vm/dart_entry.h"
15 #include "vm/debugger.h" 16 #include "vm/debugger.h"
16 #include "vm/isolate.h" 17 #include "vm/isolate.h"
17 #include "vm/lockers.h" 18 #include "vm/lockers.h"
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
67 return zone->PrintToString("objects/%" Pd "", id); 68 return zone->PrintToString("objects/%" Pd "", id);
68 } 69 }
69 70
70 71
71 // TODO(johnmccutchan): Unify embedder service handler lists and their APIs. 72 // TODO(johnmccutchan): Unify embedder service handler lists and their APIs.
72 EmbedderServiceHandler* Service::isolate_service_handler_head_ = NULL; 73 EmbedderServiceHandler* Service::isolate_service_handler_head_ = NULL;
73 EmbedderServiceHandler* Service::root_service_handler_head_ = NULL; 74 EmbedderServiceHandler* Service::root_service_handler_head_ = NULL;
74 struct ServiceMethodDescriptor; 75 struct ServiceMethodDescriptor;
75 ServiceMethodDescriptor* FindMethod(const char* method_name); 76 ServiceMethodDescriptor* FindMethod(const char* method_name);
76 77
77 // TODO(turnidge): Build a general framework later. For now, we have 78
78 // a small set of well-known streams. 79 // These are the set of streams known to the core VM.
80 const char* const Service::kIsolateStreamId = "Isolate";
81 const char* const Service::kDebugStreamId = "Debug";
82 const char* const Service::kGCStreamId = "GC";
83 const char* const Service::kEchoStreamId = "_Echo";
84 const char* const Service::kGraphStreamId = "_Graph";
Cutch 2015/07/13 14:10:29 Would be nice if we had an array of streams (with
turnidge 2015/07/13 22:50:36 Done.
85
86
79 bool Service::needs_isolate_events_ = false; 87 bool Service::needs_isolate_events_ = false;
80 bool Service::needs_debug_events_ = false; 88 bool Service::needs_debug_events_ = false;
81 bool Service::needs_gc_events_ = false; 89 bool Service::needs_gc_events_ = false;
82 bool Service::needs_echo_events_ = false; 90 bool Service::needs_echo_events_ = false;
83 bool Service::needs_graph_events_ = false; 91 bool Service::needs_graph_events_ = false;
84 92
85 void Service::ListenStream(const char* stream_id) { 93 // Support for streams defined in embedders.
94 Dart_ServiceStreamListenCallback Service::stream_listen_callback_ = NULL;
95 Dart_ServiceStreamCancelCallback Service::stream_cancel_callback_ = NULL;
96
97
98 bool Service::ListenStream(const char* stream_id) {
86 if (FLAG_trace_service) { 99 if (FLAG_trace_service) {
87 OS::Print("vm-service: starting stream '%s'\n", 100 OS::Print("vm-service: starting stream '%s'\n",
88 stream_id); 101 stream_id);
89 } 102 }
90 if (strcmp(stream_id, "Isolate") == 0) { 103 if (strcmp(stream_id, kIsolateStreamId) == 0) {
91 needs_isolate_events_ = true; 104 needs_isolate_events_ = true;
92 } else if (strcmp(stream_id, "Debug") == 0) { 105 return true;
106 } else if (strcmp(stream_id, kDebugStreamId) == 0) {
93 needs_debug_events_ = true; 107 needs_debug_events_ = true;
94 } else if (strcmp(stream_id, "GC") == 0) { 108 return true;
109 } else if (strcmp(stream_id, kGCStreamId) == 0) {
95 needs_gc_events_ = true; 110 needs_gc_events_ = true;
96 } else if (strcmp(stream_id, "_Echo") == 0) { 111 return true;
112 } else if (strcmp(stream_id, kEchoStreamId) == 0) {
97 needs_echo_events_ = true; 113 needs_echo_events_ = true;
98 } else if (strcmp(stream_id, "_Graph") == 0) { 114 return true;
115 } else if (strcmp(stream_id, kGraphStreamId) == 0) {
99 needs_graph_events_ = true; 116 needs_graph_events_ = true;
100 } else { 117 return true;
101 UNREACHABLE(); 118 } else if (stream_listen_callback_) {
119 return (*stream_listen_callback_)(stream_id);
102 } 120 }
121 return false;
103 } 122 }
104 123
105 void Service::CancelStream(const char* stream_id) { 124 void Service::CancelStream(const char* stream_id) {
106 if (FLAG_trace_service) { 125 if (FLAG_trace_service) {
107 OS::Print("vm-service: stopping stream '%s'\n", 126 OS::Print("vm-service: stopping stream '%s'\n",
108 stream_id); 127 stream_id);
109 } 128 }
110 if (strcmp(stream_id, "Isolate") == 0) { 129 if (strcmp(stream_id, kIsolateStreamId) == 0) {
111 needs_isolate_events_ = false; 130 needs_isolate_events_ = false;
112 } else if (strcmp(stream_id, "Debug") == 0) { 131 } else if (strcmp(stream_id, kDebugStreamId) == 0) {
113 needs_debug_events_ = false; 132 needs_debug_events_ = false;
114 } else if (strcmp(stream_id, "GC") == 0) { 133 } else if (strcmp(stream_id, kGCStreamId) == 0) {
115 needs_gc_events_ = false; 134 needs_gc_events_ = false;
116 } else if (strcmp(stream_id, "_Echo") == 0) { 135 } else if (strcmp(stream_id, kEchoStreamId) == 0) {
117 needs_echo_events_ = false; 136 needs_echo_events_ = false;
118 } else if (strcmp(stream_id, "_Graph") == 0) { 137 } else if (strcmp(stream_id, kGraphStreamId) == 0) {
119 needs_graph_events_ = false; 138 needs_graph_events_ = false;
120 } else { 139 } else if (stream_cancel_callback_) {
121 UNREACHABLE(); 140 return (*stream_cancel_callback_)(stream_id);
122 } 141 }
123 } 142 }
124 143
125 static uint8_t* allocator(uint8_t* ptr, intptr_t old_size, intptr_t new_size) { 144 static uint8_t* allocator(uint8_t* ptr, intptr_t old_size, intptr_t new_size) {
126 void* new_ptr = realloc(reinterpret_cast<void*>(ptr), new_size); 145 void* new_ptr = realloc(reinterpret_cast<void*>(ptr), new_size);
127 return reinterpret_cast<uint8_t*>(new_ptr); 146 return reinterpret_cast<uint8_t*>(new_ptr);
128 } 147 }
129 148
130 static void PrintMissingParamError(JSONStream* js, 149 static void PrintMissingParamError(JSONStream* js,
131 const char* param) { 150 const char* param) {
(...skipping 439 matching lines...) Expand 10 before | Expand all | Expand 10 after
571 OS::Print( 590 OS::Print(
572 "vm-service: Pushing event of type %s to stream %s, len %" Pd "\n", 591 "vm-service: Pushing event of type %s to stream %s, len %" Pd "\n",
573 event_type, stream_id, len); 592 event_type, stream_id, len);
574 } 593 }
575 // TODO(turnidge): For now we ignore failure to send an event. Revisit? 594 // TODO(turnidge): For now we ignore failure to send an event. Revisit?
576 PortMap::PostMessage( 595 PortMap::PostMessage(
577 new Message(ServiceIsolate::Port(), data, len, Message::kNormalPriority)); 596 new Message(ServiceIsolate::Port(), data, len, Message::kNormalPriority));
578 } 597 }
579 598
580 599
600 // TODO(turnidge): Rewrite this method to use Post_CObject instead.
581 void Service::SendEventWithData(const char* stream_id, 601 void Service::SendEventWithData(const char* stream_id,
582 const char* event_type, 602 const char* event_type,
583 const String& meta, 603 const String& meta,
584 const uint8_t* data, 604 const uint8_t* data,
585 intptr_t size) { 605 intptr_t size) {
586 // Bitstream: [meta data size (big-endian 64 bit)] [meta data (UTF-8)] [data] 606 // Bitstream: [meta data size (big-endian 64 bit)] [meta data (UTF-8)] [data]
587 const intptr_t meta_bytes = Utf8::Length(meta); 607 const intptr_t meta_bytes = Utf8::Length(meta);
588 const intptr_t total_bytes = sizeof(uint64_t) + meta_bytes + size; 608 const intptr_t total_bytes = sizeof(uint64_t) + meta_bytes + size;
589 const TypedData& message = TypedData::Handle( 609 const TypedData& message = TypedData::Handle(
590 TypedData::New(kTypedDataUint8ArrayCid, total_bytes)); 610 TypedData::New(kTypedDataUint8ArrayCid, total_bytes));
(...skipping 15 matching lines...) Expand all
606 } 626 }
607 ASSERT(offset == total_bytes); 627 ASSERT(offset == total_bytes);
608 SendEvent(stream_id, event_type, message); 628 SendEvent(stream_id, event_type, message);
609 } 629 }
610 630
611 631
612 void Service::HandleEvent(ServiceEvent* event) { 632 void Service::HandleEvent(ServiceEvent* event) {
613 if (ServiceIsolate::IsServiceIsolateDescendant(event->isolate())) { 633 if (ServiceIsolate::IsServiceIsolateDescendant(event->isolate())) {
614 return; 634 return;
615 } 635 }
636 if (!ServiceIsolate::IsRunning()) {
637 return;
638 }
616 JSONStream js; 639 JSONStream js;
617 const char* stream_id = event->stream_id(); 640 const char* stream_id = event->stream_id();
618 ASSERT(stream_id != NULL); 641 ASSERT(stream_id != NULL);
619 { 642 {
620 JSONObject jsobj(&js); 643 JSONObject jsobj(&js);
621 jsobj.AddProperty("event", event); 644 jsobj.AddProperty("event", event);
622 jsobj.AddProperty("streamId", stream_id); 645 jsobj.AddProperty("streamId", stream_id);
623 } 646 }
624 const String& message = String::Handle(String::New(js.ToCString())); 647
625 SendEvent(stream_id, ServiceEvent::EventTypeToCString(event->type()), 648 // Message is of the format [<stream id>, <json string>].
626 message); 649 //
650 // Build the event message in the C heap to avoid dart heap
651 // allocation. This method can be called while we have acquired a
652 // direct pointer to typed data, so we can't allocate here.
653 Dart_CObject list_cobj;
654 Dart_CObject* list_values[2];
655 list_cobj.type = Dart_CObject_kArray;
656 list_cobj.value.as_array.length = 2;
657 list_cobj.value.as_array.values = list_values;
658
659 Dart_CObject stream_id_cobj;
660 stream_id_cobj.type = Dart_CObject_kString;
661 stream_id_cobj.value.as_string = const_cast<char*>(stream_id);
662 list_values[0] = &stream_id_cobj;
663
664 Dart_CObject json_cobj;
665 json_cobj.type = Dart_CObject_kString;
666 json_cobj.value.as_string = const_cast<char*>(js.ToCString());
667 list_values[1] = &json_cobj;
668
669 if (FLAG_trace_service) {
670 OS::Print(
671 "vm-service: Pushing event of type %s to stream %s\n",
672 event->KindAsCString(), stream_id);
673 }
674
675 Dart_PostCObject(ServiceIsolate::Port(), &list_cobj);
627 } 676 }
628 677
629 678
630 class EmbedderServiceHandler { 679 class EmbedderServiceHandler {
631 public: 680 public:
632 explicit EmbedderServiceHandler(const char* name) : name_(NULL), 681 explicit EmbedderServiceHandler(const char* name) : name_(NULL),
633 callback_(NULL), 682 callback_(NULL),
634 user_data_(NULL), 683 user_data_(NULL),
635 next_(NULL) { 684 next_(NULL) {
636 ASSERT(name != NULL); 685 ASSERT(name != NULL);
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after
740 handler = new EmbedderServiceHandler(name); 789 handler = new EmbedderServiceHandler(name);
741 handler->set_callback(callback); 790 handler->set_callback(callback);
742 handler->set_user_data(user_data); 791 handler->set_user_data(user_data);
743 792
744 // Insert into root_service_handler_head_ list. 793 // Insert into root_service_handler_head_ list.
745 handler->set_next(root_service_handler_head_); 794 handler->set_next(root_service_handler_head_);
746 root_service_handler_head_ = handler; 795 root_service_handler_head_ = handler;
747 } 796 }
748 797
749 798
799 void Service::SetEmbedderStreamCallbacks(
800 Dart_ServiceStreamListenCallback listen_callback,
801 Dart_ServiceStreamCancelCallback cancel_callback) {
802 stream_listen_callback_ = listen_callback;
803 stream_cancel_callback_ = cancel_callback;
804 }
805
806
750 EmbedderServiceHandler* Service::FindRootEmbedderHandler( 807 EmbedderServiceHandler* Service::FindRootEmbedderHandler(
751 const char* name) { 808 const char* name) {
752 EmbedderServiceHandler* current = root_service_handler_head_; 809 EmbedderServiceHandler* current = root_service_handler_head_;
753 while (current != NULL) { 810 while (current != NULL) {
754 if (strcmp(name, current->name()) == 0) { 811 if (strcmp(name, current->name()) == 0) {
755 return current; 812 return current;
756 } 813 }
757 current = current->next(); 814 current = current->next();
758 } 815 }
759 return NULL; 816 return NULL;
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
823 JSONObject jsobj(&js); 880 JSONObject jsobj(&js);
824 { 881 {
825 JSONObject event(&jsobj, "event"); 882 JSONObject event(&jsobj, "event");
826 event.AddProperty("type", "Event"); 883 event.AddProperty("type", "Event");
827 event.AddProperty("kind", "_Echo"); 884 event.AddProperty("kind", "_Echo");
828 event.AddProperty("isolate", isolate); 885 event.AddProperty("isolate", isolate);
829 if (text != NULL) { 886 if (text != NULL) {
830 event.AddProperty("text", text); 887 event.AddProperty("text", text);
831 } 888 }
832 } 889 }
833 jsobj.AddProperty("streamId", "_Echo"); 890 jsobj.AddProperty("streamId", kEchoStreamId);
834 } 891 }
835 const String& message = String::Handle(String::New(js.ToCString())); 892 const String& message = String::Handle(String::New(js.ToCString()));
836 uint8_t data[] = {0, 128, 255}; 893 uint8_t data[] = {0, 128, 255};
837 SendEventWithData("_Echo", "_Echo", message, data, sizeof(data)); 894 SendEventWithData(kEchoStreamId, "_Echo", message, data, sizeof(data));
838 } 895 }
839 896
840 897
841 static bool TriggerEchoEvent(Isolate* isolate, JSONStream* js) { 898 static bool TriggerEchoEvent(Isolate* isolate, JSONStream* js) {
842 if (Service::NeedsEchoEvents()) { 899 if (Service::NeedsEchoEvents()) {
843 Service::SendEchoEvent(isolate, js->LookupParam("text")); 900 Service::SendEchoEvent(isolate, js->LookupParam("text"));
844 } 901 }
845 JSONObject jsobj(js); 902 JSONObject jsobj(js);
846 return HandleCommonEcho(&jsobj, js); 903 return HandleCommonEcho(&jsobj, js);
847 } 904 }
(...skipping 1494 matching lines...) Expand 10 before | Expand all | Expand 10 after
2342 { 2399 {
2343 JSONObject event(&jsobj, "event"); 2400 JSONObject event(&jsobj, "event");
2344 event.AddProperty("type", "Event"); 2401 event.AddProperty("type", "Event");
2345 event.AddProperty("kind", "_Graph"); 2402 event.AddProperty("kind", "_Graph");
2346 event.AddProperty("isolate", isolate); 2403 event.AddProperty("isolate", isolate);
2347 2404
2348 event.AddProperty("chunkIndex", i); 2405 event.AddProperty("chunkIndex", i);
2349 event.AddProperty("chunkCount", num_chunks); 2406 event.AddProperty("chunkCount", num_chunks);
2350 event.AddProperty("nodeCount", node_count); 2407 event.AddProperty("nodeCount", node_count);
2351 } 2408 }
2352 jsobj.AddProperty("streamId", "_Graph"); 2409 jsobj.AddProperty("streamId", kGraphStreamId);
2353 } 2410 }
2354 2411
2355 const String& message = String::Handle(String::New(js.ToCString())); 2412 const String& message = String::Handle(String::New(js.ToCString()));
2356 2413
2357 uint8_t* chunk_start = buffer + (i * kChunkSize); 2414 uint8_t* chunk_start = buffer + (i * kChunkSize);
2358 intptr_t chunk_size = (i + 1 == num_chunks) 2415 intptr_t chunk_size = (i + 1 == num_chunks)
2359 ? stream.bytes_written() - (i * kChunkSize) 2416 ? stream.bytes_written() - (i * kChunkSize)
2360 : kChunkSize; 2417 : kChunkSize;
2361 2418
2362 SendEventWithData("_Graph", "_Graph", message, chunk_start, chunk_size); 2419 SendEventWithData(kGraphStreamId, "_Graph", message,
2420 chunk_start, chunk_size);
2363 } 2421 }
2364 } 2422 }
2365 2423
2366 2424
2367 void Service::SendInspectEvent(Isolate* isolate, const Object& inspectee) { 2425 void Service::SendInspectEvent(Isolate* isolate, const Object& inspectee) {
2368 if (!Service::NeedsDebugEvents()) { 2426 if (!Service::NeedsDebugEvents()) {
2369 return; 2427 return;
2370 } 2428 }
2371 ServiceEvent event(isolate, ServiceEvent::kInspect); 2429 ServiceEvent event(isolate, ServiceEvent::kInspect);
2372 event.set_inspectee(&inspectee); 2430 event.set_inspectee(&inspectee);
2373 Service::HandleEvent(&event); 2431 Service::HandleEvent(&event);
2374 } 2432 }
2375 2433
2376 2434
2435 void Service::SendEmbedderEvent(Isolate* isolate,
2436 const char* stream_id,
2437 const char* event_kind,
2438 const uint8_t* bytes,
2439 intptr_t bytes_len) {
2440 if (!Service::NeedsDebugEvents()) {
2441 return;
2442 }
2443 ServiceEvent event(isolate, ServiceEvent::kEmbedder);
2444 event.set_embedder_kind(event_kind);
2445 event.set_embedder_stream_id(stream_id);
2446 event.set_bytes(bytes, bytes_len);
2447 Service::HandleEvent(&event);
2448 }
2449
2450
2377 class ContainsAddressVisitor : public FindObjectVisitor { 2451 class ContainsAddressVisitor : public FindObjectVisitor {
2378 public: 2452 public:
2379 ContainsAddressVisitor(Isolate* isolate, uword addr) 2453 ContainsAddressVisitor(Isolate* isolate, uword addr)
2380 : FindObjectVisitor(isolate), addr_(addr) { } 2454 : FindObjectVisitor(isolate), addr_(addr) { }
2381 virtual ~ContainsAddressVisitor() { } 2455 virtual ~ContainsAddressVisitor() { }
2382 2456
2383 virtual uword filter_addr() const { return addr_; } 2457 virtual uword filter_addr() const { return addr_; }
2384 2458
2385 virtual bool FindObject(RawObject* obj) const { 2459 virtual bool FindObject(RawObject* obj) const {
2386 // Free list elements are not real objects, so skip them. 2460 // Free list elements are not real objects, so skip them.
(...skipping 460 matching lines...) Expand 10 before | Expand all | Expand 10 after
2847 ServiceMethodDescriptor& method = service_methods_[i]; 2921 ServiceMethodDescriptor& method = service_methods_[i];
2848 if (strcmp(method_name, method.name) == 0) { 2922 if (strcmp(method_name, method.name) == 0) {
2849 return &method; 2923 return &method;
2850 } 2924 }
2851 } 2925 }
2852 return NULL; 2926 return NULL;
2853 } 2927 }
2854 2928
2855 2929
2856 } // namespace dart 2930 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698