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

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

Issue 897193002: Finish moving service protocol to json rpc. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: code review Created 5 years, 10 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 | Annotate | Revision Log
« no previous file with comments | « runtime/vm/service.h ('k') | runtime/vm/service/message.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 801 matching lines...) Expand 10 before | Expand all | Expand 10 after
812 812
813 // A handler for a per-isolate request. 813 // A handler for a per-isolate request.
814 // 814 //
815 // If a handler returns true, the reply is complete and ready to be 815 // If a handler returns true, the reply is complete and ready to be
816 // posted. If a handler returns false, then it is responsible for 816 // posted. If a handler returns false, then it is responsible for
817 // posting the reply (this can be used for asynchronous delegation of 817 // posting the reply (this can be used for asynchronous delegation of
818 // the response handling). 818 // the response handling).
819 typedef bool (*IsolateMessageHandler)(Isolate* isolate, JSONStream* stream); 819 typedef bool (*IsolateMessageHandler)(Isolate* isolate, JSONStream* stream);
820 820
821 struct IsolateMessageHandlerEntry { 821 struct IsolateMessageHandlerEntry {
822 const char* command; 822 const char* method;
823 IsolateMessageHandler handler; 823 IsolateMessageHandler handler;
824 }; 824 };
825 825
826 static IsolateMessageHandler FindIsolateMessageHandler(const char* command); 826 static IsolateMessageHandler FindIsolateMessageHandler(const char* method);
827 static IsolateMessageHandler FindIsolateMessageHandlerNew(const char* command);
828 827
829 828
830 // A handler for a root (vm-global) request. 829 // A handler for a root (vm-global) request.
831 // 830 //
832 // If a handler returns true, the reply is complete and ready to be 831 // If a handler returns true, the reply is complete and ready to be
833 // posted. If a handler returns false, then it is responsible for 832 // posted. If a handler returns false, then it is responsible for
834 // posting the reply (this can be used for asynchronous delegation of 833 // posting the reply (this can be used for asynchronous delegation of
835 // the response handling). 834 // the response handling).
836 typedef bool (*RootMessageHandler)(JSONStream* stream); 835 typedef bool (*RootMessageHandler)(JSONStream* stream);
837 836
838 struct RootMessageHandlerEntry { 837 struct RootMessageHandlerEntry {
839 const char* command; 838 const char* method;
840 RootMessageHandler handler; 839 RootMessageHandler handler;
841 }; 840 };
842 841
843 static RootMessageHandler FindRootMessageHandler(const char* command); 842 static RootMessageHandler FindRootMessageHandler(const char* method);
844 static RootMessageHandler FindRootMessageHandlerNew(const char* command);
845 843
846 844
847 static void PrintArgumentsAndOptions(const JSONObject& obj, JSONStream* js) { 845 static void PrintRequest(const JSONObject& obj, JSONStream* js) {
848 JSONObject jsobj(&obj, "request"); 846 JSONObject jsobj(&obj, "request");
847 jsobj.AddProperty("method", js->method());
849 { 848 {
850 JSONArray jsarr(&jsobj, "arguments"); 849 JSONArray jsarr(&jsobj, "param_keys");
851 for (intptr_t i = 0; i < js->num_arguments(); i++) { 850 for (intptr_t i = 0; i < js->num_params(); i++) {
852 jsarr.AddValue(js->GetArgument(i)); 851 jsarr.AddValue(js->GetParamKey(i));
853 } 852 }
854 } 853 }
855 { 854 {
856 JSONArray jsarr(&jsobj, "option_keys"); 855 JSONArray jsarr(&jsobj, "param_values");
857 for (intptr_t i = 0; i < js->num_options(); i++) { 856 for (intptr_t i = 0; i < js->num_params(); i++) {
858 jsarr.AddValue(js->GetOptionKey(i)); 857 jsarr.AddValue(js->GetParamValue(i));
859 }
860 }
861 {
862 JSONArray jsarr(&jsobj, "option_values");
863 for (intptr_t i = 0; i < js->num_options(); i++) {
864 jsarr.AddValue(js->GetOptionValue(i));
865 } 858 }
866 } 859 }
867 } 860 }
868 861
869 862
870 static void PrintError(JSONStream* js, 863 static void PrintError(JSONStream* js,
871 const char* format, ...) { 864 const char* format, ...) {
872 Isolate* isolate = Isolate::Current(); 865 Isolate* isolate = Isolate::Current();
873 866
874 va_list args; 867 va_list args;
875 va_start(args, format); 868 va_start(args, format);
876 intptr_t len = OS::VSNPrint(NULL, 0, format, args); 869 intptr_t len = OS::VSNPrint(NULL, 0, format, args);
877 va_end(args); 870 va_end(args);
878 871
879 char* buffer = isolate->current_zone()->Alloc<char>(len + 1); 872 char* buffer = isolate->current_zone()->Alloc<char>(len + 1);
880 va_list args2; 873 va_list args2;
881 va_start(args2, format); 874 va_start(args2, format);
882 OS::VSNPrint(buffer, (len + 1), format, args2); 875 OS::VSNPrint(buffer, (len + 1), format, args2);
883 va_end(args2); 876 va_end(args2);
884 877
885 JSONObject jsobj(js); 878 JSONObject jsobj(js);
886 jsobj.AddProperty("type", "Error"); 879 jsobj.AddProperty("type", "Error");
887 jsobj.AddProperty("message", buffer); 880 jsobj.AddProperty("message", buffer);
888 PrintArgumentsAndOptions(jsobj, js); 881 PrintRequest(jsobj, js);
889 } 882 }
890 883
891 884
885 static void PrintMissingParamError(JSONStream* js,
886 const char* param) {
887 PrintError(js, "%s expects the '%s' parameter",
888 js->method(), param);
889 }
890
891
892 static void PrintInvalidParamError(JSONStream* js,
893 const char* param) {
894 PrintError(js, "%s: invalid '%s' parameter: %s",
895 js->method(), param, js->LookupParam(param));
896 }
897
898
892 static void PrintErrorWithKind(JSONStream* js, 899 static void PrintErrorWithKind(JSONStream* js,
893 const char* kind, 900 const char* kind,
894 const char* format, ...) { 901 const char* format, ...) {
895 Isolate* isolate = Isolate::Current(); 902 Isolate* isolate = Isolate::Current();
896 903
897 va_list args; 904 va_list args;
898 va_start(args, format); 905 va_start(args, format);
899 intptr_t len = OS::VSNPrint(NULL, 0, format, args); 906 intptr_t len = OS::VSNPrint(NULL, 0, format, args);
900 va_end(args); 907 va_end(args);
901 908
902 char* buffer = isolate->current_zone()->Alloc<char>(len + 1); 909 char* buffer = isolate->current_zone()->Alloc<char>(len + 1);
903 va_list args2; 910 va_list args2;
904 va_start(args2, format); 911 va_start(args2, format);
905 OS::VSNPrint(buffer, (len + 1), format, args2); 912 OS::VSNPrint(buffer, (len + 1), format, args2);
906 va_end(args2); 913 va_end(args2);
907 914
908 JSONObject jsobj(js); 915 JSONObject jsobj(js);
909 jsobj.AddProperty("type", "Error"); 916 jsobj.AddProperty("type", "Error");
910 jsobj.AddProperty("id", ""); 917 jsobj.AddProperty("id", "");
911 jsobj.AddProperty("kind", kind); 918 jsobj.AddProperty("kind", kind);
912 jsobj.AddProperty("message", buffer); 919 jsobj.AddProperty("message", buffer);
913 PrintArgumentsAndOptions(jsobj, js); 920 PrintRequest(jsobj, js);
914 } 921 }
915 922
916 923
917 void Service::HandleIsolateMessageNew(Isolate* isolate, const Array& msg) { 924 void Service::HandleIsolateMessage(Isolate* isolate, const Array& msg) {
918 ASSERT(isolate != NULL); 925 ASSERT(isolate != NULL);
919 ASSERT(!msg.IsNull()); 926 ASSERT(!msg.IsNull());
927 ASSERT(msg.Length() == 5);
920 928
921 { 929 {
922 StackZone zone(isolate); 930 StackZone zone(isolate);
923 HANDLESCOPE(isolate); 931 HANDLESCOPE(isolate);
924 932
925 Instance& reply_port = Instance::Handle(isolate); 933 Instance& reply_port = Instance::Handle(isolate);
926 String& method = String::Handle(isolate); 934 String& method = String::Handle(isolate);
927 Array& param_keys = Array::Handle(isolate); 935 Array& param_keys = Array::Handle(isolate);
928 Array& param_values = Array::Handle(isolate); 936 Array& param_values = Array::Handle(isolate);
929 reply_port ^= msg.At(1); 937 reply_port ^= msg.At(1);
930 method ^= msg.At(2); 938 method ^= msg.At(2);
931 param_keys ^= msg.At(3); 939 param_keys ^= msg.At(3);
932 param_values ^= msg.At(4); 940 param_values ^= msg.At(4);
933 941
934 ASSERT(!method.IsNull()); 942 ASSERT(!method.IsNull());
935 ASSERT(!param_keys.IsNull()); 943 ASSERT(!param_keys.IsNull());
936 ASSERT(!param_values.IsNull()); 944 ASSERT(!param_values.IsNull());
937 ASSERT(param_keys.Length() == param_values.Length()); 945 ASSERT(param_keys.Length() == param_values.Length());
938 946
939 if (!reply_port.IsSendPort()) { 947 if (!reply_port.IsSendPort()) {
940 FATAL("SendPort expected."); 948 FATAL("SendPort expected.");
941 } 949 }
942 950
943 IsolateMessageHandler handler = 951 IsolateMessageHandler handler =
944 FindIsolateMessageHandlerNew(method.ToCString()); 952 FindIsolateMessageHandler(method.ToCString());
945 { 953 {
946 JSONStream js; 954 JSONStream js;
947 js.SetupNew(zone.GetZone(), SendPort::Cast(reply_port).Id(), 955 js.Setup(zone.GetZone(), SendPort::Cast(reply_port).Id(),
948 method, param_keys, param_values); 956 method, param_keys, param_values);
949 if (handler == NULL) { 957 if (handler == NULL) {
950 // Check for an embedder handler. 958 // Check for an embedder handler.
951 EmbedderServiceHandler* e_handler = 959 EmbedderServiceHandler* e_handler =
952 FindIsolateEmbedderHandler(method.ToCString()); 960 FindIsolateEmbedderHandler(method.ToCString());
953 if (e_handler != NULL) { 961 if (e_handler != NULL) {
954 EmbedderHandleMessage(e_handler, &js); 962 EmbedderHandleMessage(e_handler, &js);
955 } else { 963 } else {
956 if (FindRootMessageHandlerNew(method.ToCString()) != NULL) { 964 if (FindRootMessageHandler(method.ToCString()) != NULL) {
957 PrintError(&js, "%s expects no 'isolate' parameter\n", 965 PrintError(&js, "%s does not expect the 'isolateId' parameter",
958 method.ToCString()); 966 method.ToCString());
959 } else { 967 } else {
960 PrintError(&js, "Unrecognized method: %s", method.ToCString()); 968 PrintError(&js, "Unrecognized method: %s", method.ToCString());
961 } 969 }
962 } 970 }
963 js.PostReply(); 971 js.PostReply();
964 } else { 972 } else {
965 if (handler(isolate, &js)) { 973 if (handler(isolate, &js)) {
966 // Handler returns true if the reply is ready to be posted. 974 // Handler returns true if the reply is ready to be posted.
967 // TODO(johnmccutchan): Support asynchronous replies. 975 // TODO(johnmccutchan): Support asynchronous replies.
968 js.PostReply(); 976 js.PostReply();
969 } 977 }
970 } 978 }
971 } 979 }
972 } 980 }
973 } 981 }
974 982
975 983
976 void Service::HandleIsolateMessage(Isolate* isolate, const Array& msg) {
977 ASSERT(isolate != NULL);
978 ASSERT(!msg.IsNull());
979
980 {
981 StackZone zone(isolate);
982 HANDLESCOPE(isolate);
983
984 // Message is a list with five entries.
985 ASSERT(msg.Length() == 5);
986
987 Object& tmp = Object::Handle(isolate);
988 tmp = msg.At(2);
989 if (tmp.IsString()) {
990 return Service::HandleIsolateMessageNew(isolate, msg);
991 }
992
993 Instance& reply_port = Instance::Handle(isolate);
994 GrowableObjectArray& path = GrowableObjectArray::Handle(isolate);
995 Array& option_keys = Array::Handle(isolate);
996 Array& option_values = Array::Handle(isolate);
997 reply_port ^= msg.At(1);
998 path ^= msg.At(2);
999 option_keys ^= msg.At(3);
1000 option_values ^= msg.At(4);
1001
1002 ASSERT(!path.IsNull());
1003 ASSERT(!option_keys.IsNull());
1004 ASSERT(!option_values.IsNull());
1005 // Same number of option keys as values.
1006 ASSERT(option_keys.Length() == option_values.Length());
1007
1008 if (!reply_port.IsSendPort()) {
1009 FATAL("SendPort expected.");
1010 }
1011
1012 String& path_segment = String::Handle();
1013 if (path.Length() > 0) {
1014 path_segment ^= path.At(0);
1015 } else {
1016 path_segment ^= Symbols::Empty().raw();
1017 }
1018 ASSERT(!path_segment.IsNull());
1019 const char* path_segment_c = path_segment.ToCString();
1020
1021 IsolateMessageHandler handler =
1022 FindIsolateMessageHandler(path_segment_c);
1023 {
1024 JSONStream js;
1025 js.Setup(zone.GetZone(), SendPort::Cast(reply_port).Id(),
1026 path, option_keys, option_values);
1027 if (handler == NULL) {
1028 // Check for an embedder handler.
1029 EmbedderServiceHandler* e_handler =
1030 FindIsolateEmbedderHandler(path_segment_c);
1031 if (e_handler != NULL) {
1032 EmbedderHandleMessage(e_handler, &js);
1033 } else {
1034 PrintError(&js, "Unrecognized path");
1035 }
1036 js.PostReply();
1037 } else {
1038 if (handler(isolate, &js)) {
1039 // Handler returns true if the reply is ready to be posted.
1040 // TODO(johnmccutchan): Support asynchronous replies.
1041 js.PostReply();
1042 }
1043 }
1044 }
1045 }
1046 }
1047
1048
1049 static bool HandleIsolate(Isolate* isolate, JSONStream* js) { 984 static bool HandleIsolate(Isolate* isolate, JSONStream* js) {
1050 isolate->PrintJSON(js, false); 985 isolate->PrintJSON(js, false);
1051 return true; 986 return true;
1052 } 987 }
1053 988
1054 989
1055 static bool HandleIsolateGetStack(Isolate* isolate, JSONStream* js) { 990 static bool HandleIsolateGetStack(Isolate* isolate, JSONStream* js) {
1056 DebuggerStackTrace* stack = isolate->debugger()->StackTrace(); 991 DebuggerStackTrace* stack = isolate->debugger()->StackTrace();
1057 JSONObject jsobj(js); 992 JSONObject jsobj(js);
1058 jsobj.AddProperty("type", "Stack"); 993 jsobj.AddProperty("type", "Stack");
1059 JSONArray jsarr(&jsobj, "frames"); 994 JSONArray jsarr(&jsobj, "frames");
1060 intptr_t num_frames = stack->Length(); 995 intptr_t num_frames = stack->Length();
1061 for (intptr_t i = 0; i < num_frames; i++) { 996 for (intptr_t i = 0; i < num_frames; i++) {
1062 ActivationFrame* frame = stack->FrameAt(i); 997 ActivationFrame* frame = stack->FrameAt(i);
1063 JSONObject jsobj(&jsarr); 998 JSONObject jsobj(&jsarr);
1064 frame->PrintToJSONObject(&jsobj); 999 frame->PrintToJSONObject(&jsobj);
1065 // TODO(turnidge): Implement depth differently -- differentiate 1000 // TODO(turnidge): Implement depth differently -- differentiate
1066 // inlined frames. 1001 // inlined frames.
1067 jsobj.AddProperty("depth", i); 1002 jsobj.AddProperty("depth", i);
1068 } 1003 }
1069 return true; 1004 return true;
1070 } 1005 }
1071 1006
1072 1007
1073 static bool HandleCommonEcho(JSONObject* jsobj, JSONStream* js) { 1008 static bool HandleCommonEcho(JSONObject* jsobj, JSONStream* js) {
1074 jsobj->AddProperty("type", "_EchoResponse"); 1009 jsobj->AddProperty("type", "_EchoResponse");
1075 if (js->HasOption("text")) { 1010 if (js->HasParam("text")) {
1076 jsobj->AddProperty("text", js->LookupOption("text")); 1011 jsobj->AddProperty("text", js->LookupParam("text"));
1077 } 1012 }
1078 return true; 1013 return true;
1079 } 1014 }
1080 1015
1081 1016
1082 void Service::SendEchoEvent(Isolate* isolate, const char* text) { 1017 void Service::SendEchoEvent(Isolate* isolate, const char* text) {
1083 JSONStream js; 1018 JSONStream js;
1084 { 1019 {
1085 JSONObject jsobj(&js); 1020 JSONObject jsobj(&js);
1086 jsobj.AddProperty("type", "ServiceEvent"); 1021 jsobj.AddProperty("type", "ServiceEvent");
1087 jsobj.AddProperty("eventType", "_Echo"); 1022 jsobj.AddProperty("eventType", "_Echo");
1088 jsobj.AddProperty("isolate", isolate); 1023 jsobj.AddProperty("isolate", isolate);
1089 if (text != NULL) { 1024 if (text != NULL) {
1090 jsobj.AddProperty("text", text); 1025 jsobj.AddProperty("text", text);
1091 } 1026 }
1092 } 1027 }
1093 const String& message = String::Handle(String::New(js.ToCString())); 1028 const String& message = String::Handle(String::New(js.ToCString()));
1094 uint8_t data[] = {0, 128, 255}; 1029 uint8_t data[] = {0, 128, 255};
1095 // TODO(koda): Add 'testing' event family. 1030 // TODO(koda): Add 'testing' event family.
1096 SendEvent(kEventFamilyDebug, message, data, sizeof(data)); 1031 SendEvent(kEventFamilyDebug, message, data, sizeof(data));
1097 } 1032 }
1098 1033
1099 1034
1100 static bool HandleIsolateTriggerEchoEvent(Isolate* isolate, JSONStream* js) { 1035 static bool HandleIsolateTriggerEchoEvent(Isolate* isolate, JSONStream* js) {
1101 Service::SendEchoEvent(isolate, js->LookupOption("text")); 1036 Service::SendEchoEvent(isolate, js->LookupParam("text"));
1102 JSONObject jsobj(js); 1037 JSONObject jsobj(js);
1103 return HandleCommonEcho(&jsobj, js); 1038 return HandleCommonEcho(&jsobj, js);
1104 } 1039 }
1105 1040
1106 1041
1107 static bool HandleIsolateEcho(Isolate* isolate, JSONStream* js) { 1042 static bool HandleIsolateEcho(Isolate* isolate, JSONStream* js) {
1108 JSONObject jsobj(js); 1043 JSONObject jsobj(js);
1109 return HandleCommonEcho(&jsobj, js); 1044 return HandleCommonEcho(&jsobj, js);
1110 } 1045 }
1111 1046
1112 1047
1113 // Print an error message if there is no ID argument.
1114 #define REQUIRE_COLLECTION_ID(collection) \
1115 if (js->num_arguments() == 1) { \
1116 PrintError(js, "Must specify collection object id: /%s/id", collection); \
1117 return true; \
1118 }
1119
1120
1121 #define CHECK_COLLECTION_ID_BOUNDS(collection, length, arg, id, js) \
1122 if (!GetIntegerId(arg, &id)) { \
1123 PrintError(js, "Must specify collection object id: %s/id", collection); \
1124 return true; \
1125 } \
1126 if ((id < 0) || (id >= length)) { \
1127 PrintError(js, "%s id (%" Pd ") must be in [0, %" Pd ").", collection, id, \
1128 length); \
1129 return true; \
1130 }
1131
1132
1133 static bool GetIntegerId(const char* s, intptr_t* id, int base = 10) { 1048 static bool GetIntegerId(const char* s, intptr_t* id, int base = 10) {
1134 if ((s == NULL) || (*s == '\0')) { 1049 if ((s == NULL) || (*s == '\0')) {
1135 // Empty string. 1050 // Empty string.
1136 return false; 1051 return false;
1137 } 1052 }
1138 if (id == NULL) { 1053 if (id == NULL) {
1139 // No id pointer. 1054 // No id pointer.
1140 return false; 1055 return false;
1141 } 1056 }
1142 intptr_t r = 0; 1057 intptr_t r = 0;
(...skipping 530 matching lines...) Expand 10 before | Expand all | Expand 10 after
1673 // references to an object. 1588 // references to an object.
1674 path.SetAt(i * 2, Object::null_object()); 1589 path.SetAt(i * 2, Object::null_object());
1675 } 1590 }
1676 } 1591 }
1677 return true; 1592 return true;
1678 } 1593 }
1679 1594
1680 1595
1681 static bool HandleIsolateGetInboundReferences(Isolate* isolate, 1596 static bool HandleIsolateGetInboundReferences(Isolate* isolate,
1682 JSONStream* js) { 1597 JSONStream* js) {
1683 const char* target_id = js->LookupOption("targetId"); 1598 const char* target_id = js->LookupParam("targetId");
1684 if (target_id == NULL) { 1599 if (target_id == NULL) {
1685 PrintError(js, "Missing 'targetId' option"); 1600 PrintMissingParamError(js, "targetId");
1686 return true; 1601 return true;
1687 } 1602 }
1688 const char* limit_cstr = js->LookupOption("limit"); 1603 const char* limit_cstr = js->LookupParam("limit");
1689 if (target_id == NULL) { 1604 if (target_id == NULL) {
1690 PrintError(js, "Missing 'limit' option"); 1605 PrintMissingParamError(js, "limit");
1691 return true; 1606 return true;
1692 } 1607 }
1693 intptr_t limit; 1608 intptr_t limit;
1694 if (!GetIntegerId(js->LookupOption("limit"), &limit)) { 1609 if (!GetIntegerId(limit_cstr, &limit)) {
1695 PrintError(js, "Invalid 'limit' option: %s", limit_cstr); 1610 PrintInvalidParamError(js, "limit");
1696 return true; 1611 return true;
1697 } 1612 }
1698 1613
1699 Object& obj = Object::Handle(isolate); 1614 Object& obj = Object::Handle(isolate);
1700 ObjectIdRing::LookupResult lookup_result; 1615 ObjectIdRing::LookupResult lookup_result;
1701 { 1616 {
1702 HANDLESCOPE(isolate); 1617 HANDLESCOPE(isolate);
1703 obj = LookupHeapObject(isolate, target_id, &lookup_result); 1618 obj = LookupHeapObject(isolate, target_id, &lookup_result);
1704 } 1619 }
1705 if (obj.raw() == Object::sentinel().raw()) { 1620 if (obj.raw() == Object::sentinel().raw()) {
1706 if (lookup_result == ObjectIdRing::kCollected) { 1621 if (lookup_result == ObjectIdRing::kCollected) {
1707 PrintErrorWithKind( 1622 PrintErrorWithKind(
1708 js, "InboundReferencesCollected", 1623 js, "InboundReferencesCollected",
1709 "attempt to find a retaining path for a collected object\n", 1624 "attempt to find a retaining path for a collected object\n");
1710 js->num_arguments());
1711 return true; 1625 return true;
1712 } else if (lookup_result == ObjectIdRing::kExpired) { 1626 } else if (lookup_result == ObjectIdRing::kExpired) {
1713 PrintErrorWithKind( 1627 PrintErrorWithKind(
1714 js, "InboundReferencesExpired", 1628 js, "InboundReferencesExpired",
1715 "attempt to find a retaining path for an expired object\n", 1629 "attempt to find a retaining path for an expired object\n");
1716 js->num_arguments());
1717 return true; 1630 return true;
1718 } 1631 }
1719 PrintError(js, "Invalid 'targetId' value: no object with id '%s'", 1632 PrintInvalidParamError(js, "targetId");
1720 target_id);
1721 return true; 1633 return true;
1722 } 1634 }
1723 return PrintInboundReferences(isolate, &obj, limit, js); 1635 return PrintInboundReferences(isolate, &obj, limit, js);
1724 } 1636 }
1725 1637
1726 1638
1727 static bool PrintRetainingPath(Isolate* isolate, 1639 static bool PrintRetainingPath(Isolate* isolate,
1728 Object* obj, 1640 Object* obj,
1729 intptr_t limit, 1641 intptr_t limit,
1730 JSONStream* js) { 1642 JSONStream* js) {
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
1774 // after looking for a retaining path. 1686 // after looking for a retaining path.
1775 for (intptr_t i = 0; i < limit; ++i) { 1687 for (intptr_t i = 0; i < limit; ++i) {
1776 path.SetAt(i * 2, Object::null_object()); 1688 path.SetAt(i * 2, Object::null_object());
1777 } 1689 }
1778 1690
1779 return true; 1691 return true;
1780 } 1692 }
1781 1693
1782 static bool HandleIsolateGetRetainingPath(Isolate* isolate, 1694 static bool HandleIsolateGetRetainingPath(Isolate* isolate,
1783 JSONStream* js) { 1695 JSONStream* js) {
1784 const char* target_id = js->LookupOption("targetId"); 1696 const char* target_id = js->LookupParam("targetId");
1785 if (target_id == NULL) { 1697 if (target_id == NULL) {
1786 PrintError(js, "Missing 'targetId' option"); 1698 PrintMissingParamError(js, "targetId");
1787 return true; 1699 return true;
1788 } 1700 }
1789 const char* limit_cstr = js->LookupOption("limit"); 1701 const char* limit_cstr = js->LookupParam("limit");
1790 if (target_id == NULL) { 1702 if (target_id == NULL) {
1791 PrintError(js, "Missing 'limit' option"); 1703 PrintMissingParamError(js, "limit");
1792 return true; 1704 return true;
1793 } 1705 }
1794 intptr_t limit; 1706 intptr_t limit;
1795 if (!GetIntegerId(js->LookupOption("limit"), &limit)) { 1707 if (!GetIntegerId(limit_cstr, &limit)) {
1796 PrintError(js, "Invalid 'limit' option: %s", limit_cstr); 1708 PrintInvalidParamError(js, "limit");
1797 return true; 1709 return true;
1798 } 1710 }
1799 1711
1800 Object& obj = Object::Handle(isolate); 1712 Object& obj = Object::Handle(isolate);
1801 ObjectIdRing::LookupResult lookup_result; 1713 ObjectIdRing::LookupResult lookup_result;
1802 { 1714 {
1803 HANDLESCOPE(isolate); 1715 HANDLESCOPE(isolate);
1804 obj = LookupHeapObject(isolate, target_id, &lookup_result); 1716 obj = LookupHeapObject(isolate, target_id, &lookup_result);
1805 } 1717 }
1806 if (obj.raw() == Object::sentinel().raw()) { 1718 if (obj.raw() == Object::sentinel().raw()) {
1807 if (lookup_result == ObjectIdRing::kCollected) { 1719 if (lookup_result == ObjectIdRing::kCollected) {
1808 PrintErrorWithKind( 1720 PrintErrorWithKind(
1809 js, "RetainingPathCollected", 1721 js, "RetainingPathCollected",
1810 "attempt to find a retaining path for a collected object\n", 1722 "attempt to find a retaining path for a collected object\n");
1811 js->num_arguments());
1812 return true; 1723 return true;
1813 } else if (lookup_result == ObjectIdRing::kExpired) { 1724 } else if (lookup_result == ObjectIdRing::kExpired) {
1814 PrintErrorWithKind( 1725 PrintErrorWithKind(
1815 js, "RetainingPathExpired", 1726 js, "RetainingPathExpired",
1816 "attempt to find a retaining path for an expired object\n", 1727 "attempt to find a retaining path for an expired object\n");
1817 js->num_arguments());
1818 return true; 1728 return true;
1819 } 1729 }
1820 PrintError(js, "Invalid 'targetId' value: no object with id '%s'", 1730 PrintInvalidParamError(js, "targetId");
1821 target_id);
1822 return true; 1731 return true;
1823 } 1732 }
1824 return PrintRetainingPath(isolate, &obj, limit, js); 1733 return PrintRetainingPath(isolate, &obj, limit, js);
1825 } 1734 }
1826 1735
1827 1736
1828 static bool HandleIsolateGetRetainedSize(Isolate* isolate, JSONStream* js) { 1737 static bool HandleIsolateGetRetainedSize(Isolate* isolate, JSONStream* js) {
1829 const char* target_id = js->LookupOption("targetId"); 1738 const char* target_id = js->LookupParam("targetId");
1830 if (target_id == NULL) { 1739 if (target_id == NULL) {
1831 PrintError(js, "Missing 'targetId' option"); 1740 PrintMissingParamError(js, "targetId");
1832 return true; 1741 return true;
1833 } 1742 }
1834 ObjectIdRing::LookupResult lookup_result; 1743 ObjectIdRing::LookupResult lookup_result;
1835 Object& obj = Object::Handle(LookupHeapObject(isolate, target_id, 1744 Object& obj = Object::Handle(LookupHeapObject(isolate, target_id,
1836 &lookup_result)); 1745 &lookup_result));
1837 if (obj.raw() == Object::sentinel().raw()) { 1746 if (obj.raw() == Object::sentinel().raw()) {
1838 if (lookup_result == ObjectIdRing::kCollected) { 1747 if (lookup_result == ObjectIdRing::kCollected) {
1839 PrintErrorWithKind( 1748 PrintErrorWithKind(
1840 js, "RetainedCollected", 1749 js, "RetainedCollected",
1841 "attempt to calculate size retained by a collected object\n", 1750 "attempt to calculate size retained by a collected object\n");
1842 js->num_arguments());
1843 return true; 1751 return true;
1844 } else if (lookup_result == ObjectIdRing::kExpired) { 1752 } else if (lookup_result == ObjectIdRing::kExpired) {
1845 PrintErrorWithKind( 1753 PrintErrorWithKind(
1846 js, "RetainedExpired", 1754 js, "RetainedExpired",
1847 "attempt to calculate size retained by an expired object\n", 1755 "attempt to calculate size retained by an expired object\n");
1848 js->num_arguments());
1849 return true; 1756 return true;
1850 } 1757 }
1851 PrintError(js, "Invalid 'targetId' value: no object with id '%s'", 1758 PrintInvalidParamError(js, "targetId");
1852 target_id);
1853 return true; 1759 return true;
1854 } 1760 }
1855 if (obj.IsClass()) { 1761 if (obj.IsClass()) {
1856 const Class& cls = Class::Cast(obj); 1762 const Class& cls = Class::Cast(obj);
1857 ObjectGraph graph(isolate); 1763 ObjectGraph graph(isolate);
1858 intptr_t retained_size = graph.SizeRetainedByClass(cls.id()); 1764 intptr_t retained_size = graph.SizeRetainedByClass(cls.id());
1859 const Object& result = Object::Handle(Integer::New(retained_size)); 1765 const Object& result = Object::Handle(Integer::New(retained_size));
1860 result.PrintJSON(js, true); 1766 result.PrintJSON(js, true);
1861 return true; 1767 return true;
1862 } 1768 }
1863 if (obj.IsInstance() || obj.IsNull()) { 1769 if (obj.IsInstance() || obj.IsNull()) {
1864 // We don't use Instance::Cast here because it doesn't allow null. 1770 // We don't use Instance::Cast here because it doesn't allow null.
1865 ObjectGraph graph(isolate); 1771 ObjectGraph graph(isolate);
1866 intptr_t retained_size = graph.SizeRetainedByInstance(obj); 1772 intptr_t retained_size = graph.SizeRetainedByInstance(obj);
1867 const Object& result = Object::Handle(Integer::New(retained_size)); 1773 const Object& result = Object::Handle(Integer::New(retained_size));
1868 result.PrintJSON(js, true); 1774 result.PrintJSON(js, true);
1869 return true; 1775 return true;
1870 } 1776 }
1871 PrintError(js, "Invalid 'targetId' value: id '%s' does not correspond to a " 1777 PrintError(js, "%s: Invalid 'targetId' parameter value: "
1872 "library, class, or instance", target_id); 1778 "id '%s' does not correspond to a "
1873 return true; 1779 "library, class, or instance", js->method(), target_id);
1874 }
1875
1876
1877 static bool HandleClassesClosures(Isolate* isolate, const Class& cls,
1878 JSONStream* js) {
1879 intptr_t id;
1880 if (js->num_arguments() > 4) {
1881 PrintError(js, "Command too long");
1882 return true;
1883 }
1884 if (!GetIntegerId(js->GetArgument(3), &id)) {
1885 PrintError(js, "Must specify collection object id: closures/id");
1886 return true;
1887 }
1888 Function& func = Function::Handle();
1889 func ^= cls.ClosureFunctionFromIndex(id);
1890 if (func.IsNull()) {
1891 PrintError(js, "Closure function %" Pd " not found", id);
1892 return true;
1893 }
1894 func.PrintJSON(js, false);
1895 return true; 1780 return true;
1896 } 1781 }
1897 1782
1898 1783
1899 static bool HandleIsolateEval(Isolate* isolate, JSONStream* js) { 1784 static bool HandleIsolateEval(Isolate* isolate, JSONStream* js) {
1900 const char* target_id = js->LookupOption("targetId"); 1785 const char* target_id = js->LookupParam("targetId");
1901 if (target_id == NULL) { 1786 if (target_id == NULL) {
1902 PrintError(js, "Missing 'targetId' option"); 1787 PrintMissingParamError(js, "targetId");
1903 return true; 1788 return true;
1904 } 1789 }
1905 const char* expr = js->LookupOption("expression"); 1790 const char* expr = js->LookupParam("expression");
1906 if (expr == NULL) { 1791 if (expr == NULL) {
1907 PrintError(js, "Missing 'expression' option"); 1792 PrintMissingParamError(js, "expression");
1908 return true; 1793 return true;
1909 } 1794 }
1910 const String& expr_str = String::Handle(isolate, String::New(expr)); 1795 const String& expr_str = String::Handle(isolate, String::New(expr));
1911 ObjectIdRing::LookupResult lookup_result; 1796 ObjectIdRing::LookupResult lookup_result;
1912 Object& obj = Object::Handle(LookupHeapObject(isolate, target_id, 1797 Object& obj = Object::Handle(LookupHeapObject(isolate, target_id,
1913 &lookup_result)); 1798 &lookup_result));
1914 if (obj.raw() == Object::sentinel().raw()) { 1799 if (obj.raw() == Object::sentinel().raw()) {
1915 if (lookup_result == ObjectIdRing::kCollected) { 1800 if (lookup_result == ObjectIdRing::kCollected) {
1916 PrintSentinel(js, "objects/collected", "<collected>"); 1801 PrintSentinel(js, "objects/collected", "<collected>");
1917 } else if (lookup_result == ObjectIdRing::kExpired) { 1802 } else if (lookup_result == ObjectIdRing::kExpired) {
1918 PrintSentinel(js, "objects/expired", "<expired>"); 1803 PrintSentinel(js, "objects/expired", "<expired>");
1919 } else { 1804 } else {
1920 PrintError(js, "Invalid 'targetId' value: no object with id '%s'", 1805 PrintInvalidParamError(js, "targetId");
1921 target_id);
1922 } 1806 }
1923 return true; 1807 return true;
1924 } 1808 }
1925 if (obj.IsLibrary()) { 1809 if (obj.IsLibrary()) {
1926 const Library& lib = Library::Cast(obj); 1810 const Library& lib = Library::Cast(obj);
1927 const Object& result = Object::Handle(lib.Evaluate(expr_str, 1811 const Object& result = Object::Handle(lib.Evaluate(expr_str,
1928 Array::empty_array(), 1812 Array::empty_array(),
1929 Array::empty_array())); 1813 Array::empty_array()));
1930 result.PrintJSON(js, true); 1814 result.PrintJSON(js, true);
1931 return true; 1815 return true;
(...skipping 11 matching lines...) Expand all
1943 // We don't use Instance::Cast here because it doesn't allow null. 1827 // We don't use Instance::Cast here because it doesn't allow null.
1944 Instance& instance = Instance::Handle(isolate); 1828 Instance& instance = Instance::Handle(isolate);
1945 instance ^= obj.raw(); 1829 instance ^= obj.raw();
1946 const Object& result = 1830 const Object& result =
1947 Object::Handle(instance.Evaluate(expr_str, 1831 Object::Handle(instance.Evaluate(expr_str,
1948 Array::empty_array(), 1832 Array::empty_array(),
1949 Array::empty_array())); 1833 Array::empty_array()));
1950 result.PrintJSON(js, true); 1834 result.PrintJSON(js, true);
1951 return true; 1835 return true;
1952 } 1836 }
1953 PrintError(js, "Invalid 'targetId' value: id '%s' does not correspond to a " 1837 PrintError(js, "%s: Invalid 'targetId' parameter value: "
1954 "library, class, or instance", target_id); 1838 "id '%s' does not correspond to a "
1839 "library, class, or instance", js->method(), target_id);
1955 return true; 1840 return true;
1956 } 1841 }
1957 1842
1958
1959 static bool HandleClassesDispatchers(Isolate* isolate, const Class& cls,
1960 JSONStream* js) {
1961 intptr_t id;
1962 if (js->num_arguments() > 4) {
1963 PrintError(js, "Command too long");
1964 return true;
1965 }
1966 if (!GetIntegerId(js->GetArgument(3), &id)) {
1967 PrintError(js, "Must specify collection object id: dispatchers/id");
1968 return true;
1969 }
1970 Function& func = Function::Handle();
1971 func ^= cls.InvocationDispatcherFunctionFromIndex(id);
1972 if (func.IsNull()) {
1973 PrintError(js, "Dispatcher %" Pd " not found", id);
1974 return true;
1975 }
1976 func.PrintJSON(js, false);
1977 return true;
1978 }
1979
1980
1981 static bool HandleFunctionSetSource(
1982 Isolate* isolate, const Class& cls, const Function& func, JSONStream* js) {
1983 if (js->LookupOption("source") == NULL) {
1984 PrintError(js, "set_source expects a 'source' option\n");
1985 return true;
1986 }
1987 const String& source =
1988 String::Handle(String::New(js->LookupOption("source")));
1989 const Object& result = Object::Handle(
1990 Parser::ParseFunctionFromSource(cls, source));
1991 if (result.IsError()) {
1992 Error::Cast(result).PrintJSON(js, false);
1993 return true;
1994 }
1995 if (!result.IsFunction()) {
1996 PrintError(js, "source did not compile to a function.\n");
1997 return true;
1998 }
1999
2000 // Replace function.
2001 cls.RemoveFunction(func);
2002 cls.AddFunction(Function::Cast(result));
2003
2004 JSONObject jsobj(js);
2005 jsobj.AddProperty("type", "Success");
2006 jsobj.AddProperty("id", "");
2007 return true;
2008 }
2009
2010
2011 static bool HandleClassesFunctions(Isolate* isolate, const Class& cls,
2012 JSONStream* js) {
2013 if (js->num_arguments() != 4 && js->num_arguments() != 5) {
2014 PrintError(js, "Command should have 4 or 5 arguments");
2015 return true;
2016 }
2017 const char* encoded_id = js->GetArgument(3);
2018 String& id = String::Handle(isolate, String::New(encoded_id));
2019 id = String::DecodeIRI(id);
2020 if (id.IsNull()) {
2021 PrintError(js, "Function id %s is malformed", encoded_id);
2022 return true;
2023 }
2024 Function& func = Function::Handle(cls.LookupFunction(id));
2025 if (func.IsNull()) {
2026 PrintError(js, "Function %s not found", encoded_id);
2027 return true;
2028 }
2029 if (js->num_arguments() == 4) {
2030 func.PrintJSON(js, false);
2031 return true;
2032 } else {
2033 const char* subcommand = js->GetArgument(4);
2034 if (strcmp(subcommand, "set_source") == 0) {
2035 return HandleFunctionSetSource(isolate, cls, func, js);
2036 } else {
2037 PrintError(js, "Invalid sub command %s", subcommand);
2038 return true;
2039 }
2040 }
2041 UNREACHABLE();
2042 return true;
2043 }
2044
2045
2046 static bool HandleClassesImplicitClosures(Isolate* isolate, const Class& cls,
2047 JSONStream* js) {
2048 intptr_t id;
2049 if (js->num_arguments() > 4) {
2050 PrintError(js, "Command too long");
2051 return true;
2052 }
2053 if (!GetIntegerId(js->GetArgument(3), &id)) {
2054 PrintError(js, "Must specify collection object id: implicit_closures/id");
2055 return true;
2056 }
2057 Function& func = Function::Handle();
2058 func ^= cls.ImplicitClosureFunctionFromIndex(id);
2059 if (func.IsNull()) {
2060 PrintError(js, "Implicit closure function %" Pd " not found", id);
2061 return true;
2062 }
2063 func.PrintJSON(js, false);
2064 return true;
2065 }
2066
2067
2068 static bool HandleClassesFields(Isolate* isolate, const Class& cls,
2069 JSONStream* js) {
2070 intptr_t id;
2071 if (js->num_arguments() > 4) {
2072 PrintError(js, "Command too long");
2073 return true;
2074 }
2075 if (!GetIntegerId(js->GetArgument(3), &id)) {
2076 PrintError(js, "Must specify collection object id: fields/id");
2077 return true;
2078 }
2079 Field& field = Field::Handle(cls.FieldFromIndex(id));
2080 if (field.IsNull()) {
2081 PrintError(js, "Field %" Pd " not found", id);
2082 return true;
2083 }
2084 field.PrintJSON(js, false);
2085 return true;
2086 }
2087
2088
2089 static bool HandleClassesTypes(Isolate* isolate, const Class& cls,
2090 JSONStream* js) {
2091 if (js->num_arguments() == 3) {
2092 JSONObject jsobj(js);
2093 jsobj.AddProperty("type", "TypeList");
2094 JSONArray members(&jsobj, "members");
2095 const intptr_t num_types = cls.NumCanonicalTypes();
2096 Type& type = Type::Handle();
2097 for (intptr_t i = 0; i < num_types; i++) {
2098 type = cls.CanonicalTypeFromIndex(i);
2099 members.AddValue(type);
2100 }
2101 return true;
2102 }
2103 if (js->num_arguments() > 4) {
2104 PrintError(js, "Command too long");
2105 return true;
2106 }
2107 ASSERT(js->num_arguments() == 4);
2108 intptr_t id;
2109 if (!GetIntegerId(js->GetArgument(3), &id)) {
2110 PrintError(js, "Must specify collection object id: types/id");
2111 return true;
2112 }
2113 Type& type = Type::Handle();
2114 type ^= cls.CanonicalTypeFromIndex(id);
2115 if (type.IsNull()) {
2116 PrintError(js, "Canonical type %" Pd " not found", id);
2117 return true;
2118 }
2119 type.PrintJSON(js, false);
2120 return true;
2121 }
2122
2123 1843
2124 class GetInstancesVisitor : public ObjectGraph::Visitor { 1844 class GetInstancesVisitor : public ObjectGraph::Visitor {
2125 public: 1845 public:
2126 GetInstancesVisitor(const Class& cls, const Array& storage) 1846 GetInstancesVisitor(const Class& cls, const Array& storage)
2127 : cls_(cls), storage_(storage), count_(0) {} 1847 : cls_(cls), storage_(storage), count_(0) {}
2128 1848
2129 virtual Direction VisitObject(ObjectGraph::StackIterator* it) { 1849 virtual Direction VisitObject(ObjectGraph::StackIterator* it) {
2130 RawObject* raw_obj = it->Get(); 1850 RawObject* raw_obj = it->Get();
2131 if (raw_obj->IsFreeListElement()) { 1851 if (raw_obj->IsFreeListElement()) {
2132 return kProceed; 1852 return kProceed;
(...skipping 14 matching lines...) Expand all
2147 intptr_t count() const { return count_; } 1867 intptr_t count() const { return count_; }
2148 1868
2149 private: 1869 private:
2150 const Class& cls_; 1870 const Class& cls_;
2151 const Array& storage_; 1871 const Array& storage_;
2152 intptr_t count_; 1872 intptr_t count_;
2153 }; 1873 };
2154 1874
2155 1875
2156 static bool HandleIsolateGetInstances(Isolate* isolate, JSONStream* js) { 1876 static bool HandleIsolateGetInstances(Isolate* isolate, JSONStream* js) {
2157 const char* target_id = js->LookupOption("classId"); 1877 const char* target_id = js->LookupParam("classId");
2158 if (target_id == NULL) { 1878 if (target_id == NULL) {
2159 PrintError(js, "Missing 'classId' option"); 1879 PrintMissingParamError(js, "classId");
2160 return true; 1880 return true;
2161 } 1881 }
2162 const char* limit_cstr = js->LookupOption("limit"); 1882 const char* limit_cstr = js->LookupParam("limit");
2163 if (target_id == NULL) { 1883 if (target_id == NULL) {
2164 PrintError(js, "Missing 'limit' option"); 1884 PrintMissingParamError(js, "limit");
2165 return true; 1885 return true;
2166 } 1886 }
2167 intptr_t limit; 1887 intptr_t limit;
2168 if (!GetIntegerId(js->LookupOption("limit"), &limit)) { 1888 if (!GetIntegerId(limit_cstr, &limit)) {
2169 PrintError(js, "Invalid 'limit' option: %s", limit_cstr); 1889 PrintInvalidParamError(js, "limit");
2170 return true; 1890 return true;
2171 } 1891 }
2172 const Object& obj = 1892 const Object& obj =
2173 Object::Handle(LookupHeapObject(isolate, target_id, NULL)); 1893 Object::Handle(LookupHeapObject(isolate, target_id, NULL));
2174 if (obj.raw() == Object::sentinel().raw() || 1894 if (obj.raw() == Object::sentinel().raw() ||
2175 !obj.IsClass()) { 1895 !obj.IsClass()) {
2176 PrintError(js, "Invalid 'classId' value: no class with id '%s'", target_id); 1896 PrintInvalidParamError(js, "classId");
2177 return true; 1897 return true;
2178 } 1898 }
2179 const Class& cls = Class::Cast(obj); 1899 const Class& cls = Class::Cast(obj);
2180 Array& storage = Array::Handle(Array::New(limit)); 1900 Array& storage = Array::Handle(Array::New(limit));
2181 GetInstancesVisitor visitor(cls, storage); 1901 GetInstancesVisitor visitor(cls, storage);
2182 ObjectGraph graph(isolate); 1902 ObjectGraph graph(isolate);
2183 graph.IterateObjects(&visitor); 1903 graph.IterateObjects(&visitor);
2184 intptr_t count = visitor.count(); 1904 intptr_t count = visitor.count();
2185 if (count < limit) { 1905 if (count < limit) {
2186 // Truncate the list using utility method for GrowableObjectArray. 1906 // Truncate the list using utility method for GrowableObjectArray.
2187 GrowableObjectArray& wrapper = GrowableObjectArray::Handle( 1907 GrowableObjectArray& wrapper = GrowableObjectArray::Handle(
2188 GrowableObjectArray::New(storage)); 1908 GrowableObjectArray::New(storage));
2189 wrapper.SetLength(count); 1909 wrapper.SetLength(count);
2190 storage = Array::MakeArray(wrapper); 1910 storage = Array::MakeArray(wrapper);
2191 } 1911 }
2192 JSONObject jsobj(js); 1912 JSONObject jsobj(js);
2193 jsobj.AddProperty("type", "InstanceSet"); 1913 jsobj.AddProperty("type", "InstanceSet");
2194 jsobj.AddProperty("id", "instance_set"); 1914 jsobj.AddProperty("id", "instance_set");
2195 jsobj.AddProperty("totalCount", count); 1915 jsobj.AddProperty("totalCount", count);
2196 jsobj.AddProperty("sampleCount", storage.Length()); 1916 jsobj.AddProperty("sampleCount", storage.Length());
2197 jsobj.AddProperty("sample", storage); 1917 jsobj.AddProperty("sample", storage);
2198 return true; 1918 return true;
2199 } 1919 }
2200 1920
2201 1921
2202 static bool HandleClasses(Isolate* isolate, JSONStream* js) {
2203 if (js->num_arguments() == 1) {
2204 PrintError(js, "Invalid number of arguments.");
2205 return true;
2206 }
2207 ASSERT(js->num_arguments() >= 2);
2208 intptr_t id;
2209 if (!GetIntegerId(js->GetArgument(1), &id)) {
2210 PrintError(js, "Must specify collection object id: /classes/id");
2211 return true;
2212 }
2213 ClassTable* table = isolate->class_table();
2214 if (!table->IsValidIndex(id)) {
2215 PrintError(js, "%" Pd " is not a valid class id.", id);
2216 return true;
2217 }
2218 Class& cls = Class::Handle(table->At(id));
2219 if (js->num_arguments() == 2) {
2220 cls.PrintJSON(js, false);
2221 return true;
2222 } else if (js->num_arguments() >= 3) {
2223 const char* second = js->GetArgument(2);
2224 if (strcmp(second, "closures") == 0) {
2225 return HandleClassesClosures(isolate, cls, js);
2226 } else if (strcmp(second, "fields") == 0) {
2227 return HandleClassesFields(isolate, cls, js);
2228 } else if (strcmp(second, "functions") == 0) {
2229 return HandleClassesFunctions(isolate, cls, js);
2230 } else if (strcmp(second, "implicit_closures") == 0) {
2231 return HandleClassesImplicitClosures(isolate, cls, js);
2232 } else if (strcmp(second, "dispatchers") == 0) {
2233 return HandleClassesDispatchers(isolate, cls, js);
2234 } else if (strcmp(second, "types") == 0) {
2235 return HandleClassesTypes(isolate, cls, js);
2236 } else {
2237 PrintError(js, "Invalid sub collection %s", second);
2238 return true;
2239 }
2240 }
2241 UNREACHABLE();
2242 return true;
2243 }
2244
2245
2246 static bool HandleIsolateGetCoverage(Isolate* isolate, JSONStream* js) { 1922 static bool HandleIsolateGetCoverage(Isolate* isolate, JSONStream* js) {
2247 if (!js->HasOption("targetId")) { 1923 if (!js->HasParam("targetId")) {
2248 CodeCoverage::PrintJSON(isolate, js, NULL); 1924 CodeCoverage::PrintJSON(isolate, js, NULL);
2249 return true; 1925 return true;
2250 } 1926 }
2251 const char* target_id = js->LookupOption("targetId"); 1927 const char* target_id = js->LookupParam("targetId");
2252 Object& obj = Object::Handle(LookupHeapObject(isolate, target_id, NULL)); 1928 Object& obj = Object::Handle(LookupHeapObject(isolate, target_id, NULL));
2253 if (obj.raw() == Object::sentinel().raw()) { 1929 if (obj.raw() == Object::sentinel().raw()) {
2254 PrintError(js, "Invalid 'targetId' value: no object with id '%s'", 1930 PrintInvalidParamError(js, "targetId");
2255 target_id);
2256 return true; 1931 return true;
2257 } 1932 }
2258 if (obj.IsScript()) { 1933 if (obj.IsScript()) {
2259 ScriptCoverageFilter sf(Script::Cast(obj)); 1934 ScriptCoverageFilter sf(Script::Cast(obj));
2260 CodeCoverage::PrintJSON(isolate, js, &sf); 1935 CodeCoverage::PrintJSON(isolate, js, &sf);
2261 return true; 1936 return true;
2262 } 1937 }
2263 if (obj.IsLibrary()) { 1938 if (obj.IsLibrary()) {
2264 LibraryCoverageFilter lf(Library::Cast(obj)); 1939 LibraryCoverageFilter lf(Library::Cast(obj));
2265 CodeCoverage::PrintJSON(isolate, js, &lf); 1940 CodeCoverage::PrintJSON(isolate, js, &lf);
2266 return true; 1941 return true;
2267 } 1942 }
2268 if (obj.IsClass()) { 1943 if (obj.IsClass()) {
2269 ClassCoverageFilter cf(Class::Cast(obj)); 1944 ClassCoverageFilter cf(Class::Cast(obj));
2270 CodeCoverage::PrintJSON(isolate, js, &cf); 1945 CodeCoverage::PrintJSON(isolate, js, &cf);
2271 return true; 1946 return true;
2272 } 1947 }
2273 if (obj.IsFunction()) { 1948 if (obj.IsFunction()) {
2274 FunctionCoverageFilter ff(Function::Cast(obj)); 1949 FunctionCoverageFilter ff(Function::Cast(obj));
2275 CodeCoverage::PrintJSON(isolate, js, &ff); 1950 CodeCoverage::PrintJSON(isolate, js, &ff);
2276 return true; 1951 return true;
2277 } 1952 }
2278 PrintError(js, "Invalid 'targetId' value: id '%s' does not correspond to a " 1953 PrintError(js, "%s: Invalid 'targetId' parameter value: "
2279 "script, library, class, or function", target_id); 1954 "id '%s' does not correspond to a "
1955 "script, library, class, or function", js->method(), target_id);
2280 return true; 1956 return true;
2281 } 1957 }
2282 1958
2283 1959
2284 static bool HandleIsolateAddBreakpoint(Isolate* isolate, JSONStream* js) { 1960 static bool HandleIsolateAddBreakpoint(Isolate* isolate, JSONStream* js) {
2285 if (!js->HasOption("line")) { 1961 if (!js->HasParam("line")) {
2286 PrintError(js, "Missing 'line' option"); 1962 PrintMissingParamError(js, "line");
2287 return true; 1963 return true;
2288 } 1964 }
2289 const char* line_option = js->LookupOption("line"); 1965 const char* line_param = js->LookupParam("line");
2290 intptr_t line = -1; 1966 intptr_t line = -1;
2291 if (!GetIntegerId(line_option, &line)) { 1967 if (!GetIntegerId(line_param, &line)) {
2292 PrintError(js, "Invalid 'line' value: %s is not an integer", line_option); 1968 PrintInvalidParamError(js, "line");
2293 return true; 1969 return true;
2294 } 1970 }
2295 const char* script_id = js->LookupOption("script"); 1971 const char* script_id = js->LookupParam("script");
2296 Object& obj = Object::Handle(LookupHeapObject(isolate, script_id, NULL)); 1972 Object& obj = Object::Handle(LookupHeapObject(isolate, script_id, NULL));
2297 if (obj.raw() == Object::sentinel().raw() || !obj.IsScript()) { 1973 if (obj.raw() == Object::sentinel().raw() || !obj.IsScript()) {
2298 PrintError(js, "Invalid 'script' value: no script with id '%s'", script_id); 1974 PrintInvalidParamError(js, "script");
2299 return true; 1975 return true;
2300 } 1976 }
2301 const Script& script = Script::Cast(obj); 1977 const Script& script = Script::Cast(obj);
2302 const String& script_url = String::Handle(script.url()); 1978 const String& script_url = String::Handle(script.url());
2303 SourceBreakpoint* bpt = 1979 SourceBreakpoint* bpt =
2304 isolate->debugger()->SetBreakpointAtLine(script_url, line); 1980 isolate->debugger()->SetBreakpointAtLine(script_url, line);
2305 if (bpt == NULL) { 1981 if (bpt == NULL) {
2306 PrintError(js, "Unable to set breakpoint at line %s", line_option); 1982 PrintError(js, "Unable to set breakpoint at line %s", line_param);
2307 return true; 1983 return true;
2308 } 1984 }
2309 bpt->PrintJSON(js); 1985 bpt->PrintJSON(js);
2310 return true; 1986 return true;
2311 } 1987 }
2312 1988
2313 1989
2314 static bool HandleIsolateRemoveBreakpoint(Isolate* isolate, JSONStream* js) { 1990 static bool HandleIsolateRemoveBreakpoint(Isolate* isolate, JSONStream* js) {
2315 if (!js->HasOption("breakpointId")) { 1991 if (!js->HasParam("breakpointId")) {
2316 PrintError(js, "Missing 'breakpointId' option"); 1992 PrintMissingParamError(js, "breakpointId");
2317 return true; 1993 return true;
2318 } 1994 }
2319 const char* bpt_id = js->LookupOption("breakpointId"); 1995 const char* bpt_id = js->LookupParam("breakpointId");
2320 SourceBreakpoint* bpt = LookupBreakpoint(isolate, bpt_id); 1996 SourceBreakpoint* bpt = LookupBreakpoint(isolate, bpt_id);
2321 if (bpt == NULL) { 1997 if (bpt == NULL) {
2322 fprintf(stderr, "ERROR1"); 1998 fprintf(stderr, "ERROR1");
2323 PrintError(js, "Invalid 'breakpointId' value: no breakpoint with id '%s'", 1999 PrintInvalidParamError(js, "breakpointId");
2324 bpt_id);
2325 return true; 2000 return true;
2326 } 2001 }
2327 isolate->debugger()->RemoveBreakpoint(bpt->id()); 2002 isolate->debugger()->RemoveBreakpoint(bpt->id());
2328 2003
2329 fprintf(stderr, "SUCCESS"); 2004 fprintf(stderr, "SUCCESS");
2330 // TODO(turnidge): Consider whether the 'Success' type is proper. 2005 // TODO(turnidge): Consider whether the 'Success' type is proper.
2331 JSONObject jsobj(js); 2006 JSONObject jsobj(js);
2332 jsobj.AddProperty("type", "Success"); 2007 jsobj.AddProperty("type", "Success");
2333 jsobj.AddProperty("id", ""); 2008 jsobj.AddProperty("id", "");
2334 return true; 2009 return true;
2335 } 2010 }
2336 2011
2337 2012
2338 static bool HandleLibrariesScripts(Isolate* isolate,
2339 const Library& lib,
2340 JSONStream* js) {
2341 if (js->num_arguments() > 5) {
2342 PrintError(js, "Command too long");
2343 return true;
2344 } else if (js->num_arguments() < 4) {
2345 PrintError(js, "Must specify collection object id: scripts/id");
2346 return true;
2347 }
2348 const String& id = String::Handle(String::New(js->GetArgument(3)));
2349 ASSERT(!id.IsNull());
2350 // The id is the url of the script % encoded, decode it.
2351 const String& requested_url = String::Handle(String::DecodeIRI(id));
2352 Script& script = Script::Handle();
2353 String& script_url = String::Handle();
2354 const Array& loaded_scripts = Array::Handle(lib.LoadedScripts());
2355 ASSERT(!loaded_scripts.IsNull());
2356 intptr_t i;
2357 for (i = 0; i < loaded_scripts.Length(); i++) {
2358 script ^= loaded_scripts.At(i);
2359 ASSERT(!script.IsNull());
2360 script_url ^= script.url();
2361 if (script_url.Equals(requested_url)) {
2362 break;
2363 }
2364 }
2365 if (i == loaded_scripts.Length()) {
2366 PrintError(js, "Script %s not found", requested_url.ToCString());
2367 return true;
2368 }
2369 if (js->num_arguments() > 4) {
2370 PrintError(js, "Command too long");
2371 return true;
2372 }
2373 script.PrintJSON(js, false);
2374 return true;
2375 }
2376
2377
2378 static bool HandleLibraries(Isolate* isolate, JSONStream* js) {
2379 // TODO(johnmccutchan): Support fields and functions on libraries.
2380 REQUIRE_COLLECTION_ID("libraries");
2381 const GrowableObjectArray& libs =
2382 GrowableObjectArray::Handle(isolate->object_store()->libraries());
2383 ASSERT(!libs.IsNull());
2384 intptr_t id = 0;
2385 CHECK_COLLECTION_ID_BOUNDS("libraries", libs.Length(), js->GetArgument(1),
2386 id, js);
2387 Library& lib = Library::Handle();
2388 lib ^= libs.At(id);
2389 ASSERT(!lib.IsNull());
2390 if (js->num_arguments() == 2) {
2391 lib.PrintJSON(js, false);
2392 return true;
2393 } else if (js->num_arguments() >= 3) {
2394 const char* second = js->GetArgument(2);
2395 if (strcmp(second, "scripts") == 0) {
2396 return HandleLibrariesScripts(isolate, lib, js);
2397 } else {
2398 PrintError(js, "Invalid sub collection %s", second);
2399 return true;
2400 }
2401 }
2402 UNREACHABLE();
2403 return true;
2404 }
2405
2406
2407 static RawClass* GetMetricsClass(Isolate* isolate) { 2013 static RawClass* GetMetricsClass(Isolate* isolate) {
2408 const Library& prof_lib = 2014 const Library& prof_lib =
2409 Library::Handle(isolate, Library::ProfilerLibrary()); 2015 Library::Handle(isolate, Library::ProfilerLibrary());
2410 ASSERT(!prof_lib.IsNull()); 2016 ASSERT(!prof_lib.IsNull());
2411 const String& metrics_cls_name = 2017 const String& metrics_cls_name =
2412 String::Handle(isolate, String::New("Metrics")); 2018 String::Handle(isolate, String::New("Metrics"));
2413 ASSERT(!metrics_cls_name.IsNull()); 2019 ASSERT(!metrics_cls_name.IsNull());
2414 const Class& metrics_cls = 2020 const Class& metrics_cls =
2415 Class::Handle(isolate, prof_lib.LookupClass(metrics_cls_name)); 2021 Class::Handle(isolate, prof_lib.LookupClass(metrics_cls_name));
2416 ASSERT(!metrics_cls.IsNull()); 2022 ASSERT(!metrics_cls.IsNull());
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
2493 buffer->AddString(String::Cast(result).ToCString()); 2099 buffer->AddString(String::Cast(result).ToCString());
2494 return true; 2100 return true;
2495 } 2101 }
2496 PrintError(js, "Dart Metric %s not found\n", id); 2102 PrintError(js, "Dart Metric %s not found\n", id);
2497 return true; 2103 return true;
2498 } 2104 }
2499 2105
2500 2106
2501 static bool HandleIsolateGetMetricList(Isolate* isolate, JSONStream* js) { 2107 static bool HandleIsolateGetMetricList(Isolate* isolate, JSONStream* js) {
2502 bool native_metrics = false; 2108 bool native_metrics = false;
2503 if (js->HasOption("type")) { 2109 if (js->HasParam("type")) {
2504 if (js->OptionIs("type", "Native")) { 2110 if (js->ParamIs("type", "Native")) {
2505 native_metrics = true; 2111 native_metrics = true;
2506 } else if (js->OptionIs("type", "Dart")) { 2112 } else if (js->ParamIs("type", "Dart")) {
2507 native_metrics = false; 2113 native_metrics = false;
2508 } else { 2114 } else {
2509 PrintError(js, "Invalid 'type' option value: %s\n", 2115 PrintInvalidParamError(js, "type");
2510 js->LookupOption("type"));
2511 return true; 2116 return true;
2512 } 2117 }
2513 } else { 2118 } else {
2514 PrintError(js, "Expected 'type' option."); 2119 PrintMissingParamError(js, "type");
2515 return true; 2120 return true;
2516 } 2121 }
2517 if (native_metrics) { 2122 if (native_metrics) {
2518 return HandleNativeMetricsList(isolate, js); 2123 return HandleNativeMetricsList(isolate, js);
2519 } 2124 }
2520 return HandleDartMetricsList(isolate, js); 2125 return HandleDartMetricsList(isolate, js);
2521 } 2126 }
2522 2127
2523 2128
2524 static bool HandleIsolateGetMetric(Isolate* isolate, JSONStream* js) { 2129 static bool HandleIsolateGetMetric(Isolate* isolate, JSONStream* js) {
2525 const char* metric_id = js->LookupOption("metricId"); 2130 const char* metric_id = js->LookupParam("metricId");
2526 if (metric_id == NULL) { 2131 if (metric_id == NULL) {
2527 PrintError(js, "Expected 'metricId' option."); 2132 PrintMissingParamError(js, "metricId");
2528 return true; 2133 return true;
2529 } 2134 }
2530 // Verify id begins with "metrics/". 2135 // Verify id begins with "metrics/".
2531 static const char* kMetricIdPrefix = "metrics/"; 2136 static const char* kMetricIdPrefix = "metrics/";
2532 static intptr_t kMetricIdPrefixLen = strlen(kMetricIdPrefix); 2137 static intptr_t kMetricIdPrefixLen = strlen(kMetricIdPrefix);
2533 if (strncmp(metric_id, kMetricIdPrefix, kMetricIdPrefixLen) != 0) { 2138 if (strncmp(metric_id, kMetricIdPrefix, kMetricIdPrefixLen) != 0) {
2534 PrintError(js, "Metric %s not found\n", metric_id); 2139 PrintError(js, "Metric %s not found\n", metric_id);
2535 } 2140 }
2536 // Check if id begins with "metrics/native/". 2141 // Check if id begins with "metrics/native/".
2537 static const char* kNativeMetricIdPrefix = "metrics/native/"; 2142 static const char* kNativeMetricIdPrefix = "metrics/native/";
2538 static intptr_t kNativeMetricIdPrefixLen = strlen(kNativeMetricIdPrefix); 2143 static intptr_t kNativeMetricIdPrefixLen = strlen(kNativeMetricIdPrefix);
2539 const bool native_metric = 2144 const bool native_metric =
2540 strncmp(metric_id, kNativeMetricIdPrefix, kNativeMetricIdPrefixLen) == 0; 2145 strncmp(metric_id, kNativeMetricIdPrefix, kNativeMetricIdPrefixLen) == 0;
2541 if (native_metric) { 2146 if (native_metric) {
2542 const char* id = metric_id + kNativeMetricIdPrefixLen; 2147 const char* id = metric_id + kNativeMetricIdPrefixLen;
2543 return HandleNativeMetric(isolate, js, id); 2148 return HandleNativeMetric(isolate, js, id);
2544 } 2149 }
2545 const char* id = metric_id + kMetricIdPrefixLen; 2150 const char* id = metric_id + kMetricIdPrefixLen;
2546 return HandleDartMetric(isolate, js, id); 2151 return HandleDartMetric(isolate, js, id);
2547 } 2152 }
2548 2153
2549 2154
2550 static bool HandleVMGetMetricList(JSONStream* js) { 2155 static bool HandleVMGetMetricList(JSONStream* js) {
2551 return false; 2156 return false;
2552 } 2157 }
2553 2158
2554 2159
2555 static bool HandleVMGetMetric(JSONStream* js) { 2160 static bool HandleVMGetMetric(JSONStream* js) {
2556 const char* metric_id = js->LookupOption("metricId"); 2161 const char* metric_id = js->LookupParam("metricId");
2557 if (metric_id == NULL) { 2162 if (metric_id == NULL) {
2558 PrintError(js, "Expected 'metricId' option."); 2163 PrintMissingParamError(js, "metricId");
2559 } 2164 }
2560 return false; 2165 return false;
2561 } 2166 }
2562 2167
2563 2168
2564 static bool HandleObjects(Isolate* isolate, JSONStream* js) {
2565 REQUIRE_COLLECTION_ID("objects");
2566 if (js->num_arguments() != 2) {
2567 PrintError(js, "expected at least 2 arguments but found %" Pd "\n",
2568 js->num_arguments());
2569 return true;
2570 }
2571 const char* arg = js->GetArgument(1);
2572
2573 // Handle special non-objects first.
2574 if (strcmp(arg, "optimized-out") == 0) {
2575 if (js->num_arguments() > 2) {
2576 PrintError(js, "expected at most 2 arguments but found %" Pd "\n",
2577 js->num_arguments());
2578 } else {
2579 Symbols::OptimizedOut().PrintJSON(js, false);
2580 }
2581 return true;
2582
2583 } else if (strcmp(arg, "collected") == 0) {
2584 if (js->num_arguments() > 2) {
2585 PrintError(js, "expected at most 2 arguments but found %" Pd "\n",
2586 js->num_arguments());
2587 } else {
2588 PrintSentinel(js, "objects/collected", "<collected>");
2589 }
2590 return true;
2591
2592 } else if (strcmp(arg, "expired") == 0) {
2593 if (js->num_arguments() > 2) {
2594 PrintError(js, "expected at most 2 arguments but found %" Pd "\n",
2595 js->num_arguments());
2596 } else {
2597 PrintSentinel(js, "objects/expired", "<expired>");
2598 }
2599 return true;
2600 }
2601
2602 // Lookup the object.
2603 Object& obj = Object::Handle(isolate);
2604 ObjectIdRing::LookupResult kind = ObjectIdRing::kInvalid;
2605 obj = LookupObjectId(isolate, arg, &kind);
2606 if (kind == ObjectIdRing::kInvalid) {
2607 PrintError(js, "unrecognized object id '%s'", arg);
2608 return true;
2609 }
2610
2611 // Print.
2612 if (kind == ObjectIdRing::kCollected) {
2613 // The object has been collected by the gc.
2614 PrintSentinel(js, "objects/collected", "<collected>");
2615 return true;
2616 } else if (kind == ObjectIdRing::kExpired) {
2617 // The object id has expired.
2618 PrintSentinel(js, "objects/expired", "<expired>");
2619 return true;
2620 }
2621 obj.PrintJSON(js, false);
2622 return true;
2623 }
2624
2625
2626 static bool HandleScriptsEnumerate(Isolate* isolate, JSONStream* js) {
2627 JSONObject jsobj(js);
2628 jsobj.AddProperty("type", "ScriptList");
2629 jsobj.AddProperty("id", "scripts");
2630 JSONArray members(&jsobj, "members");
2631 const GrowableObjectArray& libs =
2632 GrowableObjectArray::Handle(isolate->object_store()->libraries());
2633 intptr_t num_libs = libs.Length();
2634 Library &lib = Library::Handle();
2635 Script& script = Script::Handle();
2636 for (intptr_t i = 0; i < num_libs; i++) {
2637 lib ^= libs.At(i);
2638 ASSERT(!lib.IsNull());
2639 ASSERT(Smi::IsValid(lib.index()));
2640 const Array& loaded_scripts = Array::Handle(lib.LoadedScripts());
2641 ASSERT(!loaded_scripts.IsNull());
2642 intptr_t num_scripts = loaded_scripts.Length();
2643 for (intptr_t i = 0; i < num_scripts; i++) {
2644 script ^= loaded_scripts.At(i);
2645 members.AddValue(script);
2646 }
2647 }
2648 return true;
2649 }
2650
2651
2652 static bool HandleScripts(Isolate* isolate, JSONStream* js) {
2653 if (js->num_arguments() == 1) {
2654 // Enumerate all scripts.
2655 return HandleScriptsEnumerate(isolate, js);
2656 }
2657 PrintError(js, "Command too long");
2658 return true;
2659 }
2660
2661
2662 static bool HandleIsolateResume(Isolate* isolate, JSONStream* js) { 2169 static bool HandleIsolateResume(Isolate* isolate, JSONStream* js) {
2663 const char* step_option = js->LookupOption("step"); 2170 const char* step_param = js->LookupParam("step");
2664 if (isolate->message_handler()->paused_on_start()) { 2171 if (isolate->message_handler()->paused_on_start()) {
2665 isolate->message_handler()->set_pause_on_start(false); 2172 isolate->message_handler()->set_pause_on_start(false);
2666 JSONObject jsobj(js); 2173 JSONObject jsobj(js);
2667 jsobj.AddProperty("type", "Success"); 2174 jsobj.AddProperty("type", "Success");
2668 jsobj.AddProperty("id", ""); 2175 jsobj.AddProperty("id", "");
2669 return true; 2176 return true;
2670 } 2177 }
2671 if (isolate->message_handler()->paused_on_exit()) { 2178 if (isolate->message_handler()->paused_on_exit()) {
2672 isolate->message_handler()->set_pause_on_exit(false); 2179 isolate->message_handler()->set_pause_on_exit(false);
2673 JSONObject jsobj(js); 2180 JSONObject jsobj(js);
2674 jsobj.AddProperty("type", "Success"); 2181 jsobj.AddProperty("type", "Success");
2675 jsobj.AddProperty("id", ""); 2182 jsobj.AddProperty("id", "");
2676 return true; 2183 return true;
2677 } 2184 }
2678 if (isolate->debugger()->PauseEvent() != NULL) { 2185 if (isolate->debugger()->PauseEvent() != NULL) {
2679 if (step_option != NULL) { 2186 if (step_param != NULL) {
2680 if (strcmp(step_option, "into") == 0) { 2187 if (strcmp(step_param, "into") == 0) {
2681 isolate->debugger()->SetSingleStep(); 2188 isolate->debugger()->SetSingleStep();
2682 } else if (strcmp(step_option, "over") == 0) { 2189 } else if (strcmp(step_param, "over") == 0) {
2683 isolate->debugger()->SetStepOver(); 2190 isolate->debugger()->SetStepOver();
2684 } else if (strcmp(step_option, "out") == 0) { 2191 } else if (strcmp(step_param, "out") == 0) {
2685 isolate->debugger()->SetStepOut(); 2192 isolate->debugger()->SetStepOut();
2686 } else { 2193 } else {
2687 PrintError(js, "Invalid 'step' option: %s", step_option); 2194 PrintInvalidParamError(js, "step");
2688 return true; 2195 return true;
2689 } 2196 }
2690 } 2197 }
2691 isolate->Resume(); 2198 isolate->Resume();
2692 JSONObject jsobj(js); 2199 JSONObject jsobj(js);
2693 jsobj.AddProperty("type", "Success"); 2200 jsobj.AddProperty("type", "Success");
2694 jsobj.AddProperty("id", ""); 2201 jsobj.AddProperty("id", "");
2695 return true; 2202 return true;
2696 } 2203 }
2697 2204
(...skipping 14 matching lines...) Expand all
2712 static bool HandleIsolatePause(Isolate* isolate, JSONStream* js) { 2219 static bool HandleIsolatePause(Isolate* isolate, JSONStream* js) {
2713 // TODO(turnidge): Don't double-interrupt the isolate here. 2220 // TODO(turnidge): Don't double-interrupt the isolate here.
2714 isolate->ScheduleInterrupts(Isolate::kApiInterrupt); 2221 isolate->ScheduleInterrupts(Isolate::kApiInterrupt);
2715 JSONObject jsobj(js); 2222 JSONObject jsobj(js);
2716 jsobj.AddProperty("type", "Success"); 2223 jsobj.AddProperty("type", "Success");
2717 jsobj.AddProperty("id", ""); 2224 jsobj.AddProperty("id", "");
2718 return true; 2225 return true;
2719 } 2226 }
2720 2227
2721 2228
2722 static bool HandleNullCode(uintptr_t pc, JSONStream* js) {
2723 // TODO(turnidge): Consider adding/using Object::null_code() for
2724 // consistent "type".
2725 Object::null_object().PrintJSON(js, false);
2726 return true;
2727 }
2728
2729
2730 static bool HandleCode(Isolate* isolate, JSONStream* js) {
2731 REQUIRE_COLLECTION_ID("code");
2732 uword pc;
2733 if (js->num_arguments() > 2) {
2734 PrintError(js, "Command too long");
2735 return true;
2736 }
2737 ASSERT(js->num_arguments() == 2);
2738 static const char* kCollectedPrefix = "collected-";
2739 static intptr_t kCollectedPrefixLen = strlen(kCollectedPrefix);
2740 static const char* kNativePrefix = "native-";
2741 static intptr_t kNativePrefixLen = strlen(kNativePrefix);
2742 static const char* kReusedPrefix = "reused-";
2743 static intptr_t kReusedPrefixLen = strlen(kReusedPrefix);
2744 const char* command = js->GetArgument(1);
2745 if (strncmp(kCollectedPrefix, command, kCollectedPrefixLen) == 0) {
2746 if (!GetUnsignedIntegerId(&command[kCollectedPrefixLen], &pc, 16)) {
2747 PrintError(js, "Must specify code address: code/%sc0deadd0.",
2748 kCollectedPrefix);
2749 return true;
2750 }
2751 return HandleNullCode(pc, js);
2752 }
2753 if (strncmp(kNativePrefix, command, kNativePrefixLen) == 0) {
2754 if (!GetUnsignedIntegerId(&command[kNativePrefixLen], &pc, 16)) {
2755 PrintError(js, "Must specify code address: code/%sc0deadd0.",
2756 kNativePrefix);
2757 return true;
2758 }
2759 // TODO(johnmccutchan): Support native Code.
2760 return HandleNullCode(pc, js);
2761 }
2762 if (strncmp(kReusedPrefix, command, kReusedPrefixLen) == 0) {
2763 if (!GetUnsignedIntegerId(&command[kReusedPrefixLen], &pc, 16)) {
2764 PrintError(js, "Must specify code address: code/%sc0deadd0.",
2765 kReusedPrefix);
2766 return true;
2767 }
2768 return HandleNullCode(pc, js);
2769 }
2770 int64_t timestamp = 0;
2771 if (!GetCodeId(command, &timestamp, &pc) || (timestamp < 0)) {
2772 PrintError(js, "Malformed code id: %s", command);
2773 return true;
2774 }
2775 Code& code = Code::Handle(Code::FindCode(pc, timestamp));
2776 if (!code.IsNull()) {
2777 code.PrintJSON(js, false);
2778 return true;
2779 }
2780 PrintError(js, "Could not find code with id: %s", command);
2781 return true;
2782 }
2783
2784
2785 static bool HandleIsolateGetTagProfile(Isolate* isolate, JSONStream* js) { 2229 static bool HandleIsolateGetTagProfile(Isolate* isolate, JSONStream* js) {
2786 JSONObject miniProfile(js); 2230 JSONObject miniProfile(js);
2787 miniProfile.AddProperty("type", "TagProfile"); 2231 miniProfile.AddProperty("type", "TagProfile");
2788 miniProfile.AddProperty("id", "profile/tag"); 2232 miniProfile.AddProperty("id", "profile/tag");
2789 isolate->vm_tag_counters()->PrintToJSONObject(&miniProfile); 2233 isolate->vm_tag_counters()->PrintToJSONObject(&miniProfile);
2790 return true; 2234 return true;
2791 } 2235 }
2792 2236
2793 static bool HandleIsolateGetCpuProfile(Isolate* isolate, JSONStream* js) { 2237 static bool HandleIsolateGetCpuProfile(Isolate* isolate, JSONStream* js) {
2794 // A full profile includes disassembly of all Dart code objects. 2238 // A full profile includes disassembly of all Dart code objects.
2795 // TODO(johnmccutchan): Add sub command to trigger full code dump. 2239 // TODO(johnmccutchan): Add option to trigger full code dump.
2796 bool full_profile = false; 2240 bool full_profile = false;
2797 const char* tags_option = js->LookupOption("tags");
2798 Profiler::TagOrder tag_order = Profiler::kUserVM; 2241 Profiler::TagOrder tag_order = Profiler::kUserVM;
2799 if (js->HasOption("tags")) { 2242 if (js->HasParam("tags")) {
2800 if (js->OptionIs("tags", "None")) { 2243 if (js->ParamIs("tags", "None")) {
2801 tag_order = Profiler::kNoTags; 2244 tag_order = Profiler::kNoTags;
2802 } else if (js->OptionIs("tags", "UserVM")) { 2245 } else if (js->ParamIs("tags", "UserVM")) {
2803 tag_order = Profiler::kUserVM; 2246 tag_order = Profiler::kUserVM;
2804 } else if (js->OptionIs("tags", "UserOnly")) { 2247 } else if (js->ParamIs("tags", "UserOnly")) {
2805 tag_order = Profiler::kUser; 2248 tag_order = Profiler::kUser;
2806 } else if (js->OptionIs("tags", "VMUser")) { 2249 } else if (js->ParamIs("tags", "VMUser")) {
2807 tag_order = Profiler::kVMUser; 2250 tag_order = Profiler::kVMUser;
2808 } else if (js->OptionIs("tags", "VMOnly")) { 2251 } else if (js->ParamIs("tags", "VMOnly")) {
2809 tag_order = Profiler::kVM; 2252 tag_order = Profiler::kVM;
2810 } else { 2253 } else {
2811 PrintError(js, "Invalid tags option value: %s\n", tags_option); 2254 PrintInvalidParamError(js, "tags");
2812 return true; 2255 return true;
2813 } 2256 }
2814 } 2257 }
2815 Profiler::PrintJSON(isolate, js, full_profile, tag_order); 2258 Profiler::PrintJSON(isolate, js, full_profile, tag_order);
2816 return true; 2259 return true;
2817 } 2260 }
2818 2261
2819 2262
2820 static bool HandleIsolateGetAllocationProfile(Isolate* isolate, 2263 static bool HandleIsolateGetAllocationProfile(Isolate* isolate,
2821 JSONStream* js) { 2264 JSONStream* js) {
2822 bool should_reset_accumulator = false; 2265 bool should_reset_accumulator = false;
2823 bool should_collect = false; 2266 bool should_collect = false;
2824 if (js->HasOption("reset")) { 2267 if (js->HasParam("reset")) {
2825 if (js->OptionIs("reset", "true")) { 2268 if (js->ParamIs("reset", "true")) {
2826 should_reset_accumulator = true; 2269 should_reset_accumulator = true;
2827 } else { 2270 } else {
2828 PrintError(js, "Unrecognized reset option '%s'", 2271 PrintInvalidParamError(js, "reset");
2829 js->LookupOption("reset"));
2830 return true; 2272 return true;
2831 } 2273 }
2832 } 2274 }
2833 if (js->HasOption("gc")) { 2275 if (js->HasParam("gc")) {
2834 if (js->OptionIs("gc", "full")) { 2276 if (js->ParamIs("gc", "full")) {
2835 should_collect = true; 2277 should_collect = true;
2836 } else { 2278 } else {
2837 PrintError(js, "Unrecognized gc option '%s'", js->LookupOption("gc")); 2279 PrintInvalidParamError(js, "gc");
2838 return true; 2280 return true;
2839 } 2281 }
2840 } 2282 }
2841 if (should_reset_accumulator) { 2283 if (should_reset_accumulator) {
2842 isolate->UpdateLastAllocationProfileAccumulatorResetTimestamp(); 2284 isolate->UpdateLastAllocationProfileAccumulatorResetTimestamp();
2843 isolate->class_table()->ResetAllocationAccumulators(); 2285 isolate->class_table()->ResetAllocationAccumulators();
2844 } 2286 }
2845 if (should_collect) { 2287 if (should_collect) {
2846 isolate->UpdateLastAllocationProfileGCTimestamp(); 2288 isolate->UpdateLastAllocationProfileGCTimestamp();
2847 isolate->heap()->CollectAllGarbage(); 2289 isolate->heap()->CollectAllGarbage();
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
2900 } 2342 }
2901 uword obj_begin = RawObject::ToAddr(obj); 2343 uword obj_begin = RawObject::ToAddr(obj);
2902 uword obj_end = obj_begin + obj->Size(); 2344 uword obj_end = obj_begin + obj->Size();
2903 return obj_begin <= addr_ && addr_ < obj_end; 2345 return obj_begin <= addr_ && addr_ < obj_end;
2904 } 2346 }
2905 private: 2347 private:
2906 uword addr_; 2348 uword addr_;
2907 }; 2349 };
2908 2350
2909 2351
2910 static bool HandleAddress(Isolate* isolate, JSONStream* js) { 2352 static bool HandleIsolateGetObjectByAddress(Isolate* isolate, JSONStream* js) {
2911 uword addr = 0; 2353 const char* addr_str = js->LookupParam("address");
2912 if (js->num_arguments() != 2 || 2354 if (addr_str == NULL) {
2913 !GetUnsignedIntegerId(js->GetArgument(1), &addr, 16)) { 2355 PrintMissingParamError(js, "address");
2914 static const uword kExampleAddr = static_cast<uword>(kIntptrMax / 7);
2915 PrintError(js, "Must specify address: address/" Px ".", kExampleAddr);
2916 return true; 2356 return true;
2917 } 2357 }
2918 bool ref = js->HasOption("ref") && js->OptionIs("ref", "true"); 2358
2359 // Handle heap objects.
2360 uword addr = 0;
2361 if (!GetUnsignedIntegerId(addr_str, &addr, 16)) {
2362 PrintInvalidParamError(js, "address");
2363 return true;
2364 }
2365 bool ref = js->HasParam("ref") && js->ParamIs("ref", "true");
2919 Object& object = Object::Handle(isolate); 2366 Object& object = Object::Handle(isolate);
2920 { 2367 {
2921 NoGCScope no_gc; 2368 NoGCScope no_gc;
2922 ContainsAddressVisitor visitor(isolate, addr); 2369 ContainsAddressVisitor visitor(isolate, addr);
2923 object = isolate->heap()->FindObject(&visitor); 2370 object = isolate->heap()->FindObject(&visitor);
2924 } 2371 }
2925 object.PrintJSON(js, ref); 2372 object.PrintJSON(js, ref);
2926 return true; 2373 return true;
2927 } 2374 }
2928 2375
(...skipping 13 matching lines...) Expand all
2942 2389
2943 2390
2944 static bool HandleIsolateRespondWithMalformedObject(Isolate* isolate, 2391 static bool HandleIsolateRespondWithMalformedObject(Isolate* isolate,
2945 JSONStream* js) { 2392 JSONStream* js) {
2946 JSONObject jsobj(js); 2393 JSONObject jsobj(js);
2947 jsobj.AddProperty("bart", "simpson"); 2394 jsobj.AddProperty("bart", "simpson");
2948 return true; 2395 return true;
2949 } 2396 }
2950 2397
2951 2398
2952 static IsolateMessageHandlerEntry isolate_handlers[] = {
2953 { "", HandleIsolate }, // getObject
2954 { "address", HandleAddress }, // to do
2955 { "classes", HandleClasses }, // getObject
2956 { "code", HandleCode }, // getObject
2957 { "libraries", HandleLibraries }, // getObject
2958 { "objects", HandleObjects }, // getObject
2959 { "scripts", HandleScripts }, // getObject
2960 };
2961
2962
2963 static IsolateMessageHandler FindIsolateMessageHandler(const char* command) {
2964 intptr_t num_message_handlers = sizeof(isolate_handlers) /
2965 sizeof(isolate_handlers[0]);
2966 for (intptr_t i = 0; i < num_message_handlers; i++) {
2967 const IsolateMessageHandlerEntry& entry = isolate_handlers[i];
2968 if (strcmp(command, entry.command) == 0) {
2969 return entry.handler;
2970 }
2971 }
2972 if (FLAG_trace_service) {
2973 OS::Print("vm-service: No isolate message handler for <%s>.\n", command);
2974 }
2975 return NULL;
2976 }
2977
2978
2979 static bool HandleIsolateGetObject(Isolate* isolate, JSONStream* js) { 2399 static bool HandleIsolateGetObject(Isolate* isolate, JSONStream* js) {
2980 const char* id = js->LookupOption("objectId"); 2400 const char* id = js->LookupParam("objectId");
2981 if (id == NULL) { 2401 if (id == NULL) {
2982 // TODO(turnidge): Print the isolate here instead. 2402 PrintMissingParamError(js, "objectId");
2983 PrintError(js, "GetObject expects an 'objectId' parameter\n",
2984 js->num_arguments());
2985 return true; 2403 return true;
2986 } 2404 }
2987 2405
2988 // Handle heap objects. 2406 // Handle heap objects.
2989 ObjectIdRing::LookupResult lookup_result; 2407 ObjectIdRing::LookupResult lookup_result;
2990 const Object& obj = 2408 const Object& obj =
2991 Object::Handle(LookupHeapObject(isolate, id, &lookup_result)); 2409 Object::Handle(LookupHeapObject(isolate, id, &lookup_result));
2992 if (obj.raw() != Object::sentinel().raw()) { 2410 if (obj.raw() != Object::sentinel().raw()) {
2993 // We found a heap object for this id. Return it. 2411 // We found a heap object for this id. Return it.
2994 obj.PrintJSON(js, false); 2412 obj.PrintJSON(js, false);
2995 return true; 2413 return true;
2996 } else if (lookup_result == ObjectIdRing::kCollected) { 2414 } else if (lookup_result == ObjectIdRing::kCollected) {
2997 PrintSentinel(js, "objects/collected", "<collected>"); 2415 PrintSentinel(js, "objects/collected", "<collected>");
2416 return true;
2998 } else if (lookup_result == ObjectIdRing::kExpired) { 2417 } else if (lookup_result == ObjectIdRing::kExpired) {
2999 PrintSentinel(js, "objects/expired", "<expired>"); 2418 PrintSentinel(js, "objects/expired", "<expired>");
2419 return true;
3000 } 2420 }
3001 2421
3002 // Handle non-heap objects. 2422 // Handle non-heap objects.
3003 SourceBreakpoint* bpt = LookupBreakpoint(isolate, id); 2423 SourceBreakpoint* bpt = LookupBreakpoint(isolate, id);
3004 if (bpt != NULL) { 2424 if (bpt != NULL) {
3005 bpt->PrintJSON(js); 2425 bpt->PrintJSON(js);
3006 return true; 2426 return true;
3007 } 2427 }
3008 2428
3009 PrintError(js, "Unrecognized object id: %s\n", id); 2429 PrintError(js, "Unrecognized object id: %s\n", id);
3010 return true; 2430 return true;
3011 } 2431 }
3012 2432
3013 2433
3014 static bool HandleIsolateGetClassList(Isolate* isolate, JSONStream* js) { 2434 static bool HandleIsolateGetClassList(Isolate* isolate, JSONStream* js) {
3015 ClassTable* table = isolate->class_table(); 2435 ClassTable* table = isolate->class_table();
3016 JSONObject jsobj(js); 2436 JSONObject jsobj(js);
3017 table->PrintToJSONObject(&jsobj); 2437 table->PrintToJSONObject(&jsobj);
3018 return true; 2438 return true;
3019 } 2439 }
3020 2440
3021 2441
3022 static bool HandleIsolateGetTypeArgumentsList(Isolate* isolate, 2442 static bool HandleIsolateGetTypeArgumentsList(Isolate* isolate,
3023 JSONStream* js) { 2443 JSONStream* js) {
3024 bool only_with_instantiations = false; 2444 bool only_with_instantiations = false;
3025 if (js->OptionIs("onlyWithInstantiations", "true")) { 2445 if (js->ParamIs("onlyWithInstantiations", "true")) {
3026 only_with_instantiations = true; 2446 only_with_instantiations = true;
3027 } 2447 }
3028 ObjectStore* object_store = isolate->object_store(); 2448 ObjectStore* object_store = isolate->object_store();
3029 const Array& table = Array::Handle(object_store->canonical_type_arguments()); 2449 const Array& table = Array::Handle(object_store->canonical_type_arguments());
3030 ASSERT(table.Length() > 0); 2450 ASSERT(table.Length() > 0);
3031 TypeArguments& type_args = TypeArguments::Handle(); 2451 TypeArguments& type_args = TypeArguments::Handle();
3032 const intptr_t table_size = table.Length() - 1; 2452 const intptr_t table_size = table.Length() - 1;
3033 const intptr_t table_used = Smi::Value(Smi::RawCast(table.At(table_size))); 2453 const intptr_t table_used = Smi::Value(Smi::RawCast(table.At(table_size)));
3034 JSONObject jsobj(js); 2454 JSONObject jsobj(js);
3035 jsobj.AddProperty("type", "TypeArgumentsList"); 2455 jsobj.AddProperty("type", "TypeArgumentsList");
3036 jsobj.AddProperty("canonicalTypeArgumentsTableSize", table_size); 2456 jsobj.AddProperty("canonicalTypeArgumentsTableSize", table_size);
3037 jsobj.AddProperty("canonicalTypeArgumentsTableUsed", table_used); 2457 jsobj.AddProperty("canonicalTypeArgumentsTableUsed", table_used);
3038 JSONArray members(&jsobj, "typeArguments"); 2458 JSONArray members(&jsobj, "typeArguments");
3039 for (intptr_t i = 0; i < table_size; i++) { 2459 for (intptr_t i = 0; i < table_size; i++) {
3040 type_args ^= table.At(i); 2460 type_args ^= table.At(i);
3041 if (!type_args.IsNull()) { 2461 if (!type_args.IsNull()) {
3042 if (!only_with_instantiations || type_args.HasInstantiations()) { 2462 if (!only_with_instantiations || type_args.HasInstantiations()) {
3043 members.AddValue(type_args); 2463 members.AddValue(type_args);
3044 } 2464 }
3045 } 2465 }
3046 } 2466 }
3047 return true; 2467 return true;
3048 } 2468 }
3049 2469
3050 2470
3051 static IsolateMessageHandlerEntry isolate_handlers_new[] = { 2471 static IsolateMessageHandlerEntry isolate_handlers_new[] = {
3052 { "getIsolate", HandleIsolate }, 2472 { "getIsolate", HandleIsolate },
3053 { "getObject", HandleIsolateGetObject }, 2473 { "getObject", HandleIsolateGetObject },
2474 { "getObjectByAddress", HandleIsolateGetObjectByAddress },
3054 { "getBreakpoints", HandleIsolateGetBreakpoints }, 2475 { "getBreakpoints", HandleIsolateGetBreakpoints },
3055 { "pause", HandleIsolatePause }, 2476 { "pause", HandleIsolatePause },
3056 { "resume", HandleIsolateResume }, 2477 { "resume", HandleIsolateResume },
3057 { "getStack", HandleIsolateGetStack }, 2478 { "getStack", HandleIsolateGetStack },
3058 { "getCpuProfile", HandleIsolateGetCpuProfile }, 2479 { "getCpuProfile", HandleIsolateGetCpuProfile },
3059 { "getTagProfile", HandleIsolateGetTagProfile }, 2480 { "getTagProfile", HandleIsolateGetTagProfile },
3060 { "getAllocationProfile", HandleIsolateGetAllocationProfile }, 2481 { "getAllocationProfile", HandleIsolateGetAllocationProfile },
3061 { "getHeapMap", HandleIsolateGetHeapMap }, 2482 { "getHeapMap", HandleIsolateGetHeapMap },
3062 { "addBreakpoint", HandleIsolateAddBreakpoint }, 2483 { "addBreakpoint", HandleIsolateAddBreakpoint },
3063 { "removeBreakpoint", HandleIsolateRemoveBreakpoint }, 2484 { "removeBreakpoint", HandleIsolateRemoveBreakpoint },
3064 { "getCoverage", HandleIsolateGetCoverage }, 2485 { "getCoverage", HandleIsolateGetCoverage },
3065 { "eval", HandleIsolateEval }, 2486 { "eval", HandleIsolateEval },
3066 { "getRetainedSize", HandleIsolateGetRetainedSize }, 2487 { "getRetainedSize", HandleIsolateGetRetainedSize },
3067 { "getRetainingPath", HandleIsolateGetRetainingPath }, 2488 { "getRetainingPath", HandleIsolateGetRetainingPath },
3068 { "getInboundReferences", HandleIsolateGetInboundReferences }, 2489 { "getInboundReferences", HandleIsolateGetInboundReferences },
3069 { "getInstances", HandleIsolateGetInstances }, 2490 { "getInstances", HandleIsolateGetInstances },
3070 { "requestHeapSnapshot", HandleIsolateRequestHeapSnapshot }, 2491 { "requestHeapSnapshot", HandleIsolateRequestHeapSnapshot },
3071 { "getClassList", HandleIsolateGetClassList }, 2492 { "getClassList", HandleIsolateGetClassList },
3072 { "getTypeArgumentsList", HandleIsolateGetTypeArgumentsList }, 2493 { "getTypeArgumentsList", HandleIsolateGetTypeArgumentsList },
3073 { "getIsolateMetricList", HandleIsolateGetMetricList }, 2494 { "getIsolateMetricList", HandleIsolateGetMetricList },
3074 { "getIsolateMetric", HandleIsolateGetMetric }, 2495 { "getIsolateMetric", HandleIsolateGetMetric },
3075 { "_echo", HandleIsolateEcho }, 2496 { "_echo", HandleIsolateEcho },
3076 { "_triggerEchoEvent", HandleIsolateTriggerEchoEvent }, 2497 { "_triggerEchoEvent", HandleIsolateTriggerEchoEvent },
3077 { "_respondWithMalformedJson", HandleIsolateRespondWithMalformedJson }, 2498 { "_respondWithMalformedJson", HandleIsolateRespondWithMalformedJson },
3078 { "_respondWithMalformedObject", HandleIsolateRespondWithMalformedObject }, 2499 { "_respondWithMalformedObject", HandleIsolateRespondWithMalformedObject },
3079 }; 2500 };
3080 2501
3081 2502
3082 static IsolateMessageHandler FindIsolateMessageHandlerNew(const char* command) { 2503 static IsolateMessageHandler FindIsolateMessageHandler(const char* method) {
3083 intptr_t num_message_handlers = sizeof(isolate_handlers_new) / 2504 intptr_t num_message_handlers = sizeof(isolate_handlers_new) /
3084 sizeof(isolate_handlers_new[0]); 2505 sizeof(isolate_handlers_new[0]);
3085 for (intptr_t i = 0; i < num_message_handlers; i++) { 2506 for (intptr_t i = 0; i < num_message_handlers; i++) {
3086 const IsolateMessageHandlerEntry& entry = isolate_handlers_new[i]; 2507 const IsolateMessageHandlerEntry& entry = isolate_handlers_new[i];
3087 if (strcmp(command, entry.command) == 0) { 2508 if (strcmp(method, entry.method) == 0) {
3088 return entry.handler; 2509 return entry.handler;
3089 } 2510 }
3090 } 2511 }
3091 if (FLAG_trace_service) { 2512 if (FLAG_trace_service) {
3092 OS::Print("Service has no isolate message handler for <%s>\n", command); 2513 OS::Print("Service has no isolate message handler for <%s>\n", method);
3093 } 2514 }
3094 return NULL; 2515 return NULL;
3095 } 2516 }
3096 2517
3097 2518
3098 void Service::HandleRootMessageNew(const Array& msg) { 2519 void Service::HandleRootMessage(const Instance& msg_instance) {
3099 Isolate* isolate = Isolate::Current(); 2520 Isolate* isolate = Isolate::Current();
3100 ASSERT(!msg.IsNull()); 2521 ASSERT(!msg_instance.IsNull());
2522 ASSERT(msg_instance.IsArray());
3101 2523
3102 { 2524 {
3103 StackZone zone(isolate); 2525 StackZone zone(isolate);
3104 HANDLESCOPE(isolate); 2526 HANDLESCOPE(isolate);
3105 2527
3106 const Array& message = Array::Cast(msg); 2528 const Array& msg = Array::Cast(msg_instance);
3107 // Message is a list with five entries. 2529 ASSERT(msg.Length() == 5);
3108 ASSERT(message.Length() == 5);
3109 2530
3110 Instance& reply_port = Instance::Handle(isolate); 2531 Instance& reply_port = Instance::Handle(isolate);
3111 String& method = String::Handle(isolate); 2532 String& method = String::Handle(isolate);
3112 Array& param_keys = Array::Handle(isolate); 2533 Array& param_keys = Array::Handle(isolate);
3113 Array& param_values = Array::Handle(isolate); 2534 Array& param_values = Array::Handle(isolate);
3114 reply_port ^= msg.At(1); 2535 reply_port ^= msg.At(1);
3115 method ^= msg.At(2); 2536 method ^= msg.At(2);
3116 param_keys ^= msg.At(3); 2537 param_keys ^= msg.At(3);
3117 param_values ^= msg.At(4); 2538 param_values ^= msg.At(4);
3118 2539
3119 ASSERT(!method.IsNull()); 2540 ASSERT(!method.IsNull());
3120 ASSERT(!param_keys.IsNull()); 2541 ASSERT(!param_keys.IsNull());
3121 ASSERT(!param_values.IsNull()); 2542 ASSERT(!param_values.IsNull());
3122 ASSERT(param_keys.Length() == param_values.Length()); 2543 ASSERT(param_keys.Length() == param_values.Length());
3123 2544
3124 if (!reply_port.IsSendPort()) { 2545 if (!reply_port.IsSendPort()) {
3125 FATAL("SendPort expected."); 2546 FATAL("SendPort expected.");
3126 } 2547 }
3127 2548
3128 RootMessageHandler handler = 2549 RootMessageHandler handler =
3129 FindRootMessageHandlerNew(method.ToCString()); 2550 FindRootMessageHandler(method.ToCString());
3130 { 2551 {
3131 JSONStream js; 2552 JSONStream js;
3132 js.SetupNew(zone.GetZone(), SendPort::Cast(reply_port).Id(), 2553 js.Setup(zone.GetZone(), SendPort::Cast(reply_port).Id(),
3133 method, param_keys, param_values); 2554 method, param_keys, param_values);
3134 if (handler == NULL) { 2555 if (handler == NULL) {
3135 // Check for an embedder handler. 2556 // Check for an embedder handler.
3136 EmbedderServiceHandler* e_handler = 2557 EmbedderServiceHandler* e_handler =
3137 FindRootEmbedderHandler(method.ToCString()); 2558 FindRootEmbedderHandler(method.ToCString());
3138 if (e_handler != NULL) { 2559 if (e_handler != NULL) {
3139 EmbedderHandleMessage(e_handler, &js); 2560 EmbedderHandleMessage(e_handler, &js);
3140 } else { 2561 } else {
3141 if (FindIsolateMessageHandlerNew(method.ToCString()) != NULL) { 2562 if (FindIsolateMessageHandler(method.ToCString()) != NULL) {
3142 PrintError(&js, "%s expects an 'isolate' parameter\n", 2563 PrintMissingParamError(&js, "isolateId");
3143 method.ToCString());
3144 } else { 2564 } else {
3145 PrintError(&js, "Unrecognized method: %s", method.ToCString()); 2565 PrintError(&js, "Unrecognized method: %s", method.ToCString());
3146 } 2566 }
3147 } 2567 }
3148 js.PostReply(); 2568 js.PostReply();
3149 } else { 2569 } else {
3150 if (handler(&js)) { 2570 if (handler(&js)) {
3151 // Handler returns true if the reply is ready to be posted. 2571 // Handler returns true if the reply is ready to be posted.
3152 // TODO(johnmccutchan): Support asynchronous replies. 2572 // TODO(johnmccutchan): Support asynchronous replies.
3153 js.PostReply(); 2573 js.PostReply();
3154 } 2574 }
3155 } 2575 }
3156 } 2576 }
3157 } 2577 }
3158 } 2578 }
3159 2579
3160 2580
3161 void Service::HandleRootMessage(const Instance& msg) {
3162 Isolate* isolate = Isolate::Current();
3163 ASSERT(!msg.IsNull());
3164 ASSERT(msg.IsArray());
3165
3166 {
3167 StackZone zone(isolate);
3168 HANDLESCOPE(isolate);
3169
3170 const Array& message = Array::Cast(msg);
3171 // Message is a list with five entries.
3172 ASSERT(message.Length() == 5);
3173
3174 Object& tmp = Object::Handle(isolate);
3175 tmp = message.At(2);
3176 if (tmp.IsString()) {
3177 return Service::HandleRootMessageNew(message);
3178 }
3179
3180 Instance& reply_port = Instance::Handle(isolate);
3181 GrowableObjectArray& path = GrowableObjectArray::Handle(isolate);
3182 Array& option_keys = Array::Handle(isolate);
3183 Array& option_values = Array::Handle(isolate);
3184
3185 reply_port ^= message.At(1);
3186 path ^= message.At(2);
3187 option_keys ^= message.At(3);
3188 option_values ^= message.At(4);
3189
3190 ASSERT(!path.IsNull());
3191 ASSERT(!option_keys.IsNull());
3192 ASSERT(!option_values.IsNull());
3193 // Path always has at least one entry in it.
3194 ASSERT(path.Length() > 0);
3195 // Same number of option keys as values.
3196 ASSERT(option_keys.Length() == option_values.Length());
3197
3198 if (!reply_port.IsSendPort()) {
3199 FATAL("SendPort expected.");
3200 }
3201
3202 String& path_segment = String::Handle();
3203 if (path.Length() > 0) {
3204 path_segment ^= path.At(0);
3205 } else {
3206 path_segment ^= Symbols::Empty().raw();
3207 }
3208 ASSERT(!path_segment.IsNull());
3209 const char* path_segment_c = path_segment.ToCString();
3210
3211 RootMessageHandler handler =
3212 FindRootMessageHandler(path_segment_c);
3213 {
3214 JSONStream js;
3215 js.Setup(zone.GetZone(), SendPort::Cast(reply_port).Id(),
3216 path, option_keys, option_values);
3217 if (handler == NULL) {
3218 // Check for an embedder handler.
3219 EmbedderServiceHandler* e_handler =
3220 FindRootEmbedderHandler(path_segment_c);
3221 if (e_handler != NULL) {
3222 EmbedderHandleMessage(e_handler, &js);
3223 } else {
3224 PrintError(&js, "Unrecognized path");
3225 }
3226 js.PostReply();
3227 } else {
3228 if (handler(&js)) {
3229 // Handler returns true if the reply is ready to be posted.
3230 // TODO(johnmccutchan): Support asynchronous replies.
3231 js.PostReply();
3232 }
3233 }
3234 }
3235 }
3236 }
3237
3238
3239 static bool HandleRootEcho(JSONStream* js) { 2581 static bool HandleRootEcho(JSONStream* js) {
3240 JSONObject jsobj(js); 2582 JSONObject jsobj(js);
3241 return HandleCommonEcho(&jsobj, js); 2583 return HandleCommonEcho(&jsobj, js);
3242 } 2584 }
3243 2585
3244 2586
3245 class ServiceIsolateVisitor : public IsolateVisitor { 2587 class ServiceIsolateVisitor : public IsolateVisitor {
3246 public: 2588 public:
3247 explicit ServiceIsolateVisitor(JSONArray* jsarr) 2589 explicit ServiceIsolateVisitor(JSONArray* jsarr)
3248 : jsarr_(jsarr) { 2590 : jsarr_(jsarr) {
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
3286 // Construct the isolate list. 2628 // Construct the isolate list.
3287 { 2629 {
3288 JSONArray jsarr(&jsobj, "isolates"); 2630 JSONArray jsarr(&jsobj, "isolates");
3289 ServiceIsolateVisitor visitor(&jsarr); 2631 ServiceIsolateVisitor visitor(&jsarr);
3290 Isolate::VisitIsolates(&visitor); 2632 Isolate::VisitIsolates(&visitor);
3291 } 2633 }
3292 return true; 2634 return true;
3293 } 2635 }
3294 2636
3295 2637
3296 static bool HandleFlags(JSONStream* js) { 2638 static bool HandleVMFlagList(JSONStream* js) {
3297 if (js->num_arguments() == 1) { 2639 Flags::PrintJSON(js);
3298 Flags::PrintJSON(js); 2640 return true;
2641 }
2642
2643
2644 static bool HandleVMSetFlag(JSONStream* js) {
2645 const char* flag_name = js->LookupParam("name");
2646 if (flag_name == NULL) {
2647 PrintMissingParamError(js, "name");
3299 return true; 2648 return true;
3300 } else if (js->num_arguments() == 2) { 2649 }
3301 const char* arg = js->GetArgument(1); 2650 const char* flag_value = js->LookupParam("value");
3302 if (strcmp(arg, "set") == 0) { 2651 if (flag_value == NULL) {
3303 if (js->num_arguments() > 2) { 2652 PrintMissingParamError(js, "value");
3304 PrintError(js, "expected at most 2 arguments but found %" Pd "\n", 2653 return true;
3305 js->num_arguments()); 2654 }
3306 } else { 2655 JSONObject jsobj(js);
3307 if (js->HasOption("name") && js->HasOption("value")) { 2656 const char* error = NULL;
3308 JSONObject jsobj(js); 2657 if (Flags::SetFlag(flag_name, flag_value, &error)) {
3309 const char* flag_name = js->LookupOption("name"); 2658 jsobj.AddProperty("type", "Success");
3310 const char* flag_value = js->LookupOption("value"); 2659 jsobj.AddProperty("id", "");
3311 const char* error = NULL;
3312 if (Flags::SetFlag(flag_name, flag_value, &error)) {
3313 jsobj.AddProperty("type", "Success");
3314 jsobj.AddProperty("id", "");
3315 } else {
3316 jsobj.AddProperty("type", "Failure");
3317 jsobj.AddProperty("id", "");
3318 jsobj.AddProperty("message", error);
3319 }
3320 } else {
3321 PrintError(js, "expected to find 'name' and 'value' options");
3322 }
3323 }
3324 }
3325 return true; 2660 return true;
3326 } else { 2661 } else {
3327 PrintError(js, "Command too long"); 2662 jsobj.AddProperty("type", "Failure");
2663 jsobj.AddProperty("id", "");
2664 jsobj.AddProperty("message", error);
3328 return true; 2665 return true;
3329 } 2666 }
3330 } 2667 }
3331 2668
3332 static RootMessageHandlerEntry root_handlers[] = {
3333 { "vm", HandleVM },
3334 { "flags", HandleFlags },
3335 };
3336
3337
3338 static RootMessageHandler FindRootMessageHandler(const char* command) {
3339 intptr_t num_message_handlers = sizeof(root_handlers) /
3340 sizeof(root_handlers[0]);
3341 for (intptr_t i = 0; i < num_message_handlers; i++) {
3342 const RootMessageHandlerEntry& entry = root_handlers[i];
3343 if (strcmp(command, entry.command) == 0) {
3344 return entry.handler;
3345 }
3346 }
3347 if (FLAG_trace_service) {
3348 OS::Print("vm-service: No root message handler for <%s>.\n", command);
3349 }
3350 return NULL;
3351 }
3352
3353 2669
3354 static RootMessageHandlerEntry root_handlers_new[] = { 2670 static RootMessageHandlerEntry root_handlers_new[] = {
3355 { "getVM", HandleVM }, 2671 { "getVM", HandleVM },
2672 { "getFlagList", HandleVMFlagList },
2673 { "setFlag", HandleVMSetFlag },
3356 { "getVMMetricList", HandleVMGetMetricList }, 2674 { "getVMMetricList", HandleVMGetMetricList },
3357 { "getVMMetric", HandleVMGetMetric }, 2675 { "getVMMetric", HandleVMGetMetric },
3358 { "_echo", HandleRootEcho }, 2676 { "_echo", HandleRootEcho },
3359 }; 2677 };
3360 2678
3361 2679
3362 static RootMessageHandler FindRootMessageHandlerNew(const char* command) { 2680 static RootMessageHandler FindRootMessageHandler(const char* method) {
3363 intptr_t num_message_handlers = sizeof(root_handlers_new) / 2681 intptr_t num_message_handlers = sizeof(root_handlers_new) /
3364 sizeof(root_handlers_new[0]); 2682 sizeof(root_handlers_new[0]);
3365 for (intptr_t i = 0; i < num_message_handlers; i++) { 2683 for (intptr_t i = 0; i < num_message_handlers; i++) {
3366 const RootMessageHandlerEntry& entry = root_handlers_new[i]; 2684 const RootMessageHandlerEntry& entry = root_handlers_new[i];
3367 if (strcmp(command, entry.command) == 0) { 2685 if (strcmp(method, entry.method) == 0) {
3368 return entry.handler; 2686 return entry.handler;
3369 } 2687 }
3370 } 2688 }
3371 if (FLAG_trace_service) { 2689 if (FLAG_trace_service) {
3372 OS::Print("vm-service: No root message handler for <%s>.\n", command); 2690 OS::Print("vm-service: No root message handler for <%s>.\n", method);
3373 } 2691 }
3374 return NULL; 2692 return NULL;
3375 } 2693 }
3376 2694
3377 2695
3378 void Service::SendEvent(intptr_t eventId, const Object& eventMessage) { 2696 void Service::SendEvent(intptr_t eventId, const Object& eventMessage) {
3379 if (!IsRunning()) { 2697 if (!IsRunning()) {
3380 return; 2698 return;
3381 } 2699 }
3382 Isolate* isolate = Isolate::Current(); 2700 Isolate* isolate = Isolate::Current();
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
3449 SendEvent(kEventFamilyDebug, message); 2767 SendEvent(kEventFamilyDebug, message);
3450 } 2768 }
3451 2769
3452 2770
3453 void Service::EmbedderHandleMessage(EmbedderServiceHandler* handler, 2771 void Service::EmbedderHandleMessage(EmbedderServiceHandler* handler,
3454 JSONStream* js) { 2772 JSONStream* js) {
3455 ASSERT(handler != NULL); 2773 ASSERT(handler != NULL);
3456 Dart_ServiceRequestCallback callback = handler->callback(); 2774 Dart_ServiceRequestCallback callback = handler->callback();
3457 ASSERT(callback != NULL); 2775 ASSERT(callback != NULL);
3458 const char* r = NULL; 2776 const char* r = NULL;
3459 const char* name = js->command(); 2777 const char* name = js->method();
3460 const char** arguments = js->arguments(); 2778 const char** keys = js->param_keys();
3461 const char** keys = js->option_keys(); 2779 const char** values = js->param_values();
3462 const char** values = js->option_values(); 2780 r = callback(name, keys, values, js->num_params(), handler->user_data());
3463 r = callback(name, arguments, js->num_arguments(), keys, values,
3464 js->num_options(), handler->user_data());
3465 ASSERT(r != NULL); 2781 ASSERT(r != NULL);
3466 // TODO(johnmccutchan): Allow for NULL returns? 2782 // TODO(johnmccutchan): Allow for NULL returns?
3467 TextBuffer* buffer = js->buffer(); 2783 TextBuffer* buffer = js->buffer();
3468 buffer->AddString(r); 2784 buffer->AddString(r);
3469 free(const_cast<char*>(r)); 2785 free(const_cast<char*>(r));
3470 } 2786 }
3471 2787
3472 2788
3473 void Service::RegisterIsolateEmbedderCallback( 2789 void Service::RegisterIsolateEmbedderCallback(
3474 const char* name, 2790 const char* name,
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
3539 while (current != NULL) { 2855 while (current != NULL) {
3540 if (strcmp(name, current->name()) == 0) { 2856 if (strcmp(name, current->name()) == 0) {
3541 return current; 2857 return current;
3542 } 2858 }
3543 current = current->next(); 2859 current = current->next();
3544 } 2860 }
3545 return NULL; 2861 return NULL;
3546 } 2862 }
3547 2863
3548 } // namespace dart 2864 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/service.h ('k') | runtime/vm/service/message.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698