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

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: 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
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 PrintMissingParamError(&js, "isolate");
958 method.ToCString());
959 } else { 966 } else {
960 PrintError(&js, "Unrecognized method: %s", method.ToCString()); 967 PrintError(&js, "Unrecognized method: %s", method.ToCString());
961 } 968 }
962 } 969 }
963 js.PostReply(); 970 js.PostReply();
964 } else { 971 } else {
965 if (handler(isolate, &js)) { 972 if (handler(isolate, &js)) {
966 // Handler returns true if the reply is ready to be posted. 973 // Handler returns true if the reply is ready to be posted.
967 // TODO(johnmccutchan): Support asynchronous replies. 974 // TODO(johnmccutchan): Support asynchronous replies.
968 js.PostReply(); 975 js.PostReply();
969 } 976 }
970 } 977 }
971 } 978 }
972 } 979 }
973 } 980 }
974 981
975 982
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) { 983 static bool HandleIsolate(Isolate* isolate, JSONStream* js) {
1050 isolate->PrintJSON(js, false); 984 isolate->PrintJSON(js, false);
1051 return true; 985 return true;
1052 } 986 }
1053 987
1054 988
1055 static bool HandleIsolateGetStack(Isolate* isolate, JSONStream* js) { 989 static bool HandleIsolateGetStack(Isolate* isolate, JSONStream* js) {
1056 DebuggerStackTrace* stack = isolate->debugger()->StackTrace(); 990 DebuggerStackTrace* stack = isolate->debugger()->StackTrace();
1057 JSONObject jsobj(js); 991 JSONObject jsobj(js);
1058 jsobj.AddProperty("type", "Stack"); 992 jsobj.AddProperty("type", "Stack");
1059 JSONArray jsarr(&jsobj, "frames"); 993 JSONArray jsarr(&jsobj, "frames");
1060 intptr_t num_frames = stack->Length(); 994 intptr_t num_frames = stack->Length();
1061 for (intptr_t i = 0; i < num_frames; i++) { 995 for (intptr_t i = 0; i < num_frames; i++) {
1062 ActivationFrame* frame = stack->FrameAt(i); 996 ActivationFrame* frame = stack->FrameAt(i);
1063 JSONObject jsobj(&jsarr); 997 JSONObject jsobj(&jsarr);
1064 frame->PrintToJSONObject(&jsobj); 998 frame->PrintToJSONObject(&jsobj);
1065 // TODO(turnidge): Implement depth differently -- differentiate 999 // TODO(turnidge): Implement depth differently -- differentiate
1066 // inlined frames. 1000 // inlined frames.
1067 jsobj.AddProperty("depth", i); 1001 jsobj.AddProperty("depth", i);
1068 } 1002 }
1069 return true; 1003 return true;
1070 } 1004 }
1071 1005
1072 1006
1073 static bool HandleCommonEcho(JSONObject* jsobj, JSONStream* js) { 1007 static bool HandleCommonEcho(JSONObject* jsobj, JSONStream* js) {
1074 jsobj->AddProperty("type", "_EchoResponse"); 1008 jsobj->AddProperty("type", "_EchoResponse");
1075 if (js->HasOption("text")) { 1009 if (js->HasParam("text")) {
1076 jsobj->AddProperty("text", js->LookupOption("text")); 1010 jsobj->AddProperty("text", js->LookupParam("text"));
1077 } 1011 }
1078 return true; 1012 return true;
1079 } 1013 }
1080 1014
1081 1015
1082 void Service::SendEchoEvent(Isolate* isolate, const char* text) { 1016 void Service::SendEchoEvent(Isolate* isolate, const char* text) {
1083 JSONStream js; 1017 JSONStream js;
1084 { 1018 {
1085 JSONObject jsobj(&js); 1019 JSONObject jsobj(&js);
1086 jsobj.AddProperty("type", "ServiceEvent"); 1020 jsobj.AddProperty("type", "ServiceEvent");
1087 jsobj.AddProperty("eventType", "_Echo"); 1021 jsobj.AddProperty("eventType", "_Echo");
1088 jsobj.AddProperty("isolate", isolate); 1022 jsobj.AddProperty("isolate", isolate);
1089 if (text != NULL) { 1023 if (text != NULL) {
1090 jsobj.AddProperty("text", text); 1024 jsobj.AddProperty("text", text);
1091 } 1025 }
1092 } 1026 }
1093 const String& message = String::Handle(String::New(js.ToCString())); 1027 const String& message = String::Handle(String::New(js.ToCString()));
1094 uint8_t data[] = {0, 128, 255}; 1028 uint8_t data[] = {0, 128, 255};
1095 // TODO(koda): Add 'testing' event family. 1029 // TODO(koda): Add 'testing' event family.
1096 SendEvent(kEventFamilyDebug, message, data, sizeof(data)); 1030 SendEvent(kEventFamilyDebug, message, data, sizeof(data));
1097 } 1031 }
1098 1032
1099 1033
1100 static bool HandleIsolateTriggerEchoEvent(Isolate* isolate, JSONStream* js) { 1034 static bool HandleIsolateTriggerEchoEvent(Isolate* isolate, JSONStream* js) {
1101 Service::SendEchoEvent(isolate, js->LookupOption("text")); 1035 Service::SendEchoEvent(isolate, js->LookupParam("text"));
1102 JSONObject jsobj(js); 1036 JSONObject jsobj(js);
1103 return HandleCommonEcho(&jsobj, js); 1037 return HandleCommonEcho(&jsobj, js);
1104 } 1038 }
1105 1039
1106 1040
1107 static bool HandleIsolateEcho(Isolate* isolate, JSONStream* js) { 1041 static bool HandleIsolateEcho(Isolate* isolate, JSONStream* js) {
1108 JSONObject jsobj(js); 1042 JSONObject jsobj(js);
1109 return HandleCommonEcho(&jsobj, js); 1043 return HandleCommonEcho(&jsobj, js);
1110 } 1044 }
1111 1045
1112 1046
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) { 1047 static bool GetIntegerId(const char* s, intptr_t* id, int base = 10) {
1134 if ((s == NULL) || (*s == '\0')) { 1048 if ((s == NULL) || (*s == '\0')) {
1135 // Empty string. 1049 // Empty string.
1136 return false; 1050 return false;
1137 } 1051 }
1138 if (id == NULL) { 1052 if (id == NULL) {
1139 // No id pointer. 1053 // No id pointer.
1140 return false; 1054 return false;
1141 } 1055 }
1142 intptr_t r = 0; 1056 intptr_t r = 0;
(...skipping 530 matching lines...) Expand 10 before | Expand all | Expand 10 after
1673 // references to an object. 1587 // references to an object.
1674 path.SetAt(i * 2, Object::null_object()); 1588 path.SetAt(i * 2, Object::null_object());
1675 } 1589 }
1676 } 1590 }
1677 return true; 1591 return true;
1678 } 1592 }
1679 1593
1680 1594
1681 static bool HandleIsolateGetInboundReferences(Isolate* isolate, 1595 static bool HandleIsolateGetInboundReferences(Isolate* isolate,
1682 JSONStream* js) { 1596 JSONStream* js) {
1683 const char* target_id = js->LookupOption("targetId"); 1597 const char* target_id = js->LookupParam("targetId");
1684 if (target_id == NULL) { 1598 if (target_id == NULL) {
1685 PrintError(js, "Missing 'targetId' option"); 1599 PrintMissingParamError(js, "targetId");
1686 return true; 1600 return true;
1687 } 1601 }
1688 const char* limit_cstr = js->LookupOption("limit"); 1602 const char* limit_cstr = js->LookupParam("limit");
1689 if (target_id == NULL) { 1603 if (target_id == NULL) {
1690 PrintError(js, "Missing 'limit' option"); 1604 PrintMissingParamError(js, "limit");
1691 return true; 1605 return true;
1692 } 1606 }
1693 intptr_t limit; 1607 intptr_t limit;
1694 if (!GetIntegerId(js->LookupOption("limit"), &limit)) { 1608 if (!GetIntegerId(limit_cstr, &limit)) {
1695 PrintError(js, "Invalid 'limit' option: %s", limit_cstr); 1609 PrintInvalidParamError(js, "limit");
1696 return true; 1610 return true;
1697 } 1611 }
1698 1612
1699 Object& obj = Object::Handle(isolate); 1613 Object& obj = Object::Handle(isolate);
1700 ObjectIdRing::LookupResult lookup_result; 1614 ObjectIdRing::LookupResult lookup_result;
1701 { 1615 {
1702 HANDLESCOPE(isolate); 1616 HANDLESCOPE(isolate);
1703 obj = LookupHeapObject(isolate, target_id, &lookup_result); 1617 obj = LookupHeapObject(isolate, target_id, &lookup_result);
1704 } 1618 }
1705 if (obj.raw() == Object::sentinel().raw()) { 1619 if (obj.raw() == Object::sentinel().raw()) {
1706 if (lookup_result == ObjectIdRing::kCollected) { 1620 if (lookup_result == ObjectIdRing::kCollected) {
1707 PrintErrorWithKind( 1621 PrintErrorWithKind(
1708 js, "InboundReferencesCollected", 1622 js, "InboundReferencesCollected",
1709 "attempt to find a retaining path for a collected object\n", 1623 "attempt to find a retaining path for a collected object\n");
1710 js->num_arguments());
1711 return true; 1624 return true;
1712 } else if (lookup_result == ObjectIdRing::kExpired) { 1625 } else if (lookup_result == ObjectIdRing::kExpired) {
1713 PrintErrorWithKind( 1626 PrintErrorWithKind(
1714 js, "InboundReferencesExpired", 1627 js, "InboundReferencesExpired",
1715 "attempt to find a retaining path for an expired object\n", 1628 "attempt to find a retaining path for an expired object\n");
1716 js->num_arguments());
1717 return true; 1629 return true;
1718 } 1630 }
1719 PrintError(js, "Invalid 'targetId' value: no object with id '%s'", 1631 PrintInvalidParamError(js, "targetId");
1720 target_id);
1721 return true; 1632 return true;
1722 } 1633 }
1723 return PrintInboundReferences(isolate, &obj, limit, js); 1634 return PrintInboundReferences(isolate, &obj, limit, js);
1724 } 1635 }
1725 1636
1726 1637
1727 static bool PrintRetainingPath(Isolate* isolate, 1638 static bool PrintRetainingPath(Isolate* isolate,
1728 Object* obj, 1639 Object* obj,
1729 intptr_t limit, 1640 intptr_t limit,
1730 JSONStream* js) { 1641 JSONStream* js) {
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
1774 // after looking for a retaining path. 1685 // after looking for a retaining path.
1775 for (intptr_t i = 0; i < limit; ++i) { 1686 for (intptr_t i = 0; i < limit; ++i) {
1776 path.SetAt(i * 2, Object::null_object()); 1687 path.SetAt(i * 2, Object::null_object());
1777 } 1688 }
1778 1689
1779 return true; 1690 return true;
1780 } 1691 }
1781 1692
1782 static bool HandleIsolateGetRetainingPath(Isolate* isolate, 1693 static bool HandleIsolateGetRetainingPath(Isolate* isolate,
1783 JSONStream* js) { 1694 JSONStream* js) {
1784 const char* target_id = js->LookupOption("targetId"); 1695 const char* target_id = js->LookupParam("targetId");
1785 if (target_id == NULL) { 1696 if (target_id == NULL) {
1786 PrintError(js, "Missing 'targetId' option"); 1697 PrintMissingParamError(js, "targetId");
1787 return true; 1698 return true;
1788 } 1699 }
1789 const char* limit_cstr = js->LookupOption("limit"); 1700 const char* limit_cstr = js->LookupParam("limit");
1790 if (target_id == NULL) { 1701 if (target_id == NULL) {
1791 PrintError(js, "Missing 'limit' option"); 1702 PrintMissingParamError(js, "limit");
1792 return true; 1703 return true;
1793 } 1704 }
1794 intptr_t limit; 1705 intptr_t limit;
1795 if (!GetIntegerId(js->LookupOption("limit"), &limit)) { 1706 if (!GetIntegerId(limit_cstr, &limit)) {
1796 PrintError(js, "Invalid 'limit' option: %s", limit_cstr); 1707 PrintInvalidParamError(js, "limit");
1797 return true; 1708 return true;
1798 } 1709 }
1799 1710
1800 Object& obj = Object::Handle(isolate); 1711 Object& obj = Object::Handle(isolate);
1801 ObjectIdRing::LookupResult lookup_result; 1712 ObjectIdRing::LookupResult lookup_result;
1802 { 1713 {
1803 HANDLESCOPE(isolate); 1714 HANDLESCOPE(isolate);
1804 obj = LookupHeapObject(isolate, target_id, &lookup_result); 1715 obj = LookupHeapObject(isolate, target_id, &lookup_result);
1805 } 1716 }
1806 if (obj.raw() == Object::sentinel().raw()) { 1717 if (obj.raw() == Object::sentinel().raw()) {
1807 if (lookup_result == ObjectIdRing::kCollected) { 1718 if (lookup_result == ObjectIdRing::kCollected) {
1808 PrintErrorWithKind( 1719 PrintErrorWithKind(
1809 js, "RetainingPathCollected", 1720 js, "RetainingPathCollected",
1810 "attempt to find a retaining path for a collected object\n", 1721 "attempt to find a retaining path for a collected object\n");
1811 js->num_arguments());
1812 return true; 1722 return true;
1813 } else if (lookup_result == ObjectIdRing::kExpired) { 1723 } else if (lookup_result == ObjectIdRing::kExpired) {
1814 PrintErrorWithKind( 1724 PrintErrorWithKind(
1815 js, "RetainingPathExpired", 1725 js, "RetainingPathExpired",
1816 "attempt to find a retaining path for an expired object\n", 1726 "attempt to find a retaining path for an expired object\n");
1817 js->num_arguments());
1818 return true; 1727 return true;
1819 } 1728 }
1820 PrintError(js, "Invalid 'targetId' value: no object with id '%s'", 1729 PrintInvalidParamError(js, "targetId");
1821 target_id);
1822 return true; 1730 return true;
1823 } 1731 }
1824 return PrintRetainingPath(isolate, &obj, limit, js); 1732 return PrintRetainingPath(isolate, &obj, limit, js);
1825 } 1733 }
1826 1734
1827 1735
1828 static bool HandleIsolateGetRetainedSize(Isolate* isolate, JSONStream* js) { 1736 static bool HandleIsolateGetRetainedSize(Isolate* isolate, JSONStream* js) {
1829 const char* target_id = js->LookupOption("targetId"); 1737 const char* target_id = js->LookupParam("targetId");
1830 if (target_id == NULL) { 1738 if (target_id == NULL) {
1831 PrintError(js, "Missing 'targetId' option"); 1739 PrintMissingParamError(js, "targetId");
1832 return true; 1740 return true;
1833 } 1741 }
1834 ObjectIdRing::LookupResult lookup_result; 1742 ObjectIdRing::LookupResult lookup_result;
1835 Object& obj = Object::Handle(LookupHeapObject(isolate, target_id, 1743 Object& obj = Object::Handle(LookupHeapObject(isolate, target_id,
1836 &lookup_result)); 1744 &lookup_result));
1837 if (obj.raw() == Object::sentinel().raw()) { 1745 if (obj.raw() == Object::sentinel().raw()) {
1838 if (lookup_result == ObjectIdRing::kCollected) { 1746 if (lookup_result == ObjectIdRing::kCollected) {
1839 PrintErrorWithKind( 1747 PrintErrorWithKind(
1840 js, "RetainedCollected", 1748 js, "RetainedCollected",
1841 "attempt to calculate size retained by a collected object\n", 1749 "attempt to calculate size retained by a collected object\n");
1842 js->num_arguments());
1843 return true; 1750 return true;
1844 } else if (lookup_result == ObjectIdRing::kExpired) { 1751 } else if (lookup_result == ObjectIdRing::kExpired) {
1845 PrintErrorWithKind( 1752 PrintErrorWithKind(
1846 js, "RetainedExpired", 1753 js, "RetainedExpired",
1847 "attempt to calculate size retained by an expired object\n", 1754 "attempt to calculate size retained by an expired object\n");
1848 js->num_arguments());
1849 return true; 1755 return true;
1850 } 1756 }
1851 PrintError(js, "Invalid 'targetId' value: no object with id '%s'", 1757 PrintInvalidParamError(js, "targetId");
1852 target_id);
1853 return true; 1758 return true;
1854 } 1759 }
1855 if (obj.IsClass()) { 1760 if (obj.IsClass()) {
1856 const Class& cls = Class::Cast(obj); 1761 const Class& cls = Class::Cast(obj);
1857 ObjectGraph graph(isolate); 1762 ObjectGraph graph(isolate);
1858 intptr_t retained_size = graph.SizeRetainedByClass(cls.id()); 1763 intptr_t retained_size = graph.SizeRetainedByClass(cls.id());
1859 const Object& result = Object::Handle(Integer::New(retained_size)); 1764 const Object& result = Object::Handle(Integer::New(retained_size));
1860 result.PrintJSON(js, true); 1765 result.PrintJSON(js, true);
1861 return true; 1766 return true;
1862 } 1767 }
1863 if (obj.IsInstance() || obj.IsNull()) { 1768 if (obj.IsInstance() || obj.IsNull()) {
1864 // We don't use Instance::Cast here because it doesn't allow null. 1769 // We don't use Instance::Cast here because it doesn't allow null.
1865 ObjectGraph graph(isolate); 1770 ObjectGraph graph(isolate);
1866 intptr_t retained_size = graph.SizeRetainedByInstance(obj); 1771 intptr_t retained_size = graph.SizeRetainedByInstance(obj);
1867 const Object& result = Object::Handle(Integer::New(retained_size)); 1772 const Object& result = Object::Handle(Integer::New(retained_size));
1868 result.PrintJSON(js, true); 1773 result.PrintJSON(js, true);
1869 return true; 1774 return true;
1870 } 1775 }
1871 PrintError(js, "Invalid 'targetId' value: id '%s' does not correspond to a " 1776 PrintError(js, "%s: Invalid 'targetId' parameter value: "
1872 "library, class, or instance", target_id); 1777 "id '%s' does not correspond to a "
1873 return true; 1778 "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; 1779 return true;
1896 } 1780 }
1897 1781
1898 1782
1899 static bool HandleIsolateEval(Isolate* isolate, JSONStream* js) { 1783 static bool HandleIsolateEval(Isolate* isolate, JSONStream* js) {
1900 const char* target_id = js->LookupOption("targetId"); 1784 const char* target_id = js->LookupParam("targetId");
1901 if (target_id == NULL) { 1785 if (target_id == NULL) {
1902 PrintError(js, "Missing 'targetId' option"); 1786 PrintMissingParamError(js, "targetId");
1903 return true; 1787 return true;
1904 } 1788 }
1905 const char* expr = js->LookupOption("expression"); 1789 const char* expr = js->LookupParam("expression");
1906 if (expr == NULL) { 1790 if (expr == NULL) {
1907 PrintError(js, "Missing 'expression' option"); 1791 PrintMissingParamError(js, "expression");
1908 return true; 1792 return true;
1909 } 1793 }
1910 const String& expr_str = String::Handle(isolate, String::New(expr)); 1794 const String& expr_str = String::Handle(isolate, String::New(expr));
1911 ObjectIdRing::LookupResult lookup_result; 1795 ObjectIdRing::LookupResult lookup_result;
1912 Object& obj = Object::Handle(LookupHeapObject(isolate, target_id, 1796 Object& obj = Object::Handle(LookupHeapObject(isolate, target_id,
1913 &lookup_result)); 1797 &lookup_result));
1914 if (obj.raw() == Object::sentinel().raw()) { 1798 if (obj.raw() == Object::sentinel().raw()) {
1915 if (lookup_result == ObjectIdRing::kCollected) { 1799 if (lookup_result == ObjectIdRing::kCollected) {
1916 PrintSentinel(js, "objects/collected", "<collected>"); 1800 PrintSentinel(js, "objects/collected", "<collected>");
1917 } else if (lookup_result == ObjectIdRing::kExpired) { 1801 } else if (lookup_result == ObjectIdRing::kExpired) {
1918 PrintSentinel(js, "objects/expired", "<expired>"); 1802 PrintSentinel(js, "objects/expired", "<expired>");
1919 } else { 1803 } else {
1920 PrintError(js, "Invalid 'targetId' value: no object with id '%s'", 1804 PrintInvalidParamError(js, "targetId");
1921 target_id);
1922 } 1805 }
1923 return true; 1806 return true;
1924 } 1807 }
1925 if (obj.IsLibrary()) { 1808 if (obj.IsLibrary()) {
1926 const Library& lib = Library::Cast(obj); 1809 const Library& lib = Library::Cast(obj);
1927 const Object& result = Object::Handle(lib.Evaluate(expr_str, 1810 const Object& result = Object::Handle(lib.Evaluate(expr_str,
1928 Array::empty_array(), 1811 Array::empty_array(),
1929 Array::empty_array())); 1812 Array::empty_array()));
1930 result.PrintJSON(js, true); 1813 result.PrintJSON(js, true);
1931 return true; 1814 return true;
(...skipping 11 matching lines...) Expand all
1943 // We don't use Instance::Cast here because it doesn't allow null. 1826 // We don't use Instance::Cast here because it doesn't allow null.
1944 Instance& instance = Instance::Handle(isolate); 1827 Instance& instance = Instance::Handle(isolate);
1945 instance ^= obj.raw(); 1828 instance ^= obj.raw();
1946 const Object& result = 1829 const Object& result =
1947 Object::Handle(instance.Evaluate(expr_str, 1830 Object::Handle(instance.Evaluate(expr_str,
1948 Array::empty_array(), 1831 Array::empty_array(),
1949 Array::empty_array())); 1832 Array::empty_array()));
1950 result.PrintJSON(js, true); 1833 result.PrintJSON(js, true);
1951 return true; 1834 return true;
1952 } 1835 }
1953 PrintError(js, "Invalid 'targetId' value: id '%s' does not correspond to a " 1836 PrintError(js, "%s: Invalid 'targetId' parameter value: "
1954 "library, class, or instance", target_id); 1837 "id '%s' does not correspond to a "
1838 "library, class, or instance", js->method(), target_id);
1955 return true; 1839 return true;
1956 } 1840 }
1957 1841
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 1842
2124 class GetInstancesVisitor : public ObjectGraph::Visitor { 1843 class GetInstancesVisitor : public ObjectGraph::Visitor {
2125 public: 1844 public:
2126 GetInstancesVisitor(const Class& cls, const Array& storage) 1845 GetInstancesVisitor(const Class& cls, const Array& storage)
2127 : cls_(cls), storage_(storage), count_(0) {} 1846 : cls_(cls), storage_(storage), count_(0) {}
2128 1847
2129 virtual Direction VisitObject(ObjectGraph::StackIterator* it) { 1848 virtual Direction VisitObject(ObjectGraph::StackIterator* it) {
2130 RawObject* raw_obj = it->Get(); 1849 RawObject* raw_obj = it->Get();
2131 if (raw_obj->IsFreeListElement()) { 1850 if (raw_obj->IsFreeListElement()) {
2132 return kProceed; 1851 return kProceed;
(...skipping 14 matching lines...) Expand all
2147 intptr_t count() const { return count_; } 1866 intptr_t count() const { return count_; }
2148 1867
2149 private: 1868 private:
2150 const Class& cls_; 1869 const Class& cls_;
2151 const Array& storage_; 1870 const Array& storage_;
2152 intptr_t count_; 1871 intptr_t count_;
2153 }; 1872 };
2154 1873
2155 1874
2156 static bool HandleIsolateGetInstances(Isolate* isolate, JSONStream* js) { 1875 static bool HandleIsolateGetInstances(Isolate* isolate, JSONStream* js) {
2157 const char* target_id = js->LookupOption("classId"); 1876 const char* target_id = js->LookupParam("classId");
2158 if (target_id == NULL) { 1877 if (target_id == NULL) {
2159 PrintError(js, "Missing 'classId' option"); 1878 PrintMissingParamError(js, "classId");
2160 return true; 1879 return true;
2161 } 1880 }
2162 const char* limit_cstr = js->LookupOption("limit"); 1881 const char* limit_cstr = js->LookupParam("limit");
2163 if (target_id == NULL) { 1882 if (target_id == NULL) {
2164 PrintError(js, "Missing 'limit' option"); 1883 PrintMissingParamError(js, "limit");
2165 return true; 1884 return true;
2166 } 1885 }
2167 intptr_t limit; 1886 intptr_t limit;
2168 if (!GetIntegerId(js->LookupOption("limit"), &limit)) { 1887 if (!GetIntegerId(limit_cstr, &limit)) {
2169 PrintError(js, "Invalid 'limit' option: %s", limit_cstr); 1888 PrintInvalidParamError(js, "limit");
2170 return true; 1889 return true;
2171 } 1890 }
2172 const Object& obj = 1891 const Object& obj =
2173 Object::Handle(LookupHeapObject(isolate, target_id, NULL)); 1892 Object::Handle(LookupHeapObject(isolate, target_id, NULL));
2174 if (obj.raw() == Object::sentinel().raw() || 1893 if (obj.raw() == Object::sentinel().raw() ||
2175 !obj.IsClass()) { 1894 !obj.IsClass()) {
2176 PrintError(js, "Invalid 'classId' value: no class with id '%s'", target_id); 1895 PrintInvalidParamError(js, "classId");
2177 return true; 1896 return true;
2178 } 1897 }
2179 const Class& cls = Class::Cast(obj); 1898 const Class& cls = Class::Cast(obj);
2180 Array& storage = Array::Handle(Array::New(limit)); 1899 Array& storage = Array::Handle(Array::New(limit));
2181 GetInstancesVisitor visitor(cls, storage); 1900 GetInstancesVisitor visitor(cls, storage);
2182 ObjectGraph graph(isolate); 1901 ObjectGraph graph(isolate);
2183 graph.IterateObjects(&visitor); 1902 graph.IterateObjects(&visitor);
2184 intptr_t count = visitor.count(); 1903 intptr_t count = visitor.count();
2185 if (count < limit) { 1904 if (count < limit) {
2186 // Truncate the list using utility method for GrowableObjectArray. 1905 // Truncate the list using utility method for GrowableObjectArray.
2187 GrowableObjectArray& wrapper = GrowableObjectArray::Handle( 1906 GrowableObjectArray& wrapper = GrowableObjectArray::Handle(
2188 GrowableObjectArray::New(storage)); 1907 GrowableObjectArray::New(storage));
2189 wrapper.SetLength(count); 1908 wrapper.SetLength(count);
2190 storage = Array::MakeArray(wrapper); 1909 storage = Array::MakeArray(wrapper);
2191 } 1910 }
2192 JSONObject jsobj(js); 1911 JSONObject jsobj(js);
2193 jsobj.AddProperty("type", "InstanceSet"); 1912 jsobj.AddProperty("type", "InstanceSet");
2194 jsobj.AddProperty("id", "instance_set"); 1913 jsobj.AddProperty("id", "instance_set");
2195 jsobj.AddProperty("totalCount", count); 1914 jsobj.AddProperty("totalCount", count);
2196 jsobj.AddProperty("sampleCount", storage.Length()); 1915 jsobj.AddProperty("sampleCount", storage.Length());
2197 jsobj.AddProperty("sample", storage); 1916 jsobj.AddProperty("sample", storage);
2198 return true; 1917 return true;
2199 } 1918 }
2200 1919
2201 1920
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) { 1921 static bool HandleIsolateGetCoverage(Isolate* isolate, JSONStream* js) {
2247 if (!js->HasOption("targetId")) { 1922 if (!js->HasParam("targetId")) {
2248 CodeCoverage::PrintJSON(isolate, js, NULL); 1923 CodeCoverage::PrintJSON(isolate, js, NULL);
2249 return true; 1924 return true;
2250 } 1925 }
2251 const char* target_id = js->LookupOption("targetId"); 1926 const char* target_id = js->LookupParam("targetId");
2252 Object& obj = Object::Handle(LookupHeapObject(isolate, target_id, NULL)); 1927 Object& obj = Object::Handle(LookupHeapObject(isolate, target_id, NULL));
2253 if (obj.raw() == Object::sentinel().raw()) { 1928 if (obj.raw() == Object::sentinel().raw()) {
2254 PrintError(js, "Invalid 'targetId' value: no object with id '%s'", 1929 PrintInvalidParamError(js, "targetId");
2255 target_id);
2256 return true; 1930 return true;
2257 } 1931 }
2258 if (obj.IsScript()) { 1932 if (obj.IsScript()) {
2259 ScriptCoverageFilter sf(Script::Cast(obj)); 1933 ScriptCoverageFilter sf(Script::Cast(obj));
2260 CodeCoverage::PrintJSON(isolate, js, &sf); 1934 CodeCoverage::PrintJSON(isolate, js, &sf);
2261 return true; 1935 return true;
2262 } 1936 }
2263 if (obj.IsLibrary()) { 1937 if (obj.IsLibrary()) {
2264 LibraryCoverageFilter lf(Library::Cast(obj)); 1938 LibraryCoverageFilter lf(Library::Cast(obj));
2265 CodeCoverage::PrintJSON(isolate, js, &lf); 1939 CodeCoverage::PrintJSON(isolate, js, &lf);
2266 return true; 1940 return true;
2267 } 1941 }
2268 if (obj.IsClass()) { 1942 if (obj.IsClass()) {
2269 ClassCoverageFilter cf(Class::Cast(obj)); 1943 ClassCoverageFilter cf(Class::Cast(obj));
2270 CodeCoverage::PrintJSON(isolate, js, &cf); 1944 CodeCoverage::PrintJSON(isolate, js, &cf);
2271 return true; 1945 return true;
2272 } 1946 }
2273 if (obj.IsFunction()) { 1947 if (obj.IsFunction()) {
2274 FunctionCoverageFilter ff(Function::Cast(obj)); 1948 FunctionCoverageFilter ff(Function::Cast(obj));
2275 CodeCoverage::PrintJSON(isolate, js, &ff); 1949 CodeCoverage::PrintJSON(isolate, js, &ff);
2276 return true; 1950 return true;
2277 } 1951 }
2278 PrintError(js, "Invalid 'targetId' value: id '%s' does not correspond to a " 1952 PrintError(js, "%s: Invalid 'targetId' parameter value: "
2279 "script, library, class, or function", target_id); 1953 "id '%s' does not correspond to a "
1954 "script, library, class, or function", js->method(), target_id);
2280 return true; 1955 return true;
2281 } 1956 }
2282 1957
2283 1958
2284 static bool HandleIsolateAddBreakpoint(Isolate* isolate, JSONStream* js) { 1959 static bool HandleIsolateAddBreakpoint(Isolate* isolate, JSONStream* js) {
2285 if (!js->HasOption("line")) { 1960 if (!js->HasParam("line")) {
2286 PrintError(js, "Missing 'line' option"); 1961 PrintMissingParamError(js, "line");
2287 return true; 1962 return true;
2288 } 1963 }
2289 const char* line_option = js->LookupOption("line"); 1964 const char* line_param = js->LookupParam("line");
2290 intptr_t line = -1; 1965 intptr_t line = -1;
2291 if (!GetIntegerId(line_option, &line)) { 1966 if (!GetIntegerId(line_param, &line)) {
2292 PrintError(js, "Invalid 'line' value: %s is not an integer", line_option); 1967 PrintInvalidParamError(js, "line");
2293 return true; 1968 return true;
2294 } 1969 }
2295 const char* script_id = js->LookupOption("script"); 1970 const char* script_id = js->LookupParam("script");
2296 Object& obj = Object::Handle(LookupHeapObject(isolate, script_id, NULL)); 1971 Object& obj = Object::Handle(LookupHeapObject(isolate, script_id, NULL));
2297 if (obj.raw() == Object::sentinel().raw() || !obj.IsScript()) { 1972 if (obj.raw() == Object::sentinel().raw() || !obj.IsScript()) {
2298 PrintError(js, "Invalid 'script' value: no script with id '%s'", script_id); 1973 PrintInvalidParamError(js, "script");
2299 return true; 1974 return true;
2300 } 1975 }
2301 const Script& script = Script::Cast(obj); 1976 const Script& script = Script::Cast(obj);
2302 const String& script_url = String::Handle(script.url()); 1977 const String& script_url = String::Handle(script.url());
2303 SourceBreakpoint* bpt = 1978 SourceBreakpoint* bpt =
2304 isolate->debugger()->SetBreakpointAtLine(script_url, line); 1979 isolate->debugger()->SetBreakpointAtLine(script_url, line);
2305 if (bpt == NULL) { 1980 if (bpt == NULL) {
2306 PrintError(js, "Unable to set breakpoint at line %s", line_option); 1981 PrintError(js, "Unable to set breakpoint at line %s", line_param);
2307 return true; 1982 return true;
2308 } 1983 }
2309 bpt->PrintJSON(js); 1984 bpt->PrintJSON(js);
2310 return true; 1985 return true;
2311 } 1986 }
2312 1987
2313 1988
2314 static bool HandleIsolateRemoveBreakpoint(Isolate* isolate, JSONStream* js) { 1989 static bool HandleIsolateRemoveBreakpoint(Isolate* isolate, JSONStream* js) {
2315 if (!js->HasOption("breakpointId")) { 1990 if (!js->HasParam("breakpointId")) {
2316 PrintError(js, "Missing 'breakpointId' option"); 1991 PrintMissingParamError(js, "breakpointId");
2317 return true; 1992 return true;
2318 } 1993 }
2319 const char* bpt_id = js->LookupOption("breakpointId"); 1994 const char* bpt_id = js->LookupParam("breakpointId");
2320 SourceBreakpoint* bpt = LookupBreakpoint(isolate, bpt_id); 1995 SourceBreakpoint* bpt = LookupBreakpoint(isolate, bpt_id);
2321 if (bpt == NULL) { 1996 if (bpt == NULL) {
2322 fprintf(stderr, "ERROR1"); 1997 fprintf(stderr, "ERROR1");
2323 PrintError(js, "Invalid 'breakpointId' value: no breakpoint with id '%s'", 1998 PrintInvalidParamError(js, "breakpointId");
2324 bpt_id);
2325 return true; 1999 return true;
2326 } 2000 }
2327 isolate->debugger()->RemoveBreakpoint(bpt->id()); 2001 isolate->debugger()->RemoveBreakpoint(bpt->id());
2328 2002
2329 fprintf(stderr, "SUCCESS"); 2003 fprintf(stderr, "SUCCESS");
2330 // TODO(turnidge): Consider whether the 'Success' type is proper. 2004 // TODO(turnidge): Consider whether the 'Success' type is proper.
2331 JSONObject jsobj(js); 2005 JSONObject jsobj(js);
2332 jsobj.AddProperty("type", "Success"); 2006 jsobj.AddProperty("type", "Success");
2333 jsobj.AddProperty("id", ""); 2007 jsobj.AddProperty("id", "");
2334 return true; 2008 return true;
2335 } 2009 }
2336 2010
2337 2011
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) { 2012 static RawClass* GetMetricsClass(Isolate* isolate) {
2408 const Library& prof_lib = 2013 const Library& prof_lib =
2409 Library::Handle(isolate, Library::ProfilerLibrary()); 2014 Library::Handle(isolate, Library::ProfilerLibrary());
2410 ASSERT(!prof_lib.IsNull()); 2015 ASSERT(!prof_lib.IsNull());
2411 const String& metrics_cls_name = 2016 const String& metrics_cls_name =
2412 String::Handle(isolate, String::New("Metrics")); 2017 String::Handle(isolate, String::New("Metrics"));
2413 ASSERT(!metrics_cls_name.IsNull()); 2018 ASSERT(!metrics_cls_name.IsNull());
2414 const Class& metrics_cls = 2019 const Class& metrics_cls =
2415 Class::Handle(isolate, prof_lib.LookupClass(metrics_cls_name)); 2020 Class::Handle(isolate, prof_lib.LookupClass(metrics_cls_name));
2416 ASSERT(!metrics_cls.IsNull()); 2021 ASSERT(!metrics_cls.IsNull());
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
2493 buffer->AddString(String::Cast(result).ToCString()); 2098 buffer->AddString(String::Cast(result).ToCString());
2494 return true; 2099 return true;
2495 } 2100 }
2496 PrintError(js, "Dart Metric %s not found\n", id); 2101 PrintError(js, "Dart Metric %s not found\n", id);
2497 return true; 2102 return true;
2498 } 2103 }
2499 2104
2500 2105
2501 static bool HandleIsolateGetMetricList(Isolate* isolate, JSONStream* js) { 2106 static bool HandleIsolateGetMetricList(Isolate* isolate, JSONStream* js) {
2502 bool native_metrics = false; 2107 bool native_metrics = false;
2503 if (js->HasOption("type")) { 2108 if (js->HasParam("type")) {
2504 if (js->OptionIs("type", "Native")) { 2109 if (js->ParamIs("type", "Native")) {
2505 native_metrics = true; 2110 native_metrics = true;
2506 } else if (js->OptionIs("type", "Dart")) { 2111 } else if (js->ParamIs("type", "Dart")) {
2507 native_metrics = false; 2112 native_metrics = false;
2508 } else { 2113 } else {
2509 PrintError(js, "Invalid 'type' option value: %s\n", 2114 PrintInvalidParamError(js, "type");
2510 js->LookupOption("type"));
2511 return true; 2115 return true;
2512 } 2116 }
2513 } else { 2117 } else {
2514 PrintError(js, "Expected 'type' option."); 2118 PrintMissingParamError(js, "type");
2515 return true; 2119 return true;
2516 } 2120 }
2517 if (native_metrics) { 2121 if (native_metrics) {
2518 return HandleNativeMetricsList(isolate, js); 2122 return HandleNativeMetricsList(isolate, js);
2519 } 2123 }
2520 return HandleDartMetricsList(isolate, js); 2124 return HandleDartMetricsList(isolate, js);
2521 } 2125 }
2522 2126
2523 2127
2524 static bool HandleIsolateGetMetric(Isolate* isolate, JSONStream* js) { 2128 static bool HandleIsolateGetMetric(Isolate* isolate, JSONStream* js) {
2525 const char* metric_id = js->LookupOption("metricId"); 2129 const char* metric_id = js->LookupParam("metricId");
2526 if (metric_id == NULL) { 2130 if (metric_id == NULL) {
2527 PrintError(js, "Expected 'metricId' option."); 2131 PrintMissingParamError(js, "metricId");
2528 return true; 2132 return true;
2529 } 2133 }
2530 // Verify id begins with "metrics/". 2134 // Verify id begins with "metrics/".
2531 static const char* kMetricIdPrefix = "metrics/"; 2135 static const char* kMetricIdPrefix = "metrics/";
2532 static intptr_t kMetricIdPrefixLen = strlen(kMetricIdPrefix); 2136 static intptr_t kMetricIdPrefixLen = strlen(kMetricIdPrefix);
2533 if (strncmp(metric_id, kMetricIdPrefix, kMetricIdPrefixLen) != 0) { 2137 if (strncmp(metric_id, kMetricIdPrefix, kMetricIdPrefixLen) != 0) {
2534 PrintError(js, "Metric %s not found\n", metric_id); 2138 PrintError(js, "Metric %s not found\n", metric_id);
2535 } 2139 }
2536 // Check if id begins with "metrics/native/". 2140 // Check if id begins with "metrics/native/".
2537 static const char* kNativeMetricIdPrefix = "metrics/native/"; 2141 static const char* kNativeMetricIdPrefix = "metrics/native/";
2538 static intptr_t kNativeMetricIdPrefixLen = strlen(kNativeMetricIdPrefix); 2142 static intptr_t kNativeMetricIdPrefixLen = strlen(kNativeMetricIdPrefix);
2539 const bool native_metric = 2143 const bool native_metric =
2540 strncmp(metric_id, kNativeMetricIdPrefix, kNativeMetricIdPrefixLen) == 0; 2144 strncmp(metric_id, kNativeMetricIdPrefix, kNativeMetricIdPrefixLen) == 0;
2541 if (native_metric) { 2145 if (native_metric) {
2542 const char* id = metric_id + kNativeMetricIdPrefixLen; 2146 const char* id = metric_id + kNativeMetricIdPrefixLen;
2543 return HandleNativeMetric(isolate, js, id); 2147 return HandleNativeMetric(isolate, js, id);
2544 } 2148 }
2545 const char* id = metric_id + kMetricIdPrefixLen; 2149 const char* id = metric_id + kMetricIdPrefixLen;
2546 return HandleDartMetric(isolate, js, id); 2150 return HandleDartMetric(isolate, js, id);
2547 } 2151 }
2548 2152
2549 2153
2550 static bool HandleVMGetMetricList(JSONStream* js) { 2154 static bool HandleVMGetMetricList(JSONStream* js) {
2551 return false; 2155 return false;
2552 } 2156 }
2553 2157
2554 2158
2555 static bool HandleVMGetMetric(JSONStream* js) { 2159 static bool HandleVMGetMetric(JSONStream* js) {
2556 const char* metric_id = js->LookupOption("metricId"); 2160 const char* metric_id = js->LookupParam("metricId");
2557 if (metric_id == NULL) { 2161 if (metric_id == NULL) {
2558 PrintError(js, "Expected 'metricId' option."); 2162 PrintMissingParamError(js, "metricId");
2559 } 2163 }
2560 return false; 2164 return false;
2561 } 2165 }
2562 2166
2563 2167
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) { 2168 static bool HandleIsolateResume(Isolate* isolate, JSONStream* js) {
2663 const char* step_option = js->LookupOption("step"); 2169 const char* step_param = js->LookupParam("step");
2664 if (isolate->message_handler()->paused_on_start()) { 2170 if (isolate->message_handler()->paused_on_start()) {
2665 isolate->message_handler()->set_pause_on_start(false); 2171 isolate->message_handler()->set_pause_on_start(false);
2666 JSONObject jsobj(js); 2172 JSONObject jsobj(js);
2667 jsobj.AddProperty("type", "Success"); 2173 jsobj.AddProperty("type", "Success");
2668 jsobj.AddProperty("id", ""); 2174 jsobj.AddProperty("id", "");
2669 return true; 2175 return true;
2670 } 2176 }
2671 if (isolate->message_handler()->paused_on_exit()) { 2177 if (isolate->message_handler()->paused_on_exit()) {
2672 isolate->message_handler()->set_pause_on_exit(false); 2178 isolate->message_handler()->set_pause_on_exit(false);
2673 JSONObject jsobj(js); 2179 JSONObject jsobj(js);
2674 jsobj.AddProperty("type", "Success"); 2180 jsobj.AddProperty("type", "Success");
2675 jsobj.AddProperty("id", ""); 2181 jsobj.AddProperty("id", "");
2676 return true; 2182 return true;
2677 } 2183 }
2678 if (isolate->debugger()->PauseEvent() != NULL) { 2184 if (isolate->debugger()->PauseEvent() != NULL) {
2679 if (step_option != NULL) { 2185 if (step_param != NULL) {
2680 if (strcmp(step_option, "into") == 0) { 2186 if (strcmp(step_param, "into") == 0) {
2681 isolate->debugger()->SetSingleStep(); 2187 isolate->debugger()->SetSingleStep();
2682 } else if (strcmp(step_option, "over") == 0) { 2188 } else if (strcmp(step_param, "over") == 0) {
2683 isolate->debugger()->SetStepOver(); 2189 isolate->debugger()->SetStepOver();
2684 } else if (strcmp(step_option, "out") == 0) { 2190 } else if (strcmp(step_param, "out") == 0) {
2685 isolate->debugger()->SetStepOut(); 2191 isolate->debugger()->SetStepOut();
2686 } else { 2192 } else {
2687 PrintError(js, "Invalid 'step' option: %s", step_option); 2193 PrintInvalidParamError(js, "step");
2688 return true; 2194 return true;
2689 } 2195 }
2690 } 2196 }
2691 isolate->Resume(); 2197 isolate->Resume();
2692 JSONObject jsobj(js); 2198 JSONObject jsobj(js);
2693 jsobj.AddProperty("type", "Success"); 2199 jsobj.AddProperty("type", "Success");
2694 jsobj.AddProperty("id", ""); 2200 jsobj.AddProperty("id", "");
2695 return true; 2201 return true;
2696 } 2202 }
2697 2203
(...skipping 14 matching lines...) Expand all
2712 static bool HandleIsolatePause(Isolate* isolate, JSONStream* js) { 2218 static bool HandleIsolatePause(Isolate* isolate, JSONStream* js) {
2713 // TODO(turnidge): Don't double-interrupt the isolate here. 2219 // TODO(turnidge): Don't double-interrupt the isolate here.
2714 isolate->ScheduleInterrupts(Isolate::kApiInterrupt); 2220 isolate->ScheduleInterrupts(Isolate::kApiInterrupt);
2715 JSONObject jsobj(js); 2221 JSONObject jsobj(js);
2716 jsobj.AddProperty("type", "Success"); 2222 jsobj.AddProperty("type", "Success");
2717 jsobj.AddProperty("id", ""); 2223 jsobj.AddProperty("id", "");
2718 return true; 2224 return true;
2719 } 2225 }
2720 2226
2721 2227
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) { 2228 static bool HandleIsolateGetTagProfile(Isolate* isolate, JSONStream* js) {
2786 JSONObject miniProfile(js); 2229 JSONObject miniProfile(js);
2787 miniProfile.AddProperty("type", "TagProfile"); 2230 miniProfile.AddProperty("type", "TagProfile");
2788 miniProfile.AddProperty("id", "profile/tag"); 2231 miniProfile.AddProperty("id", "profile/tag");
2789 isolate->vm_tag_counters()->PrintToJSONObject(&miniProfile); 2232 isolate->vm_tag_counters()->PrintToJSONObject(&miniProfile);
2790 return true; 2233 return true;
2791 } 2234 }
2792 2235
2793 static bool HandleIsolateGetCpuProfile(Isolate* isolate, JSONStream* js) { 2236 static bool HandleIsolateGetCpuProfile(Isolate* isolate, JSONStream* js) {
2794 // A full profile includes disassembly of all Dart code objects. 2237 // A full profile includes disassembly of all Dart code objects.
2795 // TODO(johnmccutchan): Add sub command to trigger full code dump. 2238 // TODO(johnmccutchan): Add option to trigger full code dump.
2796 bool full_profile = false; 2239 bool full_profile = false;
2797 const char* tags_option = js->LookupOption("tags");
2798 Profiler::TagOrder tag_order = Profiler::kUserVM; 2240 Profiler::TagOrder tag_order = Profiler::kUserVM;
2799 if (js->HasOption("tags")) { 2241 if (js->HasParam("tags")) {
2800 if (js->OptionIs("tags", "None")) { 2242 if (js->ParamIs("tags", "None")) {
2801 tag_order = Profiler::kNoTags; 2243 tag_order = Profiler::kNoTags;
2802 } else if (js->OptionIs("tags", "UserVM")) { 2244 } else if (js->ParamIs("tags", "UserVM")) {
2803 tag_order = Profiler::kUserVM; 2245 tag_order = Profiler::kUserVM;
2804 } else if (js->OptionIs("tags", "UserOnly")) { 2246 } else if (js->ParamIs("tags", "UserOnly")) {
2805 tag_order = Profiler::kUser; 2247 tag_order = Profiler::kUser;
2806 } else if (js->OptionIs("tags", "VMUser")) { 2248 } else if (js->ParamIs("tags", "VMUser")) {
2807 tag_order = Profiler::kVMUser; 2249 tag_order = Profiler::kVMUser;
2808 } else if (js->OptionIs("tags", "VMOnly")) { 2250 } else if (js->ParamIs("tags", "VMOnly")) {
2809 tag_order = Profiler::kVM; 2251 tag_order = Profiler::kVM;
2810 } else { 2252 } else {
2811 PrintError(js, "Invalid tags option value: %s\n", tags_option); 2253 PrintInvalidParamError(js, "tags");
2812 return true; 2254 return true;
2813 } 2255 }
2814 } 2256 }
2815 Profiler::PrintJSON(isolate, js, full_profile, tag_order); 2257 Profiler::PrintJSON(isolate, js, full_profile, tag_order);
2816 return true; 2258 return true;
2817 } 2259 }
2818 2260
2819 2261
2820 static bool HandleIsolateGetAllocationProfile(Isolate* isolate, 2262 static bool HandleIsolateGetAllocationProfile(Isolate* isolate,
2821 JSONStream* js) { 2263 JSONStream* js) {
2822 bool should_reset_accumulator = false; 2264 bool should_reset_accumulator = false;
2823 bool should_collect = false; 2265 bool should_collect = false;
2824 if (js->HasOption("reset")) { 2266 if (js->HasParam("reset")) {
2825 if (js->OptionIs("reset", "true")) { 2267 if (js->ParamIs("reset", "true")) {
2826 should_reset_accumulator = true; 2268 should_reset_accumulator = true;
2827 } else { 2269 } else {
2828 PrintError(js, "Unrecognized reset option '%s'", 2270 PrintInvalidParamError(js, "reset");
2829 js->LookupOption("reset"));
2830 return true; 2271 return true;
2831 } 2272 }
2832 } 2273 }
2833 if (js->HasOption("gc")) { 2274 if (js->HasParam("gc")) {
2834 if (js->OptionIs("gc", "full")) { 2275 if (js->ParamIs("gc", "full")) {
2835 should_collect = true; 2276 should_collect = true;
2836 } else { 2277 } else {
2837 PrintError(js, "Unrecognized gc option '%s'", js->LookupOption("gc")); 2278 PrintInvalidParamError(js, "gc");
2838 return true; 2279 return true;
2839 } 2280 }
2840 } 2281 }
2841 if (should_reset_accumulator) { 2282 if (should_reset_accumulator) {
2842 isolate->UpdateLastAllocationProfileAccumulatorResetTimestamp(); 2283 isolate->UpdateLastAllocationProfileAccumulatorResetTimestamp();
2843 isolate->class_table()->ResetAllocationAccumulators(); 2284 isolate->class_table()->ResetAllocationAccumulators();
2844 } 2285 }
2845 if (should_collect) { 2286 if (should_collect) {
2846 isolate->UpdateLastAllocationProfileGCTimestamp(); 2287 isolate->UpdateLastAllocationProfileGCTimestamp();
2847 isolate->heap()->CollectAllGarbage(); 2288 isolate->heap()->CollectAllGarbage();
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
2900 } 2341 }
2901 uword obj_begin = RawObject::ToAddr(obj); 2342 uword obj_begin = RawObject::ToAddr(obj);
2902 uword obj_end = obj_begin + obj->Size(); 2343 uword obj_end = obj_begin + obj->Size();
2903 return obj_begin <= addr_ && addr_ < obj_end; 2344 return obj_begin <= addr_ && addr_ < obj_end;
2904 } 2345 }
2905 private: 2346 private:
2906 uword addr_; 2347 uword addr_;
2907 }; 2348 };
2908 2349
2909 2350
2910 static bool HandleAddress(Isolate* isolate, JSONStream* js) { 2351 static bool HandleIsolateGetObjectByAddress(Isolate* isolate, JSONStream* js) {
2911 uword addr = 0; 2352 const char* addr_str = js->LookupParam("address");
2912 if (js->num_arguments() != 2 || 2353 if (addr_str == NULL) {
2913 !GetUnsignedIntegerId(js->GetArgument(1), &addr, 16)) { 2354 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; 2355 return true;
2917 } 2356 }
2918 bool ref = js->HasOption("ref") && js->OptionIs("ref", "true"); 2357
2358 // Handle heap objects.
2359 uword addr = 0;
2360 if (!GetUnsignedIntegerId(addr_str, &addr, 16)) {
2361 PrintInvalidParamError(js, "address");
2362 return true;
2363 }
2364 bool ref = js->HasParam("ref") && js->ParamIs("ref", "true");
2919 Object& object = Object::Handle(isolate); 2365 Object& object = Object::Handle(isolate);
2920 { 2366 {
2921 NoGCScope no_gc; 2367 NoGCScope no_gc;
2922 ContainsAddressVisitor visitor(isolate, addr); 2368 ContainsAddressVisitor visitor(isolate, addr);
2923 object = isolate->heap()->FindObject(&visitor); 2369 object = isolate->heap()->FindObject(&visitor);
2924 } 2370 }
2925 object.PrintJSON(js, ref); 2371 object.PrintJSON(js, ref);
2926 return true; 2372 return true;
2927 } 2373 }
2928 2374
(...skipping 13 matching lines...) Expand all
2942 2388
2943 2389
2944 static bool HandleIsolateRespondWithMalformedObject(Isolate* isolate, 2390 static bool HandleIsolateRespondWithMalformedObject(Isolate* isolate,
2945 JSONStream* js) { 2391 JSONStream* js) {
2946 JSONObject jsobj(js); 2392 JSONObject jsobj(js);
2947 jsobj.AddProperty("bart", "simpson"); 2393 jsobj.AddProperty("bart", "simpson");
2948 return true; 2394 return true;
2949 } 2395 }
2950 2396
2951 2397
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) { 2398 static bool HandleIsolateGetObject(Isolate* isolate, JSONStream* js) {
2980 const char* id = js->LookupOption("objectId"); 2399 const char* id = js->LookupParam("objectId");
2981 if (id == NULL) { 2400 if (id == NULL) {
2982 // TODO(turnidge): Print the isolate here instead. 2401 PrintMissingParamError(js, "objectId");
2983 PrintError(js, "GetObject expects an 'objectId' parameter\n",
2984 js->num_arguments());
2985 return true; 2402 return true;
2986 } 2403 }
2987 2404
2988 // Handle heap objects. 2405 // Handle heap objects.
2989 ObjectIdRing::LookupResult lookup_result; 2406 ObjectIdRing::LookupResult lookup_result;
2990 const Object& obj = 2407 const Object& obj =
2991 Object::Handle(LookupHeapObject(isolate, id, &lookup_result)); 2408 Object::Handle(LookupHeapObject(isolate, id, &lookup_result));
2992 if (obj.raw() != Object::sentinel().raw()) { 2409 if (obj.raw() != Object::sentinel().raw()) {
2993 // We found a heap object for this id. Return it. 2410 // We found a heap object for this id. Return it.
2994 obj.PrintJSON(js, false); 2411 obj.PrintJSON(js, false);
2995 return true; 2412 return true;
2996 } else if (lookup_result == ObjectIdRing::kCollected) { 2413 } else if (lookup_result == ObjectIdRing::kCollected) {
2997 PrintSentinel(js, "objects/collected", "<collected>"); 2414 PrintSentinel(js, "objects/collected", "<collected>");
2415 return true;
2998 } else if (lookup_result == ObjectIdRing::kExpired) { 2416 } else if (lookup_result == ObjectIdRing::kExpired) {
2999 PrintSentinel(js, "objects/expired", "<expired>"); 2417 PrintSentinel(js, "objects/expired", "<expired>");
2418 return true;
3000 } 2419 }
3001 2420
3002 // Handle non-heap objects. 2421 // Handle non-heap objects.
3003 SourceBreakpoint* bpt = LookupBreakpoint(isolate, id); 2422 SourceBreakpoint* bpt = LookupBreakpoint(isolate, id);
3004 if (bpt != NULL) { 2423 if (bpt != NULL) {
3005 bpt->PrintJSON(js); 2424 bpt->PrintJSON(js);
3006 return true; 2425 return true;
3007 } 2426 }
3008 2427
3009 PrintError(js, "Unrecognized object id: %s\n", id); 2428 PrintError(js, "Unrecognized object id: %s\n", id);
3010 return true; 2429 return true;
3011 } 2430 }
3012 2431
3013 2432
3014 static bool HandleIsolateGetClassList(Isolate* isolate, JSONStream* js) { 2433 static bool HandleIsolateGetClassList(Isolate* isolate, JSONStream* js) {
3015 ClassTable* table = isolate->class_table(); 2434 ClassTable* table = isolate->class_table();
3016 JSONObject jsobj(js); 2435 JSONObject jsobj(js);
3017 table->PrintToJSONObject(&jsobj); 2436 table->PrintToJSONObject(&jsobj);
3018 return true; 2437 return true;
3019 } 2438 }
3020 2439
3021 2440
3022 static bool HandleIsolateGetTypeArgumentsList(Isolate* isolate, 2441 static bool HandleIsolateGetTypeArgumentsList(Isolate* isolate,
3023 JSONStream* js) { 2442 JSONStream* js) {
3024 bool only_with_instantiations = false; 2443 bool only_with_instantiations = false;
3025 if (js->OptionIs("onlyWithInstantiations", "true")) { 2444 if (js->ParamIs("onlyWithInstantiations", "true")) {
3026 only_with_instantiations = true; 2445 only_with_instantiations = true;
3027 } 2446 }
3028 ObjectStore* object_store = isolate->object_store(); 2447 ObjectStore* object_store = isolate->object_store();
3029 const Array& table = Array::Handle(object_store->canonical_type_arguments()); 2448 const Array& table = Array::Handle(object_store->canonical_type_arguments());
3030 ASSERT(table.Length() > 0); 2449 ASSERT(table.Length() > 0);
3031 TypeArguments& type_args = TypeArguments::Handle(); 2450 TypeArguments& type_args = TypeArguments::Handle();
3032 const intptr_t table_size = table.Length() - 1; 2451 const intptr_t table_size = table.Length() - 1;
3033 const intptr_t table_used = Smi::Value(Smi::RawCast(table.At(table_size))); 2452 const intptr_t table_used = Smi::Value(Smi::RawCast(table.At(table_size)));
3034 JSONObject jsobj(js); 2453 JSONObject jsobj(js);
3035 jsobj.AddProperty("type", "TypeArgumentsList"); 2454 jsobj.AddProperty("type", "TypeArgumentsList");
3036 jsobj.AddProperty("canonicalTypeArgumentsTableSize", table_size); 2455 jsobj.AddProperty("canonicalTypeArgumentsTableSize", table_size);
3037 jsobj.AddProperty("canonicalTypeArgumentsTableUsed", table_used); 2456 jsobj.AddProperty("canonicalTypeArgumentsTableUsed", table_used);
3038 JSONArray members(&jsobj, "typeArguments"); 2457 JSONArray members(&jsobj, "typeArguments");
3039 for (intptr_t i = 0; i < table_size; i++) { 2458 for (intptr_t i = 0; i < table_size; i++) {
3040 type_args ^= table.At(i); 2459 type_args ^= table.At(i);
3041 if (!type_args.IsNull()) { 2460 if (!type_args.IsNull()) {
3042 if (!only_with_instantiations || type_args.HasInstantiations()) { 2461 if (!only_with_instantiations || type_args.HasInstantiations()) {
3043 members.AddValue(type_args); 2462 members.AddValue(type_args);
3044 } 2463 }
3045 } 2464 }
3046 } 2465 }
3047 return true; 2466 return true;
3048 } 2467 }
3049 2468
3050 2469
3051 static IsolateMessageHandlerEntry isolate_handlers_new[] = { 2470 static IsolateMessageHandlerEntry isolate_handlers_new[] = {
3052 { "getIsolate", HandleIsolate }, 2471 { "getIsolate", HandleIsolate },
3053 { "getObject", HandleIsolateGetObject }, 2472 { "getObject", HandleIsolateGetObject },
2473 { "getObjectByAddress", HandleIsolateGetObjectByAddress },
3054 { "getBreakpoints", HandleIsolateGetBreakpoints }, 2474 { "getBreakpoints", HandleIsolateGetBreakpoints },
3055 { "pause", HandleIsolatePause }, 2475 { "pause", HandleIsolatePause },
3056 { "resume", HandleIsolateResume }, 2476 { "resume", HandleIsolateResume },
3057 { "getStack", HandleIsolateGetStack }, 2477 { "getStack", HandleIsolateGetStack },
3058 { "getCpuProfile", HandleIsolateGetCpuProfile }, 2478 { "getCpuProfile", HandleIsolateGetCpuProfile },
3059 { "getTagProfile", HandleIsolateGetTagProfile }, 2479 { "getTagProfile", HandleIsolateGetTagProfile },
3060 { "getAllocationProfile", HandleIsolateGetAllocationProfile }, 2480 { "getAllocationProfile", HandleIsolateGetAllocationProfile },
3061 { "getHeapMap", HandleIsolateGetHeapMap }, 2481 { "getHeapMap", HandleIsolateGetHeapMap },
3062 { "addBreakpoint", HandleIsolateAddBreakpoint }, 2482 { "addBreakpoint", HandleIsolateAddBreakpoint },
3063 { "removeBreakpoint", HandleIsolateRemoveBreakpoint }, 2483 { "removeBreakpoint", HandleIsolateRemoveBreakpoint },
3064 { "getCoverage", HandleIsolateGetCoverage }, 2484 { "getCoverage", HandleIsolateGetCoverage },
3065 { "eval", HandleIsolateEval }, 2485 { "eval", HandleIsolateEval },
3066 { "getRetainedSize", HandleIsolateGetRetainedSize }, 2486 { "getRetainedSize", HandleIsolateGetRetainedSize },
3067 { "getRetainingPath", HandleIsolateGetRetainingPath }, 2487 { "getRetainingPath", HandleIsolateGetRetainingPath },
3068 { "getInboundReferences", HandleIsolateGetInboundReferences }, 2488 { "getInboundReferences", HandleIsolateGetInboundReferences },
3069 { "getInstances", HandleIsolateGetInstances }, 2489 { "getInstances", HandleIsolateGetInstances },
3070 { "requestHeapSnapshot", HandleIsolateRequestHeapSnapshot }, 2490 { "requestHeapSnapshot", HandleIsolateRequestHeapSnapshot },
3071 { "getClassList", HandleIsolateGetClassList }, 2491 { "getClassList", HandleIsolateGetClassList },
3072 { "getTypeArgumentsList", HandleIsolateGetTypeArgumentsList }, 2492 { "getTypeArgumentsList", HandleIsolateGetTypeArgumentsList },
3073 { "getIsolateMetricList", HandleIsolateGetMetricList }, 2493 { "getIsolateMetricList", HandleIsolateGetMetricList },
3074 { "getIsolateMetric", HandleIsolateGetMetric }, 2494 { "getIsolateMetric", HandleIsolateGetMetric },
3075 { "_echo", HandleIsolateEcho }, 2495 { "_echo", HandleIsolateEcho },
3076 { "_triggerEchoEvent", HandleIsolateTriggerEchoEvent }, 2496 { "_triggerEchoEvent", HandleIsolateTriggerEchoEvent },
3077 { "_respondWithMalformedJson", HandleIsolateRespondWithMalformedJson }, 2497 { "_respondWithMalformedJson", HandleIsolateRespondWithMalformedJson },
3078 { "_respondWithMalformedObject", HandleIsolateRespondWithMalformedObject }, 2498 { "_respondWithMalformedObject", HandleIsolateRespondWithMalformedObject },
3079 }; 2499 };
3080 2500
3081 2501
3082 static IsolateMessageHandler FindIsolateMessageHandlerNew(const char* command) { 2502 static IsolateMessageHandler FindIsolateMessageHandler(const char* method) {
3083 intptr_t num_message_handlers = sizeof(isolate_handlers_new) / 2503 intptr_t num_message_handlers = sizeof(isolate_handlers_new) /
3084 sizeof(isolate_handlers_new[0]); 2504 sizeof(isolate_handlers_new[0]);
3085 for (intptr_t i = 0; i < num_message_handlers; i++) { 2505 for (intptr_t i = 0; i < num_message_handlers; i++) {
3086 const IsolateMessageHandlerEntry& entry = isolate_handlers_new[i]; 2506 const IsolateMessageHandlerEntry& entry = isolate_handlers_new[i];
3087 if (strcmp(command, entry.command) == 0) { 2507 if (strcmp(method, entry.method) == 0) {
3088 return entry.handler; 2508 return entry.handler;
3089 } 2509 }
3090 } 2510 }
3091 if (FLAG_trace_service) { 2511 if (FLAG_trace_service) {
3092 OS::Print("Service has no isolate message handler for <%s>\n", command); 2512 OS::Print("Service has no isolate message handler for <%s>\n", method);
3093 } 2513 }
3094 return NULL; 2514 return NULL;
3095 } 2515 }
3096 2516
3097 2517
3098 void Service::HandleRootMessageNew(const Array& msg) { 2518 void Service::HandleRootMessage(const Instance& msg_instance) {
3099 Isolate* isolate = Isolate::Current(); 2519 Isolate* isolate = Isolate::Current();
3100 ASSERT(!msg.IsNull()); 2520 ASSERT(!msg_instance.IsNull());
2521 ASSERT(msg_instance.IsArray());
3101 2522
3102 { 2523 {
3103 StackZone zone(isolate); 2524 StackZone zone(isolate);
3104 HANDLESCOPE(isolate); 2525 HANDLESCOPE(isolate);
3105 2526
3106 const Array& message = Array::Cast(msg); 2527 const Array& msg = Array::Cast(msg_instance);
3107 // Message is a list with five entries. 2528 ASSERT(msg.Length() == 5);
3108 ASSERT(message.Length() == 5);
3109 2529
3110 Instance& reply_port = Instance::Handle(isolate); 2530 Instance& reply_port = Instance::Handle(isolate);
3111 String& method = String::Handle(isolate); 2531 String& method = String::Handle(isolate);
3112 Array& param_keys = Array::Handle(isolate); 2532 Array& param_keys = Array::Handle(isolate);
3113 Array& param_values = Array::Handle(isolate); 2533 Array& param_values = Array::Handle(isolate);
3114 reply_port ^= msg.At(1); 2534 reply_port ^= msg.At(1);
3115 method ^= msg.At(2); 2535 method ^= msg.At(2);
3116 param_keys ^= msg.At(3); 2536 param_keys ^= msg.At(3);
3117 param_values ^= msg.At(4); 2537 param_values ^= msg.At(4);
3118 2538
3119 ASSERT(!method.IsNull()); 2539 ASSERT(!method.IsNull());
3120 ASSERT(!param_keys.IsNull()); 2540 ASSERT(!param_keys.IsNull());
3121 ASSERT(!param_values.IsNull()); 2541 ASSERT(!param_values.IsNull());
3122 ASSERT(param_keys.Length() == param_values.Length()); 2542 ASSERT(param_keys.Length() == param_values.Length());
3123 2543
3124 if (!reply_port.IsSendPort()) { 2544 if (!reply_port.IsSendPort()) {
3125 FATAL("SendPort expected."); 2545 FATAL("SendPort expected.");
3126 } 2546 }
3127 2547
3128 RootMessageHandler handler = 2548 RootMessageHandler handler =
3129 FindRootMessageHandlerNew(method.ToCString()); 2549 FindRootMessageHandler(method.ToCString());
3130 { 2550 {
3131 JSONStream js; 2551 JSONStream js;
3132 js.SetupNew(zone.GetZone(), SendPort::Cast(reply_port).Id(), 2552 js.Setup(zone.GetZone(), SendPort::Cast(reply_port).Id(),
3133 method, param_keys, param_values); 2553 method, param_keys, param_values);
3134 if (handler == NULL) { 2554 if (handler == NULL) {
3135 // Check for an embedder handler. 2555 // Check for an embedder handler.
3136 EmbedderServiceHandler* e_handler = 2556 EmbedderServiceHandler* e_handler =
3137 FindRootEmbedderHandler(method.ToCString()); 2557 FindRootEmbedderHandler(method.ToCString());
3138 if (e_handler != NULL) { 2558 if (e_handler != NULL) {
3139 EmbedderHandleMessage(e_handler, &js); 2559 EmbedderHandleMessage(e_handler, &js);
3140 } else { 2560 } else {
3141 if (FindIsolateMessageHandlerNew(method.ToCString()) != NULL) { 2561 if (FindIsolateMessageHandler(method.ToCString()) != NULL) {
3142 PrintError(&js, "%s expects an 'isolate' parameter\n", 2562 PrintMissingParamError(&js, "isolate");
3143 method.ToCString());
3144 } else { 2563 } else {
3145 PrintError(&js, "Unrecognized method: %s", method.ToCString()); 2564 PrintError(&js, "Unrecognized method: %s", method.ToCString());
3146 } 2565 }
3147 } 2566 }
3148 js.PostReply(); 2567 js.PostReply();
3149 } else { 2568 } else {
3150 if (handler(&js)) { 2569 if (handler(&js)) {
3151 // Handler returns true if the reply is ready to be posted. 2570 // Handler returns true if the reply is ready to be posted.
3152 // TODO(johnmccutchan): Support asynchronous replies. 2571 // TODO(johnmccutchan): Support asynchronous replies.
3153 js.PostReply(); 2572 js.PostReply();
3154 } 2573 }
3155 } 2574 }
3156 } 2575 }
3157 } 2576 }
3158 } 2577 }
3159 2578
3160 2579
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) { 2580 static bool HandleRootEcho(JSONStream* js) {
3240 JSONObject jsobj(js); 2581 JSONObject jsobj(js);
3241 return HandleCommonEcho(&jsobj, js); 2582 return HandleCommonEcho(&jsobj, js);
3242 } 2583 }
3243 2584
3244 2585
3245 class ServiceIsolateVisitor : public IsolateVisitor { 2586 class ServiceIsolateVisitor : public IsolateVisitor {
3246 public: 2587 public:
3247 explicit ServiceIsolateVisitor(JSONArray* jsarr) 2588 explicit ServiceIsolateVisitor(JSONArray* jsarr)
3248 : jsarr_(jsarr) { 2589 : jsarr_(jsarr) {
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
3286 // Construct the isolate list. 2627 // Construct the isolate list.
3287 { 2628 {
3288 JSONArray jsarr(&jsobj, "isolates"); 2629 JSONArray jsarr(&jsobj, "isolates");
3289 ServiceIsolateVisitor visitor(&jsarr); 2630 ServiceIsolateVisitor visitor(&jsarr);
3290 Isolate::VisitIsolates(&visitor); 2631 Isolate::VisitIsolates(&visitor);
3291 } 2632 }
3292 return true; 2633 return true;
3293 } 2634 }
3294 2635
3295 2636
3296 static bool HandleFlags(JSONStream* js) { 2637 static bool HandleVMFlagList(JSONStream* js) {
3297 if (js->num_arguments() == 1) { 2638 Flags::PrintJSON(js);
3298 Flags::PrintJSON(js); 2639 return true;
2640 }
2641
2642
2643 static bool HandleVMSetFlag(JSONStream* js) {
2644 const char* flag_name = js->LookupParam("name");
2645 if (flag_name == NULL) {
2646 PrintMissingParamError(js, "name");
3299 return true; 2647 return true;
3300 } else if (js->num_arguments() == 2) { 2648 }
3301 const char* arg = js->GetArgument(1); 2649 const char* flag_value = js->LookupParam("value");
3302 if (strcmp(arg, "set") == 0) { 2650 if (flag_value == NULL) {
3303 if (js->num_arguments() > 2) { 2651 PrintMissingParamError(js, "value");
3304 PrintError(js, "expected at most 2 arguments but found %" Pd "\n", 2652 return true;
3305 js->num_arguments()); 2653 }
3306 } else { 2654 JSONObject jsobj(js);
3307 if (js->HasOption("name") && js->HasOption("value")) { 2655 const char* error = NULL;
3308 JSONObject jsobj(js); 2656 if (Flags::SetFlag(flag_name, flag_value, &error)) {
3309 const char* flag_name = js->LookupOption("name"); 2657 jsobj.AddProperty("type", "Success");
3310 const char* flag_value = js->LookupOption("value"); 2658 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; 2659 return true;
3326 } else { 2660 } else {
3327 PrintError(js, "Command too long"); 2661 jsobj.AddProperty("type", "Failure");
2662 jsobj.AddProperty("id", "");
2663 jsobj.AddProperty("message", error);
3328 return true; 2664 return true;
3329 } 2665 }
3330 } 2666 }
3331 2667
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 2668
3354 static RootMessageHandlerEntry root_handlers_new[] = { 2669 static RootMessageHandlerEntry root_handlers_new[] = {
3355 { "getVM", HandleVM }, 2670 { "getVM", HandleVM },
2671 { "getFlagList", HandleVMFlagList },
2672 { "setFlag", HandleVMSetFlag },
3356 { "getVMMetricList", HandleVMGetMetricList }, 2673 { "getVMMetricList", HandleVMGetMetricList },
3357 { "getVMMetric", HandleVMGetMetric }, 2674 { "getVMMetric", HandleVMGetMetric },
3358 { "_echo", HandleRootEcho }, 2675 { "_echo", HandleRootEcho },
3359 }; 2676 };
3360 2677
3361 2678
3362 static RootMessageHandler FindRootMessageHandlerNew(const char* command) { 2679 static RootMessageHandler FindRootMessageHandler(const char* method) {
3363 intptr_t num_message_handlers = sizeof(root_handlers_new) / 2680 intptr_t num_message_handlers = sizeof(root_handlers_new) /
3364 sizeof(root_handlers_new[0]); 2681 sizeof(root_handlers_new[0]);
3365 for (intptr_t i = 0; i < num_message_handlers; i++) { 2682 for (intptr_t i = 0; i < num_message_handlers; i++) {
3366 const RootMessageHandlerEntry& entry = root_handlers_new[i]; 2683 const RootMessageHandlerEntry& entry = root_handlers_new[i];
3367 if (strcmp(command, entry.command) == 0) { 2684 if (strcmp(method, entry.method) == 0) {
3368 return entry.handler; 2685 return entry.handler;
3369 } 2686 }
3370 } 2687 }
3371 if (FLAG_trace_service) { 2688 if (FLAG_trace_service) {
3372 OS::Print("vm-service: No root message handler for <%s>.\n", command); 2689 OS::Print("vm-service: No root message handler for <%s>.\n", method);
3373 } 2690 }
3374 return NULL; 2691 return NULL;
3375 } 2692 }
3376 2693
3377 2694
3378 void Service::SendEvent(intptr_t eventId, const Object& eventMessage) { 2695 void Service::SendEvent(intptr_t eventId, const Object& eventMessage) {
3379 if (!IsRunning()) { 2696 if (!IsRunning()) {
3380 return; 2697 return;
3381 } 2698 }
3382 Isolate* isolate = Isolate::Current(); 2699 Isolate* isolate = Isolate::Current();
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
3449 SendEvent(kEventFamilyDebug, message); 2766 SendEvent(kEventFamilyDebug, message);
3450 } 2767 }
3451 2768
3452 2769
3453 void Service::EmbedderHandleMessage(EmbedderServiceHandler* handler, 2770 void Service::EmbedderHandleMessage(EmbedderServiceHandler* handler,
3454 JSONStream* js) { 2771 JSONStream* js) {
3455 ASSERT(handler != NULL); 2772 ASSERT(handler != NULL);
3456 Dart_ServiceRequestCallback callback = handler->callback(); 2773 Dart_ServiceRequestCallback callback = handler->callback();
3457 ASSERT(callback != NULL); 2774 ASSERT(callback != NULL);
3458 const char* r = NULL; 2775 const char* r = NULL;
3459 const char* name = js->command(); 2776 const char* name = js->method();
3460 const char** arguments = js->arguments(); 2777 const char** keys = js->param_keys();
3461 const char** keys = js->option_keys(); 2778 const char** values = js->param_values();
3462 const char** values = js->option_values(); 2779 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); 2780 ASSERT(r != NULL);
3466 // TODO(johnmccutchan): Allow for NULL returns? 2781 // TODO(johnmccutchan): Allow for NULL returns?
3467 TextBuffer* buffer = js->buffer(); 2782 TextBuffer* buffer = js->buffer();
3468 buffer->AddString(r); 2783 buffer->AddString(r);
3469 free(const_cast<char*>(r)); 2784 free(const_cast<char*>(r));
3470 } 2785 }
3471 2786
3472 2787
3473 void Service::RegisterIsolateEmbedderCallback( 2788 void Service::RegisterIsolateEmbedderCallback(
3474 const char* name, 2789 const char* name,
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
3539 while (current != NULL) { 2854 while (current != NULL) {
3540 if (strcmp(name, current->name()) == 0) { 2855 if (strcmp(name, current->name()) == 0) {
3541 return current; 2856 return current;
3542 } 2857 }
3543 current = current->next(); 2858 current = current->next();
3544 } 2859 }
3545 return NULL; 2860 return NULL;
3546 } 2861 }
3547 2862
3548 } // namespace dart 2863 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698