OLD | NEW |
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 26 matching lines...) Expand all Loading... |
37 namespace dart { | 37 namespace dart { |
38 | 38 |
39 DECLARE_FLAG(bool, trace_service); | 39 DECLARE_FLAG(bool, trace_service); |
40 DECLARE_FLAG(bool, trace_service_pause_events); | 40 DECLARE_FLAG(bool, trace_service_pause_events); |
41 DECLARE_FLAG(bool, enable_type_checks); | 41 DECLARE_FLAG(bool, enable_type_checks); |
42 DECLARE_FLAG(bool, enable_asserts); | 42 DECLARE_FLAG(bool, enable_asserts); |
43 | 43 |
44 // TODO(johnmccutchan): Unify embedder service handler lists and their APIs. | 44 // TODO(johnmccutchan): Unify embedder service handler lists and their APIs. |
45 EmbedderServiceHandler* Service::isolate_service_handler_head_ = NULL; | 45 EmbedderServiceHandler* Service::isolate_service_handler_head_ = NULL; |
46 EmbedderServiceHandler* Service::root_service_handler_head_ = NULL; | 46 EmbedderServiceHandler* Service::root_service_handler_head_ = NULL; |
47 uint32_t Service::event_mask_ = 0; | |
48 struct ServiceMethodDescriptor; | 47 struct ServiceMethodDescriptor; |
49 ServiceMethodDescriptor* FindMethod(const char* method_name); | 48 ServiceMethodDescriptor* FindMethod(const char* method_name); |
50 | 49 |
51 static uint8_t* allocator(uint8_t* ptr, intptr_t old_size, intptr_t new_size) { | 50 static uint8_t* allocator(uint8_t* ptr, intptr_t old_size, intptr_t new_size) { |
52 void* new_ptr = realloc(reinterpret_cast<void*>(ptr), new_size); | 51 void* new_ptr = realloc(reinterpret_cast<void*>(ptr), new_size); |
53 return reinterpret_cast<uint8_t*>(new_ptr); | 52 return reinterpret_cast<uint8_t*>(new_ptr); |
54 } | 53 } |
55 | 54 |
56 static void PrintRequest(const JSONObject& obj, JSONStream* js) { | 55 static void PrintRequest(const JSONObject& obj, JSONStream* js) { |
57 JSONObject jsobj(&obj, "request"); | 56 JSONObject jsobj(&obj, "request"); |
(...skipping 436 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
494 InvokeMethod(isolate, msg_instance); | 493 InvokeMethod(isolate, msg_instance); |
495 } | 494 } |
496 | 495 |
497 | 496 |
498 void Service::HandleIsolateMessage(Isolate* isolate, const Array& msg) { | 497 void Service::HandleIsolateMessage(Isolate* isolate, const Array& msg) { |
499 ASSERT(isolate != NULL); | 498 ASSERT(isolate != NULL); |
500 InvokeMethod(isolate, msg); | 499 InvokeMethod(isolate, msg); |
501 } | 500 } |
502 | 501 |
503 | 502 |
504 bool Service::EventMaskHas(uint32_t mask) { | |
505 return (event_mask_ & mask) != 0; | |
506 } | |
507 | |
508 | |
509 bool Service::NeedsEvents() { | 503 bool Service::NeedsEvents() { |
510 return ServiceIsolate::IsRunning(); | 504 return ServiceIsolate::IsRunning(); |
511 } | 505 } |
512 | 506 |
513 | 507 |
514 bool Service::NeedsDebuggerEvents() { | 508 void Service::SendEvent(intptr_t eventType, |
515 return NeedsEvents() && EventMaskHas(kEventFamilyDebugMask); | |
516 } | |
517 | |
518 | |
519 bool Service::NeedsGCEvents() { | |
520 return NeedsEvents() && EventMaskHas(kEventFamilyGCMask); | |
521 } | |
522 | |
523 | |
524 void Service::SetEventMask(uint32_t mask) { | |
525 event_mask_ = mask; | |
526 } | |
527 | |
528 | |
529 void Service::SendEvent(intptr_t eventFamilyId, | |
530 intptr_t eventType, | |
531 const Object& eventMessage) { | 509 const Object& eventMessage) { |
532 ASSERT(!ServiceIsolate::IsServiceIsolateDescendant(Isolate::Current())); | 510 ASSERT(!ServiceIsolate::IsServiceIsolateDescendant(Isolate::Current())); |
533 if (!ServiceIsolate::IsRunning()) { | 511 if (!ServiceIsolate::IsRunning()) { |
534 return; | 512 return; |
535 } | 513 } |
536 Isolate* isolate = Isolate::Current(); | 514 Isolate* isolate = Isolate::Current(); |
537 ASSERT(isolate != NULL); | 515 ASSERT(isolate != NULL); |
538 HANDLESCOPE(isolate); | 516 HANDLESCOPE(isolate); |
539 | 517 |
540 // Construct a list of the form [eventFamilyId, eventMessage]. | |
541 // | |
542 // TODO(turnidge): Revisit passing the eventFamilyId here at all. | |
543 const Array& list = Array::Handle(Array::New(2)); | |
544 ASSERT(!list.IsNull()); | |
545 list.SetAt(0, Integer::Handle(Integer::New(eventFamilyId))); | |
546 list.SetAt(1, eventMessage); | |
547 | |
548 // Push the event to port_. | 518 // Push the event to port_. |
549 uint8_t* data = NULL; | 519 uint8_t* data = NULL; |
550 MessageWriter writer(&data, &allocator, false); | 520 MessageWriter writer(&data, &allocator, false); |
551 writer.WriteMessage(list); | 521 writer.WriteMessage(eventMessage); |
552 intptr_t len = writer.BytesWritten(); | 522 intptr_t len = writer.BytesWritten(); |
553 if (FLAG_trace_service) { | 523 if (FLAG_trace_service) { |
554 OS::Print("vm-service: Pushing event of type %" Pd ", len %" Pd "\n", | 524 OS::Print("vm-service: Pushing event of type %" Pd ", len %" Pd "\n", |
555 eventType, len); | 525 eventType, len); |
556 } | 526 } |
557 // TODO(turnidge): For now we ignore failure to send an event. Revisit? | 527 // TODO(turnidge): For now we ignore failure to send an event. Revisit? |
558 PortMap::PostMessage( | 528 PortMap::PostMessage( |
559 new Message(ServiceIsolate::Port(), data, len, Message::kNormalPriority)); | 529 new Message(ServiceIsolate::Port(), data, len, Message::kNormalPriority)); |
560 } | 530 } |
561 | 531 |
562 | 532 |
563 void Service::SendEvent(intptr_t eventFamilyId, | 533 void Service::SendEvent(const String& meta, |
564 const String& meta, | |
565 const uint8_t* data, | 534 const uint8_t* data, |
566 intptr_t size) { | 535 intptr_t size) { |
567 // Bitstream: [meta data size (big-endian 64 bit)] [meta data (UTF-8)] [data] | 536 // Bitstream: [meta data size (big-endian 64 bit)] [meta data (UTF-8)] [data] |
568 const intptr_t meta_bytes = Utf8::Length(meta); | 537 const intptr_t meta_bytes = Utf8::Length(meta); |
569 const intptr_t total_bytes = sizeof(uint64_t) + meta_bytes + size; | 538 const intptr_t total_bytes = sizeof(uint64_t) + meta_bytes + size; |
570 const TypedData& message = TypedData::Handle( | 539 const TypedData& message = TypedData::Handle( |
571 TypedData::New(kTypedDataUint8ArrayCid, total_bytes)); | 540 TypedData::New(kTypedDataUint8ArrayCid, total_bytes)); |
572 intptr_t offset = 0; | 541 intptr_t offset = 0; |
573 // TODO(koda): Rename these methods SetHostUint64, etc. | 542 // TODO(koda): Rename these methods SetHostUint64, etc. |
574 message.SetUint64(0, Utils::HostToBigEndian64(meta_bytes)); | 543 message.SetUint64(0, Utils::HostToBigEndian64(meta_bytes)); |
575 offset += sizeof(uint64_t); | 544 offset += sizeof(uint64_t); |
576 { | 545 { |
577 NoSafepointScope no_safepoint; | 546 NoSafepointScope no_safepoint; |
578 meta.ToUTF8(static_cast<uint8_t*>(message.DataAddr(offset)), meta_bytes); | 547 meta.ToUTF8(static_cast<uint8_t*>(message.DataAddr(offset)), meta_bytes); |
579 offset += meta_bytes; | 548 offset += meta_bytes; |
580 } | 549 } |
581 // TODO(koda): It would be nice to avoid this copy (requires changes to | 550 // TODO(koda): It would be nice to avoid this copy (requires changes to |
582 // MessageWriter code). | 551 // MessageWriter code). |
583 { | 552 { |
584 NoSafepointScope no_safepoint; | 553 NoSafepointScope no_safepoint; |
585 memmove(message.DataAddr(offset), data, size); | 554 memmove(message.DataAddr(offset), data, size); |
586 offset += size; | 555 offset += size; |
587 } | 556 } |
588 ASSERT(offset == total_bytes); | 557 ASSERT(offset == total_bytes); |
589 // TODO(turnidge): Pass the real eventType here. | 558 // TODO(turnidge): Pass the real eventType here. |
590 SendEvent(eventFamilyId, 0, message); | 559 SendEvent(0, message); |
591 } | 560 } |
592 | 561 |
593 | 562 |
594 void Service::HandleGCEvent(GCEvent* event) { | 563 void Service::HandleGCEvent(GCEvent* event) { |
595 if (ServiceIsolate::IsServiceIsolateDescendant(Isolate::Current())) { | 564 if (ServiceIsolate::IsServiceIsolateDescendant(Isolate::Current())) { |
596 return; | 565 return; |
597 } | 566 } |
598 JSONStream js; | 567 JSONStream js; |
599 event->PrintJSON(&js); | 568 event->PrintJSON(&js); |
600 const String& message = String::Handle(String::New(js.ToCString())); | 569 const String& message = String::Handle(String::New(js.ToCString())); |
601 // TODO(turnidge): Pass the real eventType here. | 570 // TODO(turnidge): Pass the real eventType here. |
602 SendEvent(kEventFamilyGC, 0, message); | 571 SendEvent(0, message); |
603 } | 572 } |
604 | 573 |
605 | 574 |
606 void Service::HandleEvent(ServiceEvent* event) { | 575 void Service::HandleEvent(ServiceEvent* event) { |
607 JSONStream js; | 576 JSONStream js; |
608 event->PrintJSON(&js); | 577 event->PrintJSON(&js); |
609 const String& message = String::Handle(String::New(js.ToCString())); | 578 const String& message = String::Handle(String::New(js.ToCString())); |
610 SendEvent(kEventFamilyDebug, event->type(), message); | 579 SendEvent(event->type(), message); |
611 } | 580 } |
612 | 581 |
613 | 582 |
614 class EmbedderServiceHandler { | 583 class EmbedderServiceHandler { |
615 public: | 584 public: |
616 explicit EmbedderServiceHandler(const char* name) : name_(NULL), | 585 explicit EmbedderServiceHandler(const char* name) : name_(NULL), |
617 callback_(NULL), | 586 callback_(NULL), |
618 user_data_(NULL), | 587 user_data_(NULL), |
619 next_(NULL) { | 588 next_(NULL) { |
620 ASSERT(name != NULL); | 589 ASSERT(name != NULL); |
(...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
795 JSONObject jsobj(&js); | 764 JSONObject jsobj(&js); |
796 jsobj.AddProperty("type", "ServiceEvent"); | 765 jsobj.AddProperty("type", "ServiceEvent"); |
797 jsobj.AddProperty("eventType", "_Echo"); | 766 jsobj.AddProperty("eventType", "_Echo"); |
798 jsobj.AddProperty("isolate", isolate); | 767 jsobj.AddProperty("isolate", isolate); |
799 if (text != NULL) { | 768 if (text != NULL) { |
800 jsobj.AddProperty("text", text); | 769 jsobj.AddProperty("text", text); |
801 } | 770 } |
802 } | 771 } |
803 const String& message = String::Handle(String::New(js.ToCString())); | 772 const String& message = String::Handle(String::New(js.ToCString())); |
804 uint8_t data[] = {0, 128, 255}; | 773 uint8_t data[] = {0, 128, 255}; |
805 // TODO(koda): Add 'testing' event family. | 774 SendEvent(message, data, sizeof(data)); |
806 SendEvent(kEventFamilyDebug, message, data, sizeof(data)); | |
807 } | 775 } |
808 | 776 |
809 | 777 |
810 static bool _TriggerEchoEvent(Isolate* isolate, JSONStream* js) { | 778 static bool _TriggerEchoEvent(Isolate* isolate, JSONStream* js) { |
811 Service::SendEchoEvent(isolate, js->LookupParam("text")); | 779 Service::SendEchoEvent(isolate, js->LookupParam("text")); |
812 JSONObject jsobj(js); | 780 JSONObject jsobj(js); |
813 return HandleCommonEcho(&jsobj, js); | 781 return HandleCommonEcho(&jsobj, js); |
814 } | 782 } |
815 | 783 |
816 | 784 |
(...skipping 1412 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2229 | 2197 |
2230 void Service::SendGraphEvent(Isolate* isolate) { | 2198 void Service::SendGraphEvent(Isolate* isolate) { |
2231 uint8_t* buffer = NULL; | 2199 uint8_t* buffer = NULL; |
2232 WriteStream stream(&buffer, &allocator, 1 * MB); | 2200 WriteStream stream(&buffer, &allocator, 1 * MB); |
2233 ObjectGraph graph(isolate); | 2201 ObjectGraph graph(isolate); |
2234 graph.Serialize(&stream); | 2202 graph.Serialize(&stream); |
2235 JSONStream js; | 2203 JSONStream js; |
2236 { | 2204 { |
2237 JSONObject jsobj(&js); | 2205 JSONObject jsobj(&js); |
2238 jsobj.AddProperty("type", "ServiceEvent"); | 2206 jsobj.AddProperty("type", "ServiceEvent"); |
2239 jsobj.AddPropertyF("id", "_graphEvent"); | |
2240 jsobj.AddProperty("eventType", "_Graph"); | 2207 jsobj.AddProperty("eventType", "_Graph"); |
2241 jsobj.AddProperty("isolate", isolate); | 2208 jsobj.AddProperty("isolate", isolate); |
2242 } | 2209 } |
2243 const String& message = String::Handle(String::New(js.ToCString())); | 2210 const String& message = String::Handle(String::New(js.ToCString())); |
2244 SendEvent(kEventFamilyDebug, message, buffer, stream.bytes_written()); | 2211 SendEvent(message, buffer, stream.bytes_written()); |
2245 } | 2212 } |
2246 | 2213 |
2247 | 2214 |
2248 class ContainsAddressVisitor : public FindObjectVisitor { | 2215 class ContainsAddressVisitor : public FindObjectVisitor { |
2249 public: | 2216 public: |
2250 ContainsAddressVisitor(Isolate* isolate, uword addr) | 2217 ContainsAddressVisitor(Isolate* isolate, uword addr) |
2251 : FindObjectVisitor(isolate), addr_(addr) { } | 2218 : FindObjectVisitor(isolate), addr_(addr) { } |
2252 virtual ~ContainsAddressVisitor() { } | 2219 virtual ~ContainsAddressVisitor() { } |
2253 | 2220 |
2254 virtual uword filter_addr() const { return addr_; } | 2221 virtual uword filter_addr() const { return addr_; } |
(...skipping 354 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2609 ServiceMethodDescriptor& method = service_methods_[i]; | 2576 ServiceMethodDescriptor& method = service_methods_[i]; |
2610 if (strcmp(method_name, method.name) == 0) { | 2577 if (strcmp(method_name, method.name) == 0) { |
2611 return &method; | 2578 return &method; |
2612 } | 2579 } |
2613 } | 2580 } |
2614 return NULL; | 2581 return NULL; |
2615 } | 2582 } |
2616 | 2583 |
2617 | 2584 |
2618 } // namespace dart | 2585 } // namespace dart |
OLD | NEW |