Chromium Code Reviews| 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 21 matching lines...) Expand all Loading... | |
| 32 #include "vm/stack_frame.h" | 32 #include "vm/stack_frame.h" |
| 33 #include "vm/symbols.h" | 33 #include "vm/symbols.h" |
| 34 #include "vm/unicode.h" | 34 #include "vm/unicode.h" |
| 35 #include "vm/version.h" | 35 #include "vm/version.h" |
| 36 | 36 |
| 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 | 41 |
| 42 ServiceIdZone::ServiceIdZone() { | |
| 43 } | |
| 44 | |
| 45 | |
| 46 ServiceIdZone::~ServiceIdZone() { | |
| 47 } | |
| 48 | |
| 49 | |
| 50 RingServiceIdZone::RingServiceIdZone(ObjectIdRing::IdPolicy policy) | |
| 51 : policy_(policy) { | |
| 52 } | |
| 53 | |
| 54 | |
| 55 RingServiceIdZone::~RingServiceIdZone() { | |
| 56 } | |
| 57 | |
| 58 | |
| 59 char* RingServiceIdZone::GetServiceId(const Object& obj) { | |
| 60 Thread* thread = Thread::Current(); | |
| 61 Isolate* isolate = thread->isolate(); | |
| 62 ASSERT(isolate != NULL); | |
| 63 Zone* zone = thread->zone(); | |
| 64 ASSERT(zone != NULL); | |
| 65 ObjectIdRing* ring = isolate->object_id_ring(); | |
| 66 const intptr_t id = ring->GetIdForObject(obj.raw(), policy_); | |
| 67 return zone->PrintToString("objects/%" Pd "", id); | |
| 68 } | |
| 69 | |
| 70 GrowableServiceIdZone::GrowableServiceIdZone(const char* format_str, | |
|
turnidge
2015/05/11 19:48:45
format_str is perhaps too general, given that we w
Cutch
2015/05/12 14:59:57
Acknowledged.
| |
| 71 const GrowableObjectArray& storage) | |
| 72 : format_str_(format_str), | |
| 73 array_(GrowableObjectArray::Handle(storage.raw())) { | |
| 74 } | |
| 75 | |
| 76 | |
| 77 GrowableServiceIdZone::~GrowableServiceIdZone() { | |
| 78 } | |
| 79 | |
| 80 | |
| 81 char* GrowableServiceIdZone::GetServiceId(const Object& obj) { | |
| 82 Thread* thread = Thread::Current(); | |
| 83 Zone* zone = thread->zone(); | |
| 84 ASSERT(zone != NULL); | |
| 85 intptr_t id = FindIndex(obj); | |
| 86 if (id < 0) { | |
| 87 id = Append(obj); | |
| 88 } | |
| 89 ASSERT(id >= 0); | |
| 90 return zone->PrintToString(format_str_, id); | |
| 91 } | |
| 92 | |
| 93 | |
| 94 intptr_t GrowableServiceIdZone::FindIndex(const Object& obj) { | |
| 95 for (intptr_t i = 0; i < array_.Length(); i++) { | |
| 96 if (obj.raw() == array_.At(i)) { | |
| 97 return i; | |
| 98 } | |
| 99 } | |
| 100 return -1; | |
| 101 } | |
| 102 | |
| 103 | |
| 104 intptr_t GrowableServiceIdZone::Append(const Object& obj) { | |
| 105 intptr_t id = array_.Length(); | |
| 106 array_.Add(obj); | |
| 107 ASSERT(id == (array_.Length() - 1)); | |
| 108 return id; | |
| 109 } | |
| 110 | |
| 111 | |
| 42 // TODO(johnmccutchan): Unify embedder service handler lists and their APIs. | 112 // TODO(johnmccutchan): Unify embedder service handler lists and their APIs. |
| 43 EmbedderServiceHandler* Service::isolate_service_handler_head_ = NULL; | 113 EmbedderServiceHandler* Service::isolate_service_handler_head_ = NULL; |
| 44 EmbedderServiceHandler* Service::root_service_handler_head_ = NULL; | 114 EmbedderServiceHandler* Service::root_service_handler_head_ = NULL; |
| 45 struct ServiceMethodDescriptor; | 115 struct ServiceMethodDescriptor; |
| 46 ServiceMethodDescriptor* FindMethod(const char* method_name); | 116 ServiceMethodDescriptor* FindMethod(const char* method_name); |
| 47 | 117 |
| 48 static uint8_t* allocator(uint8_t* ptr, intptr_t old_size, intptr_t new_size) { | 118 static uint8_t* allocator(uint8_t* ptr, intptr_t old_size, intptr_t new_size) { |
| 49 void* new_ptr = realloc(reinterpret_cast<void*>(ptr), new_size); | 119 void* new_ptr = realloc(reinterpret_cast<void*>(ptr), new_size); |
| 50 return reinterpret_cast<uint8_t*>(new_ptr); | 120 return reinterpret_cast<uint8_t*>(new_ptr); |
| 51 } | 121 } |
| (...skipping 387 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 439 ASSERT(!method_name.IsNull()); | 509 ASSERT(!method_name.IsNull()); |
| 440 ASSERT(!seq.IsNull()); | 510 ASSERT(!seq.IsNull()); |
| 441 ASSERT(!param_keys.IsNull()); | 511 ASSERT(!param_keys.IsNull()); |
| 442 ASSERT(!param_values.IsNull()); | 512 ASSERT(!param_values.IsNull()); |
| 443 ASSERT(param_keys.Length() == param_values.Length()); | 513 ASSERT(param_keys.Length() == param_values.Length()); |
| 444 | 514 |
| 445 if (!reply_port.IsSendPort()) { | 515 if (!reply_port.IsSendPort()) { |
| 446 FATAL("SendPort expected."); | 516 FATAL("SendPort expected."); |
| 447 } | 517 } |
| 448 | 518 |
| 519 // Default service id zone is the standard object id ring which eagerly | |
| 520 // allocates a new id each time. Keep existing_ring_service_id_zone on | |
| 521 // the stack in case it is requested. | |
| 522 RingServiceIdZone | |
| 523 existing_ring_service_id_zone(ObjectIdRing::kExistingOrNewId); | |
|
turnidge
2015/05/11 19:48:45
Having this on the stack feels wrong, somehow.
Cutch
2015/05/12 14:59:57
Done.
| |
| 524 | |
| 449 JSONStream js; | 525 JSONStream js; |
| 450 js.Setup(zone.GetZone(), SendPort::Cast(reply_port).Id(), | 526 js.Setup(zone.GetZone(), SendPort::Cast(reply_port).Id(), |
| 451 seq, method_name, param_keys, param_values); | 527 seq, method_name, param_keys, param_values); |
| 452 | 528 |
| 529 // RPC came in with a custom service id zone. | |
| 530 const char* service_id_zone_param = js.LookupParam("_serviceIdZone"); | |
| 531 | |
| 532 if (service_id_zone_param != NULL) { | |
| 533 // Override service id. | |
| 534 if (strcmp("Ring.NewId", service_id_zone_param) == 0) { | |
|
turnidge
2015/05/11 19:48:45
Name this ring "default"?
Cutch
2015/05/12 14:59:57
Done.
| |
| 535 // Ring with eager id allocation. This is the default ring. | |
| 536 // Nothing to do. | |
| 537 } else if (strcmp("Ring.ExistingId", service_id_zone_param) == 0) { | |
|
turnidge
2015/05/11 19:48:45
Name this ring "default.reuse"? Not sure.
Cutch
2015/05/12 14:59:57
Done.
| |
| 538 // Ring with existing id reuse. | |
| 539 js.set_service_id_zone(&existing_ring_service_id_zone); | |
| 540 } else { | |
| 541 // TODO(johnmccutchan): Support creating, deleting, and selecting | |
| 542 // custom service id zones (see GrowableServiceIdZone). | |
| 543 // For now, always return an error. | |
| 544 PrintInvalidParamError(&js, "_serviceIdZone"); | |
|
turnidge
2015/05/11 20:01:04
_idZone instead? service is implied. Here are el
Cutch
2015/05/12 14:59:57
Done.
| |
| 545 js.PostReply(); | |
| 546 return; | |
| 547 } | |
| 548 } | |
| 453 const char* c_method_name = method_name.ToCString(); | 549 const char* c_method_name = method_name.ToCString(); |
| 454 | 550 |
| 455 ServiceMethodDescriptor* method = FindMethod(c_method_name); | 551 ServiceMethodDescriptor* method = FindMethod(c_method_name); |
| 456 if (method != NULL) { | 552 if (method != NULL) { |
| 457 if (!ValidateParameters(method->parameters, &js)) { | 553 if (!ValidateParameters(method->parameters, &js)) { |
| 458 js.PostReply(); | 554 js.PostReply(); |
| 459 return; | 555 return; |
| 460 } | 556 } |
| 461 if (method->entry(isolate, &js)) { | 557 if (method->entry(isolate, &js)) { |
| 462 js.PostReply(); | 558 js.PostReply(); |
| (...skipping 249 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 712 | 808 |
| 713 | 809 |
| 714 static bool GetIsolate(Isolate* isolate, JSONStream* js) { | 810 static bool GetIsolate(Isolate* isolate, JSONStream* js) { |
| 715 isolate->PrintJSON(js, false); | 811 isolate->PrintJSON(js, false); |
| 716 return true; | 812 return true; |
| 717 } | 813 } |
| 718 | 814 |
| 719 | 815 |
| 720 static const MethodParameter* get_stack_params[] = { | 816 static const MethodParameter* get_stack_params[] = { |
| 721 ISOLATE_PARAMETER, | 817 ISOLATE_PARAMETER, |
| 722 new BoolParameter("full", false), | 818 new BoolParameter("_full", false), |
|
turnidge
2015/05/11 19:48:45
Update the idl if necessary.
Cutch
2015/05/12 14:59:57
Done.
| |
| 723 NULL, | 819 NULL, |
| 724 }; | 820 }; |
| 725 | 821 |
| 726 | 822 |
| 727 static bool GetStack(Isolate* isolate, JSONStream* js) { | 823 static bool GetStack(Isolate* isolate, JSONStream* js) { |
| 728 DebuggerStackTrace* stack = isolate->debugger()->StackTrace(); | 824 DebuggerStackTrace* stack = isolate->debugger()->StackTrace(); |
| 729 // Do we want the complete script object and complete local variable objects? | 825 // Do we want the complete script object and complete local variable objects? |
| 730 // This is true for dump requests. | 826 // This is true for dump requests. |
| 731 const bool full = BoolParameter::Parse(js->LookupParam("full"), false); | 827 const bool full = BoolParameter::Parse(js->LookupParam("_full"), false); |
| 732 JSONObject jsobj(js); | 828 JSONObject jsobj(js); |
| 733 jsobj.AddProperty("type", "Stack"); | 829 jsobj.AddProperty("type", "Stack"); |
| 734 { | 830 { |
| 735 JSONArray jsarr(&jsobj, "frames"); | 831 JSONArray jsarr(&jsobj, "frames"); |
| 736 | 832 |
| 737 intptr_t num_frames = stack->Length(); | 833 intptr_t num_frames = stack->Length(); |
| 738 for (intptr_t i = 0; i < num_frames; i++) { | 834 for (intptr_t i = 0; i < num_frames; i++) { |
| 739 ActivationFrame* frame = stack->FrameAt(i); | 835 ActivationFrame* frame = stack->FrameAt(i); |
| 740 JSONObject jsobj(&jsarr); | 836 JSONObject jsobj(&jsarr); |
| 741 frame->PrintToJSONObject(&jsobj, full); | 837 frame->PrintToJSONObject(&jsobj, full); |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 784 } | 880 } |
| 785 | 881 |
| 786 | 882 |
| 787 static bool _TriggerEchoEvent(Isolate* isolate, JSONStream* js) { | 883 static bool _TriggerEchoEvent(Isolate* isolate, JSONStream* js) { |
| 788 Service::SendEchoEvent(isolate, js->LookupParam("text")); | 884 Service::SendEchoEvent(isolate, js->LookupParam("text")); |
| 789 JSONObject jsobj(js); | 885 JSONObject jsobj(js); |
| 790 return HandleCommonEcho(&jsobj, js); | 886 return HandleCommonEcho(&jsobj, js); |
| 791 } | 887 } |
| 792 | 888 |
| 793 | 889 |
| 890 static bool _DumpRingRequests(Isolate* isolate, JSONStream* js) { | |
|
turnidge
2015/05/11 19:48:45
Is using a leading underscore a thing in our C++?
Cutch
2015/05/12 14:59:57
Done.
| |
| 891 // Reuse object ids found in the ring. | |
| 892 RingServiceIdZone | |
| 893 existing_ring_service_id_zone(ObjectIdRing::kExistingOrNewId); | |
| 894 js->set_service_id_zone(&existing_ring_service_id_zone); | |
| 895 ObjectIdRing* ring = isolate->object_id_ring(); | |
| 896 ring->PrintGetObjectRequestsToJSON(js); | |
| 897 return true; | |
| 898 } | |
| 899 | |
| 900 | |
| 794 static bool _Echo(Isolate* isolate, JSONStream* js) { | 901 static bool _Echo(Isolate* isolate, JSONStream* js) { |
| 795 JSONObject jsobj(js); | 902 JSONObject jsobj(js); |
| 796 return HandleCommonEcho(&jsobj, js); | 903 return HandleCommonEcho(&jsobj, js); |
| 797 } | 904 } |
| 798 | 905 |
| 799 | 906 |
| 800 static bool ContainsNonInstance(const Object& obj) { | 907 static bool ContainsNonInstance(const Object& obj) { |
| 801 if (obj.IsArray()) { | 908 if (obj.IsArray()) { |
| 802 const Array& array = Array::Cast(obj); | 909 const Array& array = Array::Cast(obj); |
| 803 Object& element = Object::Handle(); | 910 Object& element = Object::Handle(); |
| (...skipping 1736 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2540 ServiceEvent event(isolate, ServiceEvent::kIsolateUpdate); | 2647 ServiceEvent event(isolate, ServiceEvent::kIsolateUpdate); |
| 2541 Service::HandleEvent(&event); | 2648 Service::HandleEvent(&event); |
| 2542 } | 2649 } |
| 2543 JSONObject jsobj(js); | 2650 JSONObject jsobj(js); |
| 2544 jsobj.AddProperty("type", "Success"); | 2651 jsobj.AddProperty("type", "Success"); |
| 2545 return true; | 2652 return true; |
| 2546 } | 2653 } |
| 2547 | 2654 |
| 2548 | 2655 |
| 2549 static ServiceMethodDescriptor service_methods_[] = { | 2656 static ServiceMethodDescriptor service_methods_[] = { |
| 2657 { "_dumpRingRequests", _DumpRingRequests, NULL }, | |
|
turnidge
2015/05/11 19:48:45
I would instead like this request to be "_dumpZone
Cutch
2015/05/12 14:59:57
Done.
| |
| 2550 { "_echo", _Echo, | 2658 { "_echo", _Echo, |
| 2551 NULL }, | 2659 NULL }, |
| 2552 { "_respondWithMalformedJson", _RespondWithMalformedJson, | 2660 { "_respondWithMalformedJson", _RespondWithMalformedJson, |
| 2553 NULL }, | 2661 NULL }, |
| 2554 { "_respondWithMalformedObject", _RespondWithMalformedObject, | 2662 { "_respondWithMalformedObject", _RespondWithMalformedObject, |
| 2555 NULL }, | 2663 NULL }, |
| 2556 { "_triggerEchoEvent", _TriggerEchoEvent, | 2664 { "_triggerEchoEvent", _TriggerEchoEvent, |
| 2557 NULL }, | 2665 NULL }, |
| 2558 { "addBreakpoint", AddBreakpoint, | 2666 { "addBreakpoint", AddBreakpoint, |
| 2559 add_breakpoint_params }, | 2667 add_breakpoint_params }, |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2631 ServiceMethodDescriptor& method = service_methods_[i]; | 2739 ServiceMethodDescriptor& method = service_methods_[i]; |
| 2632 if (strcmp(method_name, method.name) == 0) { | 2740 if (strcmp(method_name, method.name) == 0) { |
| 2633 return &method; | 2741 return &method; |
| 2634 } | 2742 } |
| 2635 } | 2743 } |
| 2636 return NULL; | 2744 return NULL; |
| 2637 } | 2745 } |
| 2638 | 2746 |
| 2639 | 2747 |
| 2640 } // namespace dart | 2748 } // namespace dart |
| OLD | NEW |