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

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

Issue 823403004: Begin migrating the vm service from a rest-style interface to a json-rpc style interface. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: remove old-style standalone tests. Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « runtime/vm/service.h ('k') | runtime/vm/service/message.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "vm/service.h" 5 #include "vm/service.h"
6 6
7 #include "include/dart_api.h" 7 #include "include/dart_api.h"
8 #include "platform/globals.h" 8 #include "platform/globals.h"
9 9
10 #include "vm/compiler.h" 10 #include "vm/compiler.h"
(...skipping 806 matching lines...) Expand 10 before | Expand all | Expand 10 after
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* command;
823 IsolateMessageHandler handler; 823 IsolateMessageHandler handler;
824 }; 824 };
825 825
826 static IsolateMessageHandler FindIsolateMessageHandler(const char* command); 826 static IsolateMessageHandler FindIsolateMessageHandler(const char* command);
827 static IsolateMessageHandler FindIsolateMessageHandlerNew(const char* command);
827 828
828 829
829 // A handler for a root (vm-global) request. 830 // A handler for a root (vm-global) request.
830 // 831 //
831 // If a handler returns true, the reply is complete and ready to be 832 // If a handler returns true, the reply is complete and ready to be
832 // posted. If a handler returns false, then it is responsible for 833 // posted. If a handler returns false, then it is responsible for
833 // posting the reply (this can be used for asynchronous delegation of 834 // posting the reply (this can be used for asynchronous delegation of
834 // the response handling). 835 // the response handling).
835 typedef bool (*RootMessageHandler)(JSONStream* stream); 836 typedef bool (*RootMessageHandler)(JSONStream* stream);
836 837
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
875 va_end(args); 876 va_end(args);
876 877
877 char* buffer = isolate->current_zone()->Alloc<char>(len + 1); 878 char* buffer = isolate->current_zone()->Alloc<char>(len + 1);
878 va_list args2; 879 va_list args2;
879 va_start(args2, format); 880 va_start(args2, format);
880 OS::VSNPrint(buffer, (len + 1), format, args2); 881 OS::VSNPrint(buffer, (len + 1), format, args2);
881 va_end(args2); 882 va_end(args2);
882 883
883 JSONObject jsobj(js); 884 JSONObject jsobj(js);
884 jsobj.AddProperty("type", "Error"); 885 jsobj.AddProperty("type", "Error");
885 jsobj.AddProperty("id", "");
886 jsobj.AddProperty("message", buffer); 886 jsobj.AddProperty("message", buffer);
887 PrintArgumentsAndOptions(jsobj, js); 887 PrintArgumentsAndOptions(jsobj, js);
888 } 888 }
889 889
890 890
891 static void PrintErrorWithKind(JSONStream* js, 891 static void PrintErrorWithKind(JSONStream* js,
892 const char* kind, 892 const char* kind,
893 const char* format, ...) { 893 const char* format, ...) {
894 Isolate* isolate = Isolate::Current(); 894 Isolate* isolate = Isolate::Current();
895 895
(...skipping 10 matching lines...) Expand all
906 906
907 JSONObject jsobj(js); 907 JSONObject jsobj(js);
908 jsobj.AddProperty("type", "Error"); 908 jsobj.AddProperty("type", "Error");
909 jsobj.AddProperty("id", ""); 909 jsobj.AddProperty("id", "");
910 jsobj.AddProperty("kind", kind); 910 jsobj.AddProperty("kind", kind);
911 jsobj.AddProperty("message", buffer); 911 jsobj.AddProperty("message", buffer);
912 PrintArgumentsAndOptions(jsobj, js); 912 PrintArgumentsAndOptions(jsobj, js);
913 } 913 }
914 914
915 915
916 void Service::HandleIsolateMessageNew(Isolate* isolate, const Array& msg) {
917 ASSERT(isolate != NULL);
918 ASSERT(!msg.IsNull());
919
920 {
921 StackZone zone(isolate);
922 HANDLESCOPE(isolate);
923
924 Instance& reply_port = Instance::Handle(isolate);
925 String& method = String::Handle(isolate);
926 Array& param_keys = Array::Handle(isolate);
927 Array& param_values = Array::Handle(isolate);
928 reply_port ^= msg.At(1);
929 method ^= msg.At(2);
930 param_keys ^= msg.At(3);
931 param_values ^= msg.At(4);
932
933 ASSERT(!method.IsNull());
934 ASSERT(!param_keys.IsNull());
935 ASSERT(!param_values.IsNull());
936 ASSERT(param_keys.Length() == param_values.Length());
937
938 if (!reply_port.IsSendPort()) {
939 FATAL("SendPort expected.");
940 }
941
942 IsolateMessageHandler handler =
943 FindIsolateMessageHandlerNew(method.ToCString());
944 {
945 JSONStream js;
946 js.SetupNew(zone.GetZone(), SendPort::Cast(reply_port).Id(),
947 method, param_keys, param_values);
948 if (handler == NULL) {
949 // Check for an embedder handler.
950 EmbedderServiceHandler* e_handler =
951 FindIsolateEmbedderHandler(method.ToCString());
952 if (e_handler != NULL) {
953 EmbedderHandleMessage(e_handler, &js);
954 } else {
955 PrintError(&js, "Unrecognized method: %s", method.ToCString());
956 }
957 js.PostReply();
958 } else {
959 if (handler(isolate, &js)) {
960 // Handler returns true if the reply is ready to be posted.
961 // TODO(johnmccutchan): Support asynchronous replies.
962 js.PostReply();
963 }
964 }
965 }
966 }
967 }
968
969
916 void Service::HandleIsolateMessage(Isolate* isolate, const Array& msg) { 970 void Service::HandleIsolateMessage(Isolate* isolate, const Array& msg) {
917 ASSERT(isolate != NULL); 971 ASSERT(isolate != NULL);
918 ASSERT(!msg.IsNull()); 972 ASSERT(!msg.IsNull());
919 973
920 { 974 {
921 StackZone zone(isolate); 975 StackZone zone(isolate);
922 HANDLESCOPE(isolate); 976 HANDLESCOPE(isolate);
923 977
924 // Message is a list with five entries. 978 // Message is a list with five entries.
925 ASSERT(msg.Length() == 5); 979 ASSERT(msg.Length() == 5);
926 980
981 Object& tmp = Object::Handle(isolate);
982 tmp = msg.At(2);
983 if (tmp.IsString()) {
984 return Service::HandleIsolateMessageNew(isolate, msg);
985 }
986
927 Instance& reply_port = Instance::Handle(isolate); 987 Instance& reply_port = Instance::Handle(isolate);
928 GrowableObjectArray& path = GrowableObjectArray::Handle(isolate); 988 GrowableObjectArray& path = GrowableObjectArray::Handle(isolate);
929 Array& option_keys = Array::Handle(isolate); 989 Array& option_keys = Array::Handle(isolate);
930 Array& option_values = Array::Handle(isolate); 990 Array& option_values = Array::Handle(isolate);
931 reply_port ^= msg.At(1); 991 reply_port ^= msg.At(1);
932 path ^= msg.At(2); 992 path ^= msg.At(2);
933 option_keys ^= msg.At(3); 993 option_keys ^= msg.At(3);
934 option_values ^= msg.At(4); 994 option_values ^= msg.At(4);
935 995
936 ASSERT(!path.IsNull()); 996 ASSERT(!path.IsNull());
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
979 } 1039 }
980 } 1040 }
981 1041
982 1042
983 static bool HandleIsolate(Isolate* isolate, JSONStream* js) { 1043 static bool HandleIsolate(Isolate* isolate, JSONStream* js) {
984 isolate->PrintJSON(js, false); 1044 isolate->PrintJSON(js, false);
985 return true; 1045 return true;
986 } 1046 }
987 1047
988 1048
989 static bool HandleStackTrace(Isolate* isolate, JSONStream* js) { 1049 static bool HandleIsolateGetStack(Isolate* isolate, JSONStream* js) {
990 if (js->num_arguments() > 1) {
991 PrintError(js, "Command too long");
992 return true;
993 }
994 DebuggerStackTrace* stack = isolate->debugger()->StackTrace(); 1050 DebuggerStackTrace* stack = isolate->debugger()->StackTrace();
995 JSONObject jsobj(js); 1051 JSONObject jsobj(js);
996 jsobj.AddProperty("type", "StackTrace"); 1052 jsobj.AddProperty("type", "Stack");
997 jsobj.AddProperty("id", "stacktrace"); 1053 JSONArray jsarr(&jsobj, "frames");
998 JSONArray jsarr(&jsobj, "members");
999 intptr_t num_frames = stack->Length(); 1054 intptr_t num_frames = stack->Length();
1000 for (intptr_t i = 0; i < num_frames; i++) { 1055 for (intptr_t i = 0; i < num_frames; i++) {
1001 ActivationFrame* frame = stack->FrameAt(i); 1056 ActivationFrame* frame = stack->FrameAt(i);
1002 JSONObject jsobj(&jsarr); 1057 JSONObject jsobj(&jsarr);
1003 frame->PrintToJSONObject(&jsobj); 1058 frame->PrintToJSONObject(&jsobj);
1004 // TODO(turnidge): Implement depth differently -- differentiate 1059 // TODO(turnidge): Implement depth differently -- differentiate
1005 // inlined frames. 1060 // inlined frames.
1006 jsobj.AddProperty("depth", i); 1061 jsobj.AddProperty("depth", i);
1007 } 1062 }
1008 return true; 1063 return true;
(...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after
1188 return true; 1243 return true;
1189 } 1244 }
1190 } 1245 }
1191 return false; 1246 return false;
1192 } else { 1247 } else {
1193 return !(obj.IsInstance() || obj.IsNull()); 1248 return !(obj.IsInstance() || obj.IsNull());
1194 } 1249 }
1195 } 1250 }
1196 1251
1197 1252
1198 static bool HandleInboundReferences(Isolate* isolate, 1253 static RawObject* LookupObjectId(Isolate* isolate,
1199 Object* target, 1254 const char* arg,
1200 intptr_t limit, 1255 ObjectIdRing::LookupResult* kind) {
1201 JSONStream* js) { 1256 *kind = ObjectIdRing::kValid;
1257 if (strncmp(arg, "int-", 4) == 0) {
1258 arg += 4;
1259 int64_t value = 0;
1260 if (!OS::StringToInt64(arg, &value) ||
1261 !Smi::IsValid(value)) {
1262 *kind = ObjectIdRing::kInvalid;
1263 return Object::null();
1264 }
1265 const Integer& obj =
1266 Integer::Handle(isolate, Smi::New(static_cast<intptr_t>(value)));
1267 return obj.raw();
1268 } else if (strcmp(arg, "bool-true") == 0) {
1269 return Bool::True().raw();
1270 } else if (strcmp(arg, "bool-false") == 0) {
1271 return Bool::False().raw();
1272 } else if (strcmp(arg, "null") == 0) {
1273 return Object::null();
1274 } else if (strcmp(arg, "not-initialized") == 0) {
1275 return Object::sentinel().raw();
1276 } else if (strcmp(arg, "being-initialized") == 0) {
1277 return Object::transition_sentinel().raw();
1278 }
1279
1280 ObjectIdRing* ring = isolate->object_id_ring();
1281 ASSERT(ring != NULL);
1282 intptr_t id = -1;
1283 if (!GetIntegerId(arg, &id)) {
1284 *kind = ObjectIdRing::kInvalid;
1285 return Object::null();
1286 }
1287 return ring->GetObjectForId(id, kind);
1288 }
1289
1290
1291 static RawObject* LookupHeapObjectLibraries(Isolate* isolate,
1292 char** parts, int num_parts) {
1293 // Library ids look like "libraries/35"
1294 if (num_parts < 2) {
1295 return Object::sentinel().raw();
1296 }
1297 const GrowableObjectArray& libs =
1298 GrowableObjectArray::Handle(isolate->object_store()->libraries());
1299 ASSERT(!libs.IsNull());
1300 intptr_t id = 0;
1301 if (!GetIntegerId(parts[1], &id)) {
1302 return Object::sentinel().raw();
1303 }
1304 if ((id < 0) || (id >= libs.Length())) {
1305 return Object::sentinel().raw();
1306 }
1307 Library& lib = Library::Handle();
1308 lib ^= libs.At(id);
1309 ASSERT(!lib.IsNull());
1310 if (num_parts == 2) {
1311 return lib.raw();
1312 }
1313 if (strcmp(parts[2], "scripts") == 0) {
1314 // Script ids look like "libraries/35/scripts/library%2Furl.dart"
1315 if (num_parts != 4) {
1316 return Object::sentinel().raw();
1317 }
1318 const String& id = String::Handle(String::New(parts[3]));
1319 ASSERT(!id.IsNull());
1320 // The id is the url of the script % encoded, decode it.
1321 const String& requested_url = String::Handle(String::DecodeIRI(id));
1322 Script& script = Script::Handle();
1323 String& script_url = String::Handle();
1324 const Array& loaded_scripts = Array::Handle(lib.LoadedScripts());
1325 ASSERT(!loaded_scripts.IsNull());
1326 intptr_t i;
1327 for (i = 0; i < loaded_scripts.Length(); i++) {
1328 script ^= loaded_scripts.At(i);
1329 ASSERT(!script.IsNull());
1330 script_url ^= script.url();
1331 if (script_url.Equals(requested_url)) {
1332 return script.raw();
1333 }
1334 }
1335 }
1336
1337 // Not found.
1338 return Object::sentinel().raw();
1339 }
1340
1341 static RawObject* LookupHeapObjectClasses(Isolate* isolate,
1342 char** parts, int num_parts) {
1343 // Class ids look like: "classes/17"
1344 if (num_parts < 2) {
1345 return Object::sentinel().raw();
1346 }
1347 ClassTable* table = isolate->class_table();
1348 intptr_t id;
1349 if (!GetIntegerId(parts[1], &id) ||
1350 !table->IsValidIndex(id)) {
1351 return Object::sentinel().raw();
1352 }
1353 Class& cls = Class::Handle(table->At(id));
1354 if (num_parts == 2) {
1355 return cls.raw();
1356 }
1357 if (strcmp(parts[2], "closures") == 0) {
1358 // Closure ids look like: "classes/17/closures/11"
1359 if (num_parts != 4) {
1360 return Object::sentinel().raw();
1361 }
1362 intptr_t id;
1363 if (!GetIntegerId(parts[3], &id)) {
1364 return Object::sentinel().raw();
1365 }
1366 Function& func = Function::Handle();
1367 func ^= cls.ClosureFunctionFromIndex(id);
1368 if (func.IsNull()) {
1369 return Object::sentinel().raw();
1370 }
1371 return func.raw();
1372
1373 } else if (strcmp(parts[2], "fields") == 0) {
1374 // Field ids look like: "classes/17/fields/11"
1375 if (num_parts != 4) {
1376 return Object::sentinel().raw();
1377 }
1378 intptr_t id;
1379 if (!GetIntegerId(parts[3], &id)) {
1380 return Object::sentinel().raw();
1381 }
1382 Field& field = Field::Handle(cls.FieldFromIndex(id));
1383 if (field.IsNull()) {
1384 return Object::sentinel().raw();
1385 }
1386 return field.raw();
1387
1388 } else if (strcmp(parts[2], "functions") == 0) {
1389 // Function ids look like: "classes/17/functions/11"
1390 if (num_parts != 4) {
1391 return Object::sentinel().raw();
1392 }
1393 const char* encoded_id = parts[3];
1394 String& id = String::Handle(isolate, String::New(encoded_id));
1395 id = String::DecodeIRI(id);
1396 if (id.IsNull()) {
1397 return Object::sentinel().raw();
1398 }
1399 Function& func = Function::Handle(cls.LookupFunction(id));
1400 if (func.IsNull()) {
1401 return Object::sentinel().raw();
1402 }
1403 return func.raw();
1404
1405 } else if (strcmp(parts[2], "implicit_closures") == 0) {
1406 // Function ids look like: "classes/17/implicit_closures/11"
1407 if (num_parts != 4) {
1408 return Object::sentinel().raw();
1409 }
1410 intptr_t id;
1411 if (!GetIntegerId(parts[3], &id)) {
1412 return Object::sentinel().raw();
1413 }
1414 Function& func = Function::Handle();
1415 func ^= cls.ImplicitClosureFunctionFromIndex(id);
1416 if (func.IsNull()) {
1417 return Object::sentinel().raw();
1418 }
1419 return func.raw();
1420
1421 } else if (strcmp(parts[2], "dispatchers") == 0) {
1422 // Dispatcher Function ids look like: "classes/17/dispatchers/11"
1423 if (num_parts != 4) {
1424 return Object::sentinel().raw();
1425 }
1426 intptr_t id;
1427 if (!GetIntegerId(parts[3], &id)) {
1428 return Object::sentinel().raw();
1429 }
1430 Function& func = Function::Handle();
1431 func ^= cls.InvocationDispatcherFunctionFromIndex(id);
1432 if (func.IsNull()) {
1433 return Object::sentinel().raw();
1434 }
1435 return func.raw();
1436
1437 } else if (strcmp(parts[2], "types") == 0) {
1438 // Type ids look like: "classes/17/types/11"
1439 if (num_parts != 4) {
1440 return Object::sentinel().raw();
1441 }
1442 intptr_t id;
1443 if (!GetIntegerId(parts[3], &id)) {
1444 return Object::sentinel().raw();
1445 }
1446 Type& type = Type::Handle();
1447 type ^= cls.CanonicalTypeFromIndex(id);
1448 if (type.IsNull()) {
1449 return Object::sentinel().raw();
1450 }
1451 return type.raw();
1452 }
1453
1454 // Not found.
1455 return Object::sentinel().raw();
1456 }
1457
1458
1459 static RawObject* LookupHeapObject(Isolate* isolate,
1460 const char* id_original,
1461 ObjectIdRing::LookupResult* result) {
1462 char* id = isolate->current_zone()->MakeCopyOfString(id_original);
1463
1464 // Parse the id by splitting at each '/'.
1465 const int MAX_PARTS = 8;
1466 char* parts[MAX_PARTS];
1467 int num_parts = 0;
1468 int i = 0;
1469 int start_pos = 0;
1470 while (id[i] != '\0') {
1471 if (id[i] == '/') {
1472 id[i++] = '\0';
1473 parts[num_parts++] = &id[start_pos];
1474 if (num_parts == MAX_PARTS) {
1475 break;
1476 }
1477 start_pos = i;
1478 } else {
1479 i++;
1480 }
1481 }
1482 if (num_parts < MAX_PARTS) {
1483 parts[num_parts++] = &id[start_pos];
1484 }
1485
1486 if (result != NULL) {
1487 *result = ObjectIdRing::kValid;
1488 }
1489
1490 if (strcmp(parts[0], "objects") == 0) {
1491 // Object ids look like "objects/1123"
1492 Object& obj = Object::Handle(isolate);
1493 ObjectIdRing::LookupResult lookup_result;
1494 obj = LookupObjectId(isolate, parts[1], &lookup_result);
1495 if (lookup_result != ObjectIdRing::kValid) {
1496 if (result != NULL) {
1497 *result = lookup_result;
1498 }
1499 return Object::sentinel().raw();
1500 }
1501 return obj.raw();
1502
1503 } else if (strcmp(parts[0], "libraries") == 0) {
1504 return LookupHeapObjectLibraries(isolate, parts, num_parts);
1505 } else if (strcmp(parts[0], "classes") == 0) {
1506 return LookupHeapObjectClasses(isolate, parts, num_parts);
1507 }
1508
1509 // Not found.
1510 return Object::sentinel().raw();
1511 }
1512
1513
1514 static void PrintSentinel(JSONStream* js,
1515 const char* id,
1516 const char* preview) {
1517 JSONObject jsobj(js);
1518 jsobj.AddProperty("type", "Sentinel");
1519 jsobj.AddProperty("id", id);
1520 jsobj.AddProperty("valueAsString", preview);
1521 }
1522
1523
1524 static SourceBreakpoint* LookupBreakpoint(Isolate* isolate, const char* id) {
1525 size_t end_pos = strcspn(id, "/");
1526 const char* rest = NULL;
1527 if (end_pos < strlen(id)) {
1528 rest = id + end_pos + 1; // +1 for '/'.
1529 }
1530 if (strncmp("breakpoints", id, end_pos) == 0) {
1531 if (rest == NULL) {
1532 return NULL;
1533 }
1534 intptr_t bpt_id = 0;
1535 SourceBreakpoint* bpt = NULL;
1536 if (GetIntegerId(rest, &bpt_id)) {
1537 bpt = isolate->debugger()->GetBreakpointById(bpt_id);
1538 }
1539 return bpt;
1540 }
1541 return NULL;
1542 }
1543
1544
1545
1546
1547 static bool PrintInboundReferences(Isolate* isolate,
1548 Object* target,
1549 intptr_t limit,
1550 JSONStream* js) {
1202 ObjectGraph graph(isolate); 1551 ObjectGraph graph(isolate);
1203 Array& path = Array::Handle(Array::New(limit * 2)); 1552 Array& path = Array::Handle(Array::New(limit * 2));
1204 intptr_t length = graph.InboundReferences(target, path); 1553 intptr_t length = graph.InboundReferences(target, path);
1205 JSONObject jsobj(js); 1554 JSONObject jsobj(js);
1206 jsobj.AddProperty("type", "InboundReferences"); 1555 jsobj.AddProperty("type", "InboundReferences");
1207 jsobj.AddProperty("id", "inbound_references");
1208 { 1556 {
1209 JSONArray elements(&jsobj, "references"); 1557 JSONArray elements(&jsobj, "references");
1210 Object& source = Object::Handle(); 1558 Object& source = Object::Handle();
1211 Smi& slot_offset = Smi::Handle(); 1559 Smi& slot_offset = Smi::Handle();
1212 Class& source_class = Class::Handle(); 1560 Class& source_class = Class::Handle();
1213 Field& field = Field::Handle(); 1561 Field& field = Field::Handle();
1214 Array& parent_field_map = Array::Handle(); 1562 Array& parent_field_map = Array::Handle();
1215 limit = Utils::Minimum(limit, length); 1563 limit = Utils::Minimum(limit, length);
1216 for (intptr_t i = 0; i < limit; ++i) { 1564 for (intptr_t i = 0; i < limit; ++i) {
1217 JSONObject jselement(&elements); 1565 JSONObject jselement(&elements);
(...skipping 19 matching lines...) Expand all
1237 // We nil out the array after generating the response to prevent 1585 // We nil out the array after generating the response to prevent
1238 // reporting suprious references when repeatedly looking for the 1586 // reporting suprious references when repeatedly looking for the
1239 // references to an object. 1587 // references to an object.
1240 path.SetAt(i * 2, Object::null_object()); 1588 path.SetAt(i * 2, Object::null_object());
1241 } 1589 }
1242 } 1590 }
1243 return true; 1591 return true;
1244 } 1592 }
1245 1593
1246 1594
1247 static bool HandleRetainingPath(Isolate* isolate, 1595 static bool HandleIsolateGetInboundReferences(Isolate* isolate,
1248 Object* obj, 1596 JSONStream* js) {
1249 intptr_t limit, 1597 const char* target_id = js->LookupOption("targetId");
1250 JSONStream* js) { 1598 if (target_id == NULL) {
1599 PrintError(js, "Missing 'targetId' option");
1600 return true;
1601 }
1602 const char* limit_cstr = js->LookupOption("limit");
1603 if (target_id == NULL) {
1604 PrintError(js, "Missing 'limit' option");
1605 return true;
1606 }
1607 intptr_t limit;
1608 if (!GetIntegerId(js->LookupOption("limit"), &limit)) {
1609 PrintError(js, "Invalid 'limit' option: %s", limit_cstr);
1610 return true;
1611 }
1612
1613 Object& obj = Object::Handle(isolate);
1614 ObjectIdRing::LookupResult lookup_result;
1615 {
1616 HANDLESCOPE(isolate);
1617 obj = LookupHeapObject(isolate, target_id, &lookup_result);
1618 }
1619 if (obj.raw() == Object::sentinel().raw()) {
1620 if (lookup_result == ObjectIdRing::kCollected) {
1621 PrintErrorWithKind(
1622 js, "InboundReferencesCollected",
1623 "attempt to find a retaining path for a collected object\n",
1624 js->num_arguments());
1625 return true;
1626 } else if (lookup_result == ObjectIdRing::kExpired) {
1627 PrintErrorWithKind(
1628 js, "InboundReferencesExpired",
1629 "attempt to find a retaining path for an expired object\n",
1630 js->num_arguments());
1631 return true;
1632 }
1633 PrintError(js, "Invalid 'targetId' value: no object with id '%s'",
1634 target_id);
1635 return true;
1636 }
1637 return PrintInboundReferences(isolate, &obj, limit, js);
1638 }
1639
1640
1641 static bool PrintRetainingPath(Isolate* isolate,
1642 Object* obj,
1643 intptr_t limit,
1644 JSONStream* js) {
1251 ObjectGraph graph(isolate); 1645 ObjectGraph graph(isolate);
1252 Array& path = Array::Handle(Array::New(limit * 2)); 1646 Array& path = Array::Handle(Array::New(limit * 2));
1253 intptr_t length = graph.RetainingPath(obj, path); 1647 intptr_t length = graph.RetainingPath(obj, path);
1254 JSONObject jsobj(js); 1648 JSONObject jsobj(js);
1255 jsobj.AddProperty("type", "RetainingPath"); 1649 jsobj.AddProperty("type", "RetainingPath");
1256 jsobj.AddProperty("id", "retaining_path");
1257 jsobj.AddProperty("length", length); 1650 jsobj.AddProperty("length", length);
1258 JSONArray elements(&jsobj, "elements"); 1651 JSONArray elements(&jsobj, "elements");
1259 Object& element = Object::Handle(); 1652 Object& element = Object::Handle();
1260 Object& parent = Object::Handle(); 1653 Object& parent = Object::Handle();
1261 Smi& offset_from_parent = Smi::Handle(); 1654 Smi& offset_from_parent = Smi::Handle();
1262 Class& parent_class = Class::Handle(); 1655 Class& parent_class = Class::Handle();
1263 Array& parent_field_map = Array::Handle(); 1656 Array& parent_field_map = Array::Handle();
1264 Field& field = Field::Handle(); 1657 Field& field = Field::Handle();
1265 limit = Utils::Minimum(limit, length); 1658 limit = Utils::Minimum(limit, length);
1266 for (intptr_t i = 0; i < limit; ++i) { 1659 for (intptr_t i = 0; i < limit; ++i) {
(...skipping 17 matching lines...) Expand all
1284 intptr_t offset = offset_from_parent.Value(); 1677 intptr_t offset = offset_from_parent.Value();
1285 if (offset > 0 && offset < parent_field_map.Length()) { 1678 if (offset > 0 && offset < parent_field_map.Length()) {
1286 field ^= parent_field_map.At(offset); 1679 field ^= parent_field_map.At(offset);
1287 jselement.AddProperty("parentField", field); 1680 jselement.AddProperty("parentField", field);
1288 } 1681 }
1289 } 1682 }
1290 } 1683 }
1291 } 1684 }
1292 1685
1293 // We nil out the array after generating the response to prevent 1686 // We nil out the array after generating the response to prevent
1294 // reporting suprious references when looking for inbound references 1687 // reporting spurious references when looking for inbound references
1295 // after looking for a retaining path. 1688 // after looking for a retaining path.
1296 for (intptr_t i = 0; i < limit; ++i) { 1689 for (intptr_t i = 0; i < limit; ++i) {
1297 path.SetAt(i * 2, Object::null_object()); 1690 path.SetAt(i * 2, Object::null_object());
1298 } 1691 }
1299 1692
1300 return true; 1693 return true;
1301 } 1694 }
1302 1695
1696 static bool HandleIsolateGetRetainingPath(Isolate* isolate,
1697 JSONStream* js) {
1698 const char* target_id = js->LookupOption("targetId");
1699 if (target_id == NULL) {
1700 PrintError(js, "Missing 'targetId' option");
1701 return true;
1702 }
1703 const char* limit_cstr = js->LookupOption("limit");
1704 if (target_id == NULL) {
1705 PrintError(js, "Missing 'limit' option");
1706 return true;
1707 }
1708 intptr_t limit;
1709 if (!GetIntegerId(js->LookupOption("limit"), &limit)) {
1710 PrintError(js, "Invalid 'limit' option: %s", limit_cstr);
1711 return true;
1712 }
1303 1713
1304 // Takes an Object* only because RetainingPath temporarily clears it. 1714 Object& obj = Object::Handle(isolate);
1305 static bool HandleInstanceCommands(Isolate* isolate, 1715 ObjectIdRing::LookupResult lookup_result;
1306 Object* obj, 1716 {
1307 ObjectIdRing::LookupResult kind, 1717 HANDLESCOPE(isolate);
1308 JSONStream* js, 1718 obj = LookupHeapObject(isolate, target_id, &lookup_result);
1309 intptr_t arg_pos) { 1719 }
1310 ASSERT(js->num_arguments() > arg_pos); 1720 if (obj.raw() == Object::sentinel().raw()) {
1311 ASSERT(kind != ObjectIdRing::kInvalid); 1721 if (lookup_result == ObjectIdRing::kCollected) {
1312 const char* action = js->GetArgument(arg_pos); 1722 PrintErrorWithKind(
1313 if (strcmp(action, "eval") == 0) { 1723 js, "RetainingPathCollected",
1314 if (js->num_arguments() > (arg_pos + 1)) { 1724 "attempt to find a retaining path for a collected object\n",
1315 PrintError(js, "expected at most %" Pd " arguments but found %" Pd "\n", 1725 js->num_arguments());
1316 arg_pos + 1, 1726 return true;
1317 js->num_arguments()); 1727 } else if (lookup_result == ObjectIdRing::kExpired) {
1728 PrintErrorWithKind(
1729 js, "RetainingPathExpired",
1730 "attempt to find a retaining path for an expired object\n",
1731 js->num_arguments());
1318 return true; 1732 return true;
1319 } 1733 }
1320 if (kind == ObjectIdRing::kCollected) { 1734 PrintError(js, "Invalid 'targetId' value: no object with id '%s'",
1321 PrintErrorWithKind(js, "EvalCollected", 1735 target_id);
1322 "attempt to evaluate against collected object\n",
1323 js->num_arguments());
1324 return true;
1325 }
1326 if (kind == ObjectIdRing::kExpired) {
1327 PrintErrorWithKind(js, "EvalExpired",
1328 "attempt to evaluate against expired object\n",
1329 js->num_arguments());
1330 return true;
1331 }
1332 if (ContainsNonInstance(*obj)) {
1333 PrintError(js, "attempt to evaluate against internal VM object\n");
1334 return true;
1335 }
1336 const char* expr = js->LookupOption("expr");
1337 if (expr == NULL) {
1338 PrintError(js, "eval expects an 'expr' option\n",
1339 js->num_arguments());
1340 return true;
1341 }
1342 const String& expr_str = String::Handle(isolate, String::New(expr));
1343 ASSERT(obj->IsInstance() || obj->IsNull());
1344 Instance& instance = Instance::Handle();
1345 instance ^= obj->raw();
1346 const Object& result =
1347 Object::Handle(instance.Evaluate(expr_str,
1348 Array::empty_array(),
1349 Array::empty_array()));
1350 result.PrintJSON(js, true);
1351 return true; 1736 return true;
1352 } else if (strcmp(action, "retained") == 0) { 1737 }
1353 if (kind == ObjectIdRing::kCollected) { 1738 return PrintRetainingPath(isolate, &obj, limit, js);
1739 }
1740
1741
1742 static bool HandleIsolateGetRetainedSize(Isolate* isolate, JSONStream* js) {
1743 const char* target_id = js->LookupOption("targetId");
1744 if (target_id == NULL) {
1745 PrintError(js, "Missing 'targetId' option");
1746 return true;
1747 }
1748 ObjectIdRing::LookupResult lookup_result;
1749 Object& obj = Object::Handle(LookupHeapObject(isolate, target_id,
1750 &lookup_result));
1751 if (obj.raw() == Object::sentinel().raw()) {
1752 if (lookup_result == ObjectIdRing::kCollected) {
1354 PrintErrorWithKind( 1753 PrintErrorWithKind(
1355 js, "RetainedCollected", 1754 js, "RetainedCollected",
1356 "attempt to calculate size retained by a collected object\n", 1755 "attempt to calculate size retained by a collected object\n",
1357 js->num_arguments()); 1756 js->num_arguments());
1358 return true; 1757 return true;
1359 } 1758 } else if (lookup_result == ObjectIdRing::kExpired) {
1360 if (kind == ObjectIdRing::kExpired) {
1361 PrintErrorWithKind( 1759 PrintErrorWithKind(
1362 js, "RetainedExpired", 1760 js, "RetainedExpired",
1363 "attempt to calculate size retained by an expired object\n", 1761 "attempt to calculate size retained by an expired object\n",
1364 js->num_arguments()); 1762 js->num_arguments());
1365 return true; 1763 return true;
1366 } 1764 }
1765 PrintError(js, "Invalid 'targetId' value: no object with id '%s'",
1766 target_id);
1767 return true;
1768 }
1769 if (obj.IsClass()) {
1770 const Class& cls = Class::Cast(obj);
1367 ObjectGraph graph(isolate); 1771 ObjectGraph graph(isolate);
1368 intptr_t retained_size = graph.SizeRetainedByInstance(*obj); 1772 intptr_t retained_size = graph.SizeRetainedByClass(cls.id());
1369 const Object& result = Object::Handle(Integer::New(retained_size)); 1773 const Object& result = Object::Handle(Integer::New(retained_size));
1370 result.PrintJSON(js, true); 1774 result.PrintJSON(js, true);
1371 return true; 1775 return true;
1372 } else if (strcmp(action, "retaining_path") == 0) {
1373 if (kind == ObjectIdRing::kCollected) {
1374 PrintErrorWithKind(
1375 js, "RetainingPathCollected",
1376 "attempt to find a retaining path for a collected object\n",
1377 js->num_arguments());
1378 return true;
1379 }
1380 if (kind == ObjectIdRing::kExpired) {
1381 PrintErrorWithKind(
1382 js, "RetainingPathExpired",
1383 "attempt to find a retaining path for an expired object\n",
1384 js->num_arguments());
1385 return true;
1386 }
1387 intptr_t limit;
1388 if (!GetIntegerId(js->LookupOption("limit"), &limit)) {
1389 PrintError(js, "retaining_path expects a 'limit' option\n",
1390 js->num_arguments());
1391 return true;
1392 }
1393 return HandleRetainingPath(isolate, obj, limit, js);
1394 } else if (strcmp(action, "inbound_references") == 0) {
1395 if (kind == ObjectIdRing::kCollected) {
1396 PrintErrorWithKind(
1397 js, "InboundReferencesCollected",
1398 "attempt to find inbound references for a collected object\n",
1399 js->num_arguments());
1400 return true;
1401 }
1402 if (kind == ObjectIdRing::kExpired) {
1403 PrintErrorWithKind(
1404 js, "InboundReferencesExpired",
1405 "attempt to find inbound references for an expired object\n",
1406 js->num_arguments());
1407 return true;
1408 }
1409 intptr_t limit;
1410 if (!GetIntegerId(js->LookupOption("limit"), &limit)) {
1411 PrintError(js, "inbound_references expects a 'limit' option\n",
1412 js->num_arguments());
1413 return true;
1414 }
1415 return HandleInboundReferences(isolate, obj, limit, js);
1416 } 1776 }
1417 1777 if (obj.IsInstance() || obj.IsNull()) {
1418 PrintError(js, "unrecognized action '%s'\n", action); 1778 // We don't use Instance::Cast here because it doesn't allow null.
1779 ObjectGraph graph(isolate);
1780 intptr_t retained_size = graph.SizeRetainedByInstance(obj);
1781 const Object& result = Object::Handle(Integer::New(retained_size));
1782 result.PrintJSON(js, true);
1783 return true;
1784 }
1785 PrintError(js, "Invalid 'targetId' value: id '%s' does not correspond to a "
1786 "library, class, or instance", target_id);
1419 return true; 1787 return true;
1420 } 1788 }
1421 1789
1422 1790
1423 static bool HandleClassesClosures(Isolate* isolate, const Class& cls, 1791 static bool HandleClassesClosures(Isolate* isolate, const Class& cls,
1424 JSONStream* js) { 1792 JSONStream* js) {
1425 intptr_t id; 1793 intptr_t id;
1426 if (js->num_arguments() > 4) { 1794 if (js->num_arguments() > 4) {
1427 PrintError(js, "Command too long"); 1795 PrintError(js, "Command too long");
1428 return true; 1796 return true;
1429 } 1797 }
1430 if (!GetIntegerId(js->GetArgument(3), &id)) { 1798 if (!GetIntegerId(js->GetArgument(3), &id)) {
1431 PrintError(js, "Must specify collection object id: closures/id"); 1799 PrintError(js, "Must specify collection object id: closures/id");
1432 return true; 1800 return true;
1433 } 1801 }
1434 Function& func = Function::Handle(); 1802 Function& func = Function::Handle();
1435 func ^= cls.ClosureFunctionFromIndex(id); 1803 func ^= cls.ClosureFunctionFromIndex(id);
1436 if (func.IsNull()) { 1804 if (func.IsNull()) {
1437 PrintError(js, "Closure function %" Pd " not found", id); 1805 PrintError(js, "Closure function %" Pd " not found", id);
1438 return true; 1806 return true;
1439 } 1807 }
1440 func.PrintJSON(js, false); 1808 func.PrintJSON(js, false);
1441 return true; 1809 return true;
1442 } 1810 }
1443 1811
1444 1812
1445 static bool HandleClassesEval(Isolate* isolate, const Class& cls, 1813 static bool HandleIsolateEval(Isolate* isolate, JSONStream* js) {
1446 JSONStream* js) { 1814 const char* target_id = js->LookupOption("targetId");
1447 if (js->num_arguments() > 3) { 1815 if (target_id == NULL) {
1448 PrintError(js, "Command too long"); 1816 PrintError(js, "Missing 'targetId' option");
1449 return true; 1817 return true;
1450 } 1818 }
1451 const char* expr = js->LookupOption("expr"); 1819 const char* expr = js->LookupOption("expression");
1452 if (expr == NULL) { 1820 if (expr == NULL) {
1453 PrintError(js, "eval expects an 'expr' option\n", 1821 PrintError(js, "Missing 'expression' option");
1454 js->num_arguments());
1455 return true; 1822 return true;
1456 } 1823 }
1457 const String& expr_str = String::Handle(isolate, String::New(expr)); 1824 const String& expr_str = String::Handle(isolate, String::New(expr));
1458 const Object& result = Object::Handle(cls.Evaluate(expr_str, 1825 ObjectIdRing::LookupResult lookup_result;
1459 Array::empty_array(), 1826 Object& obj = Object::Handle(LookupHeapObject(isolate, target_id,
1460 Array::empty_array())); 1827 &lookup_result));
1461 result.PrintJSON(js, true); 1828 if (obj.raw() == Object::sentinel().raw()) {
1829 if (lookup_result == ObjectIdRing::kCollected) {
1830 PrintSentinel(js, "objects/collected", "<collected>");
1831 } else if (lookup_result == ObjectIdRing::kExpired) {
1832 PrintSentinel(js, "objects/expired", "<expired>");
1833 } else {
1834 PrintError(js, "Invalid 'targetId' value: no object with id '%s'",
1835 target_id);
1836 }
1837 return true;
1838 }
1839 if (obj.IsLibrary()) {
1840 const Library& lib = Library::Cast(obj);
1841 const Object& result = Object::Handle(lib.Evaluate(expr_str,
1842 Array::empty_array(),
1843 Array::empty_array()));
1844 result.PrintJSON(js, true);
1845 return true;
1846 }
1847 if (obj.IsClass()) {
1848 const Class& cls = Class::Cast(obj);
1849 const Object& result = Object::Handle(cls.Evaluate(expr_str,
1850 Array::empty_array(),
1851 Array::empty_array()));
1852 result.PrintJSON(js, true);
1853 return true;
1854 }
1855 if ((obj.IsInstance() || obj.IsNull()) &&
1856 !ContainsNonInstance(obj)) {
1857 // We don't use Instance::Cast here because it doesn't allow null.
1858 Instance& instance = Instance::Handle(isolate);
1859 instance ^= obj.raw();
1860 const Object& result =
1861 Object::Handle(instance.Evaluate(expr_str,
1862 Array::empty_array(),
1863 Array::empty_array()));
1864 result.PrintJSON(js, true);
1865 return true;
1866 }
1867 PrintError(js, "Invalid 'targetId' value: id '%s' does not correspond to a "
1868 "library, class, or instance", target_id);
1462 return true; 1869 return true;
1463 } 1870 }
1464 1871
1465 1872
1466 static bool HandleClassesDispatchers(Isolate* isolate, const Class& cls, 1873 static bool HandleClassesDispatchers(Isolate* isolate, const Class& cls,
1467 JSONStream* js) { 1874 JSONStream* js) {
1468 intptr_t id; 1875 intptr_t id;
1469 if (js->num_arguments() > 4) { 1876 if (js->num_arguments() > 4) {
1470 PrintError(js, "Command too long"); 1877 PrintError(js, "Command too long");
1471 return true; 1878 return true;
1472 } 1879 }
1473 if (!GetIntegerId(js->GetArgument(3), &id)) { 1880 if (!GetIntegerId(js->GetArgument(3), &id)) {
1474 PrintError(js, "Must specify collection object id: dispatchers/id"); 1881 PrintError(js, "Must specify collection object id: dispatchers/id");
1475 return true; 1882 return true;
1476 } 1883 }
1477 Function& func = Function::Handle(); 1884 Function& func = Function::Handle();
1478 func ^= cls.InvocationDispatcherFunctionFromIndex(id); 1885 func ^= cls.InvocationDispatcherFunctionFromIndex(id);
1479 if (func.IsNull()) { 1886 if (func.IsNull()) {
1480 PrintError(js, "Dispatcher %" Pd " not found", id); 1887 PrintError(js, "Dispatcher %" Pd " not found", id);
1481 return true; 1888 return true;
1482 } 1889 }
1483 func.PrintJSON(js, false); 1890 func.PrintJSON(js, false);
1484 return true; 1891 return true;
1485 } 1892 }
1486 1893
1487 1894
1488 static bool HandleClassesFunctionsCoverage(
1489 Isolate* isolate, const Function& func, JSONStream* js) {
1490 FunctionCoverageFilter filter(func);
1491 CodeCoverage::PrintJSON(isolate, js, &filter);
1492 return true;
1493 }
1494
1495
1496 static bool HandleFunctionSetSource( 1895 static bool HandleFunctionSetSource(
1497 Isolate* isolate, const Class& cls, const Function& func, JSONStream* js) { 1896 Isolate* isolate, const Class& cls, const Function& func, JSONStream* js) {
1498 if (js->LookupOption("source") == NULL) { 1897 if (js->LookupOption("source") == NULL) {
1499 PrintError(js, "set_source expects a 'source' option\n"); 1898 PrintError(js, "set_source expects a 'source' option\n");
1500 return true; 1899 return true;
1501 } 1900 }
1502 const String& source = 1901 const String& source =
1503 String::Handle(String::New(js->LookupOption("source"))); 1902 String::Handle(String::New(js->LookupOption("source")));
1504 const Object& result = Object::Handle( 1903 const Object& result = Object::Handle(
1505 Parser::ParseFunctionFromSource(cls, source)); 1904 Parser::ParseFunctionFromSource(cls, source));
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
1539 Function& func = Function::Handle(cls.LookupFunction(id)); 1938 Function& func = Function::Handle(cls.LookupFunction(id));
1540 if (func.IsNull()) { 1939 if (func.IsNull()) {
1541 PrintError(js, "Function %s not found", encoded_id); 1940 PrintError(js, "Function %s not found", encoded_id);
1542 return true; 1941 return true;
1543 } 1942 }
1544 if (js->num_arguments() == 4) { 1943 if (js->num_arguments() == 4) {
1545 func.PrintJSON(js, false); 1944 func.PrintJSON(js, false);
1546 return true; 1945 return true;
1547 } else { 1946 } else {
1548 const char* subcommand = js->GetArgument(4); 1947 const char* subcommand = js->GetArgument(4);
1549 if (strcmp(subcommand, "coverage") == 0) { 1948 if (strcmp(subcommand, "set_source") == 0) {
1550 return HandleClassesFunctionsCoverage(isolate, func, js);
1551 } else if (strcmp(subcommand, "set_source") == 0) {
1552 return HandleFunctionSetSource(isolate, cls, func, js); 1949 return HandleFunctionSetSource(isolate, cls, func, js);
1553 } else { 1950 } else {
1554 PrintError(js, "Invalid sub command %s", subcommand); 1951 PrintError(js, "Invalid sub command %s", subcommand);
1555 return true; 1952 return true;
1556 } 1953 }
1557 } 1954 }
1558 UNREACHABLE(); 1955 UNREACHABLE();
1559 return true; 1956 return true;
1560 } 1957 }
1561 1958
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
1610 jsobj.AddProperty("type", "TypeList"); 2007 jsobj.AddProperty("type", "TypeList");
1611 JSONArray members(&jsobj, "members"); 2008 JSONArray members(&jsobj, "members");
1612 const intptr_t num_types = cls.NumCanonicalTypes(); 2009 const intptr_t num_types = cls.NumCanonicalTypes();
1613 Type& type = Type::Handle(); 2010 Type& type = Type::Handle();
1614 for (intptr_t i = 0; i < num_types; i++) { 2011 for (intptr_t i = 0; i < num_types; i++) {
1615 type = cls.CanonicalTypeFromIndex(i); 2012 type = cls.CanonicalTypeFromIndex(i);
1616 members.AddValue(type); 2013 members.AddValue(type);
1617 } 2014 }
1618 return true; 2015 return true;
1619 } 2016 }
1620 ASSERT(js->num_arguments() >= 4); 2017 if (js->num_arguments() > 4) {
2018 PrintError(js, "Command too long");
2019 return true;
2020 }
2021 ASSERT(js->num_arguments() == 4);
1621 intptr_t id; 2022 intptr_t id;
1622 if (!GetIntegerId(js->GetArgument(3), &id)) { 2023 if (!GetIntegerId(js->GetArgument(3), &id)) {
1623 PrintError(js, "Must specify collection object id: types/id"); 2024 PrintError(js, "Must specify collection object id: types/id");
1624 return true; 2025 return true;
1625 } 2026 }
1626 Type& type = Type::Handle(); 2027 Type& type = Type::Handle();
1627 type ^= cls.CanonicalTypeFromIndex(id); 2028 type ^= cls.CanonicalTypeFromIndex(id);
1628 if (type.IsNull()) { 2029 if (type.IsNull()) {
1629 PrintError(js, "Canonical type %" Pd " not found", id); 2030 PrintError(js, "Canonical type %" Pd " not found", id);
1630 return true; 2031 return true;
1631 } 2032 }
1632 if (js->num_arguments() == 4) { 2033 type.PrintJSON(js, false);
1633 type.PrintJSON(js, false);
1634 return true;
1635 }
1636 return HandleInstanceCommands(isolate, &type, ObjectIdRing::kValid, js, 4);
1637 }
1638
1639
1640 static bool HandleClassesRetained(Isolate* isolate, const Class& cls,
1641 JSONStream* js) {
1642 if (js->num_arguments() != 3) {
1643 PrintError(js, "Command too long");
1644 return true;
1645 }
1646 ObjectGraph graph(isolate);
1647 intptr_t retained_size = graph.SizeRetainedByClass(cls.id());
1648 const Object& result = Object::Handle(Integer::New(retained_size));
1649 result.PrintJSON(js, true);
1650 return true; 2034 return true;
1651 } 2035 }
1652 2036
1653 2037
1654 class GetInstancesVisitor : public ObjectGraph::Visitor { 2038 class GetInstancesVisitor : public ObjectGraph::Visitor {
1655 public: 2039 public:
1656 GetInstancesVisitor(const Class& cls, const Array& storage) 2040 GetInstancesVisitor(const Class& cls, const Array& storage)
1657 : cls_(cls), storage_(storage), count_(0) {} 2041 : cls_(cls), storage_(storage), count_(0) {}
1658 2042
1659 virtual Direction VisitObject(ObjectGraph::StackIterator* it) { 2043 virtual Direction VisitObject(ObjectGraph::StackIterator* it) {
(...skipping 16 matching lines...) Expand all
1676 2060
1677 intptr_t count() const { return count_; } 2061 intptr_t count() const { return count_; }
1678 2062
1679 private: 2063 private:
1680 const Class& cls_; 2064 const Class& cls_;
1681 const Array& storage_; 2065 const Array& storage_;
1682 intptr_t count_; 2066 intptr_t count_;
1683 }; 2067 };
1684 2068
1685 2069
1686 static bool HandleClassesInstances(Isolate* isolate, const Class& cls, 2070 static bool HandleIsolateGetInstances(Isolate* isolate, JSONStream* js) {
1687 JSONStream* js) { 2071 const char* target_id = js->LookupOption("classId");
1688 if (js->num_arguments() != 3) { 2072 if (target_id == NULL) {
1689 PrintError(js, "Command too long"); 2073 PrintError(js, "Missing 'classId' option");
2074 return true;
2075 }
2076 const char* limit_cstr = js->LookupOption("limit");
2077 if (target_id == NULL) {
2078 PrintError(js, "Missing 'limit' option");
1690 return true; 2079 return true;
1691 } 2080 }
1692 intptr_t limit; 2081 intptr_t limit;
1693 if (!GetIntegerId(js->LookupOption("limit"), &limit)) { 2082 if (!GetIntegerId(js->LookupOption("limit"), &limit)) {
1694 PrintError(js, "instances expects a 'limit' option\n", 2083 PrintError(js, "Invalid 'limit' option: %s", limit_cstr);
1695 js->num_arguments());
1696 return true; 2084 return true;
1697 } 2085 }
2086 const Object& obj =
2087 Object::Handle(LookupHeapObject(isolate, target_id, NULL));
2088 if (obj.raw() == Object::sentinel().raw() ||
2089 !obj.IsClass()) {
2090 PrintError(js, "Invalid 'classId' value: no class with id '%s'", target_id);
2091 return true;
2092 }
2093 const Class& cls = Class::Cast(obj);
1698 Array& storage = Array::Handle(Array::New(limit)); 2094 Array& storage = Array::Handle(Array::New(limit));
1699 GetInstancesVisitor visitor(cls, storage); 2095 GetInstancesVisitor visitor(cls, storage);
1700 ObjectGraph graph(isolate); 2096 ObjectGraph graph(isolate);
1701 graph.IterateObjects(&visitor); 2097 graph.IterateObjects(&visitor);
1702 intptr_t count = visitor.count(); 2098 intptr_t count = visitor.count();
1703 if (count < limit) { 2099 if (count < limit) {
1704 // Truncate the list using utility method for GrowableObjectArray. 2100 // Truncate the list using utility method for GrowableObjectArray.
1705 GrowableObjectArray& wrapper = GrowableObjectArray::Handle( 2101 GrowableObjectArray& wrapper = GrowableObjectArray::Handle(
1706 GrowableObjectArray::New(storage)); 2102 GrowableObjectArray::New(storage));
1707 wrapper.SetLength(count); 2103 wrapper.SetLength(count);
1708 storage = Array::MakeArray(wrapper); 2104 storage = Array::MakeArray(wrapper);
1709 } 2105 }
1710 JSONObject jsobj(js); 2106 JSONObject jsobj(js);
1711 jsobj.AddProperty("type", "InstanceSet"); 2107 jsobj.AddProperty("type", "InstanceSet");
1712 jsobj.AddProperty("id", "instance_set"); 2108 jsobj.AddProperty("id", "instance_set");
1713 jsobj.AddProperty("totalCount", count); 2109 jsobj.AddProperty("totalCount", count);
1714 jsobj.AddProperty("sampleCount", storage.Length()); 2110 jsobj.AddProperty("sampleCount", storage.Length());
1715 jsobj.AddProperty("sample", storage); 2111 jsobj.AddProperty("sample", storage);
1716 return true; 2112 return true;
1717 } 2113 }
1718 2114
1719 2115
1720 static bool HandleClassesCoverage(Isolate* isolate,
1721 const Class& cls,
1722 JSONStream* stream) {
1723 ClassCoverageFilter cf(cls);
1724 CodeCoverage::PrintJSON(isolate, stream, &cf);
1725 return true;
1726 }
1727
1728
1729 static bool HandleClasses(Isolate* isolate, JSONStream* js) { 2116 static bool HandleClasses(Isolate* isolate, JSONStream* js) {
1730 if (js->num_arguments() == 1) { 2117 if (js->num_arguments() == 1) {
1731 ClassTable* table = isolate->class_table(); 2118 ClassTable* table = isolate->class_table();
1732 JSONObject jsobj(js); 2119 JSONObject jsobj(js);
1733 table->PrintToJSONObject(&jsobj); 2120 table->PrintToJSONObject(&jsobj);
1734 return true; 2121 return true;
1735 } 2122 }
1736 ASSERT(js->num_arguments() >= 2); 2123 ASSERT(js->num_arguments() >= 2);
1737 intptr_t id; 2124 intptr_t id;
1738 if (!GetIntegerId(js->GetArgument(1), &id)) { 2125 if (!GetIntegerId(js->GetArgument(1), &id)) {
1739 PrintError(js, "Must specify collection object id: /classes/id"); 2126 PrintError(js, "Must specify collection object id: /classes/id");
1740 return true; 2127 return true;
1741 } 2128 }
1742 ClassTable* table = isolate->class_table(); 2129 ClassTable* table = isolate->class_table();
1743 if (!table->IsValidIndex(id)) { 2130 if (!table->IsValidIndex(id)) {
1744 PrintError(js, "%" Pd " is not a valid class id.", id); 2131 PrintError(js, "%" Pd " is not a valid class id.", id);
1745 return true; 2132 return true;
1746 } 2133 }
1747 Class& cls = Class::Handle(table->At(id)); 2134 Class& cls = Class::Handle(table->At(id));
1748 if (js->num_arguments() == 2) { 2135 if (js->num_arguments() == 2) {
1749 cls.PrintJSON(js, false); 2136 cls.PrintJSON(js, false);
1750 return true; 2137 return true;
1751 } else if (js->num_arguments() >= 3) { 2138 } else if (js->num_arguments() >= 3) {
1752 const char* second = js->GetArgument(2); 2139 const char* second = js->GetArgument(2);
1753 if (strcmp(second, "eval") == 0) { 2140 if (strcmp(second, "closures") == 0) {
1754 return HandleClassesEval(isolate, cls, js);
1755 } else if (strcmp(second, "closures") == 0) {
1756 return HandleClassesClosures(isolate, cls, js); 2141 return HandleClassesClosures(isolate, cls, js);
1757 } else if (strcmp(second, "fields") == 0) { 2142 } else if (strcmp(second, "fields") == 0) {
1758 return HandleClassesFields(isolate, cls, js); 2143 return HandleClassesFields(isolate, cls, js);
1759 } else if (strcmp(second, "functions") == 0) { 2144 } else if (strcmp(second, "functions") == 0) {
1760 return HandleClassesFunctions(isolate, cls, js); 2145 return HandleClassesFunctions(isolate, cls, js);
1761 } else if (strcmp(second, "implicit_closures") == 0) { 2146 } else if (strcmp(second, "implicit_closures") == 0) {
1762 return HandleClassesImplicitClosures(isolate, cls, js); 2147 return HandleClassesImplicitClosures(isolate, cls, js);
1763 } else if (strcmp(second, "dispatchers") == 0) { 2148 } else if (strcmp(second, "dispatchers") == 0) {
1764 return HandleClassesDispatchers(isolate, cls, js); 2149 return HandleClassesDispatchers(isolate, cls, js);
1765 } else if (strcmp(second, "types") == 0) { 2150 } else if (strcmp(second, "types") == 0) {
1766 return HandleClassesTypes(isolate, cls, js); 2151 return HandleClassesTypes(isolate, cls, js);
1767 } else if (strcmp(second, "retained") == 0) {
1768 return HandleClassesRetained(isolate, cls, js);
1769 } else if (strcmp(second, "instances") == 0) {
1770 return HandleClassesInstances(isolate, cls, js);
1771 } else if (strcmp(second, "coverage") == 0) {
1772 return HandleClassesCoverage(isolate, cls, js);
1773 } else { 2152 } else {
1774 PrintError(js, "Invalid sub collection %s", second); 2153 PrintError(js, "Invalid sub collection %s", second);
1775 return true; 2154 return true;
1776 } 2155 }
1777 } 2156 }
1778 UNREACHABLE(); 2157 UNREACHABLE();
1779 return true; 2158 return true;
1780 } 2159 }
1781 2160
1782 2161
1783 static bool HandleLibrariesEval(Isolate* isolate, const Library& lib, 2162 static bool HandleIsolateGetCoverage(Isolate* isolate, JSONStream* js) {
1784 JSONStream* js) { 2163 if (!js->HasOption("targetId")) {
1785 if (js->num_arguments() > 3) { 2164 CodeCoverage::PrintJSON(isolate, js, NULL);
1786 PrintError(js, "Command too long");
1787 return true; 2165 return true;
1788 } 2166 }
1789 const char* expr = js->LookupOption("expr"); 2167 const char* target_id = js->LookupOption("targetId");
1790 if (expr == NULL) { 2168 Object& obj = Object::Handle(LookupHeapObject(isolate, target_id, NULL));
1791 PrintError(js, "eval expects an 'expr' option\n", 2169 if (obj.raw() == Object::sentinel().raw()) {
1792 js->num_arguments()); 2170 PrintError(js, "Invalid 'targetId' value: no object with id '%s'",
2171 target_id);
1793 return true; 2172 return true;
1794 } 2173 }
1795 const String& expr_str = String::Handle(isolate, String::New(expr)); 2174 if (obj.IsScript()) {
1796 const Object& result = Object::Handle(lib.Evaluate(expr_str, 2175 ScriptCoverageFilter sf(Script::Cast(obj));
1797 Array::empty_array(), 2176 CodeCoverage::PrintJSON(isolate, js, &sf);
1798 Array::empty_array())); 2177 return true;
1799 result.PrintJSON(js, true); 2178 }
2179 if (obj.IsLibrary()) {
2180 LibraryCoverageFilter lf(Library::Cast(obj));
2181 CodeCoverage::PrintJSON(isolate, js, &lf);
2182 return true;
2183 }
2184 if (obj.IsClass()) {
2185 ClassCoverageFilter cf(Class::Cast(obj));
2186 CodeCoverage::PrintJSON(isolate, js, &cf);
2187 return true;
2188 }
2189 if (obj.IsFunction()) {
2190 FunctionCoverageFilter ff(Function::Cast(obj));
2191 CodeCoverage::PrintJSON(isolate, js, &ff);
2192 return true;
2193 }
2194 PrintError(js, "Invalid 'targetId' value: id '%s' does not correspond to a "
2195 "script, library, class, or function", target_id);
1800 return true; 2196 return true;
1801 } 2197 }
1802 2198
1803 2199
1804 static bool HandleLibrariesScriptsCoverage( 2200 static bool HandleIsolateAddBreakpoint(Isolate* isolate, JSONStream* js) {
1805 Isolate* isolate, const Script& script, JSONStream* js) {
1806 ScriptCoverageFilter sf(script);
1807 CodeCoverage::PrintJSON(isolate, js, &sf);
1808 return true;
1809 }
1810
1811
1812 static bool HandleLibrariesScriptsSetBreakpoint(
1813 Isolate* isolate, const Script& script, JSONStream* js) {
1814 if (!js->HasOption("line")) { 2201 if (!js->HasOption("line")) {
1815 PrintError(js, "Missing 'line' option"); 2202 PrintError(js, "Missing 'line' option");
1816 return true; 2203 return true;
1817 } 2204 }
1818 const char* line_option = js->LookupOption("line"); 2205 const char* line_option = js->LookupOption("line");
1819 intptr_t line = -1; 2206 intptr_t line = -1;
1820 if (!GetIntegerId(line_option, &line)) { 2207 if (!GetIntegerId(line_option, &line)) {
1821 PrintError(js, "Invalid 'line' value: %s", line_option); 2208 PrintError(js, "Invalid 'line' value: %s is not an integer", line_option);
1822 return true; 2209 return true;
1823 } 2210 }
2211 const char* script_id = js->LookupOption("script");
2212 Object& obj = Object::Handle(LookupHeapObject(isolate, script_id, NULL));
2213 if (obj.raw() == Object::sentinel().raw() || !obj.IsScript()) {
2214 PrintError(js, "Invalid 'script' value: no script with id '%s'", script_id);
2215 return true;
2216 }
2217 const Script& script = Script::Cast(obj);
1824 const String& script_url = String::Handle(script.url()); 2218 const String& script_url = String::Handle(script.url());
1825 SourceBreakpoint* bpt = 2219 SourceBreakpoint* bpt =
1826 isolate->debugger()->SetBreakpointAtLine(script_url, line); 2220 isolate->debugger()->SetBreakpointAtLine(script_url, line);
1827 if (bpt == NULL) { 2221 if (bpt == NULL) {
1828 PrintError(js, "Unable to set breakpoint at line %s", line_option); 2222 PrintError(js, "Unable to set breakpoint at line %s", line_option);
1829 return true; 2223 return true;
1830 } 2224 }
1831 bpt->PrintJSON(js); 2225 bpt->PrintJSON(js);
1832 return true; 2226 return true;
1833 } 2227 }
1834 2228
1835 2229
2230 static bool HandleIsolateRemoveBreakpoint(Isolate* isolate, JSONStream* js) {
2231 if (!js->HasOption("breakpointId")) {
2232 PrintError(js, "Missing 'breakpointId' option");
2233 return true;
2234 }
2235 const char* bpt_id = js->LookupOption("breakpointId");
2236 SourceBreakpoint* bpt = LookupBreakpoint(isolate, bpt_id);
2237 if (bpt == NULL) {
2238 fprintf(stderr, "ERROR1");
2239 PrintError(js, "Invalid 'breakpointId' value: no breakpoint with id '%s'",
2240 bpt_id);
2241 return true;
2242 }
2243 isolate->debugger()->RemoveBreakpoint(bpt->id());
2244
2245 fprintf(stderr, "SUCCESS");
2246 // TODO(turnidge): Consider whether the 'Success' type is proper.
2247 JSONObject jsobj(js);
2248 jsobj.AddProperty("type", "Success");
2249 jsobj.AddProperty("id", "");
2250 return true;
2251 }
2252
2253
1836 static bool HandleLibrariesScripts(Isolate* isolate, 2254 static bool HandleLibrariesScripts(Isolate* isolate,
1837 const Library& lib, 2255 const Library& lib,
1838 JSONStream* js) { 2256 JSONStream* js) {
1839 if (js->num_arguments() > 5) { 2257 if (js->num_arguments() > 5) {
1840 PrintError(js, "Command too long"); 2258 PrintError(js, "Command too long");
1841 return true; 2259 return true;
1842 } else if (js->num_arguments() < 4) { 2260 } else if (js->num_arguments() < 4) {
1843 PrintError(js, "Must specify collection object id: scripts/id"); 2261 PrintError(js, "Must specify collection object id: scripts/id");
1844 return true; 2262 return true;
1845 } 2263 }
(...skipping 11 matching lines...) Expand all
1857 ASSERT(!script.IsNull()); 2275 ASSERT(!script.IsNull());
1858 script_url ^= script.url(); 2276 script_url ^= script.url();
1859 if (script_url.Equals(requested_url)) { 2277 if (script_url.Equals(requested_url)) {
1860 break; 2278 break;
1861 } 2279 }
1862 } 2280 }
1863 if (i == loaded_scripts.Length()) { 2281 if (i == loaded_scripts.Length()) {
1864 PrintError(js, "Script %s not found", requested_url.ToCString()); 2282 PrintError(js, "Script %s not found", requested_url.ToCString());
1865 return true; 2283 return true;
1866 } 2284 }
1867 if (js->num_arguments() == 4) { 2285 if (js->num_arguments() > 4) {
1868 script.PrintJSON(js, false); 2286 PrintError(js, "Command too long");
1869 return true; 2287 return true;
1870 } else {
1871 const char* subcollection = js->GetArgument(4);
1872 if (strcmp(subcollection, "coverage") == 0) {
1873 return HandleLibrariesScriptsCoverage(isolate, script, js);
1874 } else if (strcmp(subcollection, "setBreakpoint") == 0) {
1875 return HandleLibrariesScriptsSetBreakpoint(isolate, script, js);
1876 } else {
1877 PrintError(js, "Invalid sub collection %s", subcollection);
1878 return true;
1879 }
1880 } 2288 }
1881 UNREACHABLE(); 2289 script.PrintJSON(js, false);
1882 return true; 2290 return true;
1883 } 2291 }
1884 2292
1885
1886 static bool HandleLibrariesCoverage(Isolate* isolate,
1887 const Library& lib,
1888 JSONStream* js) {
1889 LibraryCoverageFilter lf(lib);
1890 CodeCoverage::PrintJSON(isolate, js, &lf);
1891 return true;
1892 }
1893
1894 2293
1895 static bool HandleLibraries(Isolate* isolate, JSONStream* js) { 2294 static bool HandleLibraries(Isolate* isolate, JSONStream* js) {
1896 // TODO(johnmccutchan): Support fields and functions on libraries. 2295 // TODO(johnmccutchan): Support fields and functions on libraries.
1897 REQUIRE_COLLECTION_ID("libraries"); 2296 REQUIRE_COLLECTION_ID("libraries");
1898 const GrowableObjectArray& libs = 2297 const GrowableObjectArray& libs =
1899 GrowableObjectArray::Handle(isolate->object_store()->libraries()); 2298 GrowableObjectArray::Handle(isolate->object_store()->libraries());
1900 ASSERT(!libs.IsNull()); 2299 ASSERT(!libs.IsNull());
1901 intptr_t id = 0; 2300 intptr_t id = 0;
1902 CHECK_COLLECTION_ID_BOUNDS("libraries", libs.Length(), js->GetArgument(1), 2301 CHECK_COLLECTION_ID_BOUNDS("libraries", libs.Length(), js->GetArgument(1),
1903 id, js); 2302 id, js);
1904 Library& lib = Library::Handle(); 2303 Library& lib = Library::Handle();
1905 lib ^= libs.At(id); 2304 lib ^= libs.At(id);
1906 ASSERT(!lib.IsNull()); 2305 ASSERT(!lib.IsNull());
1907 if (js->num_arguments() == 2) { 2306 if (js->num_arguments() == 2) {
1908 lib.PrintJSON(js, false); 2307 lib.PrintJSON(js, false);
1909 return true; 2308 return true;
1910 } else if (js->num_arguments() >= 3) { 2309 } else if (js->num_arguments() >= 3) {
1911 const char* second = js->GetArgument(2); 2310 const char* second = js->GetArgument(2);
1912 if (strcmp(second, "eval") == 0) { 2311 if (strcmp(second, "scripts") == 0) {
1913 return HandleLibrariesEval(isolate, lib, js);
1914 } else if (strcmp(second, "scripts") == 0) {
1915 return HandleLibrariesScripts(isolate, lib, js); 2312 return HandleLibrariesScripts(isolate, lib, js);
1916 } else if (strcmp(second, "coverage") == 0) {
1917 return HandleLibrariesCoverage(isolate, lib, js);
1918 } else { 2313 } else {
1919 PrintError(js, "Invalid sub collection %s", second); 2314 PrintError(js, "Invalid sub collection %s", second);
1920 return true; 2315 return true;
1921 } 2316 }
1922 } 2317 }
1923 UNREACHABLE(); 2318 UNREACHABLE();
1924 return true; 2319 return true;
1925 } 2320 }
1926 2321
1927 2322
1928 static void PrintSentinel(JSONStream* js,
1929 const char* id,
1930 const char* preview) {
1931 JSONObject jsobj(js);
1932 jsobj.AddProperty("type", "Sentinel");
1933 jsobj.AddProperty("id", id);
1934 jsobj.AddProperty("valueAsString", preview);
1935 }
1936
1937
1938 static RawObject* LookupObjectId(Isolate* isolate,
1939 const char* arg,
1940 ObjectIdRing::LookupResult* kind) {
1941 *kind = ObjectIdRing::kValid;
1942 if (strncmp(arg, "int-", 4) == 0) {
1943 arg += 4;
1944 int64_t value = 0;
1945 if (!OS::StringToInt64(arg, &value) ||
1946 !Smi::IsValid(value)) {
1947 *kind = ObjectIdRing::kInvalid;
1948 return Object::null();
1949 }
1950 const Integer& obj =
1951 Integer::Handle(isolate, Smi::New(static_cast<intptr_t>(value)));
1952 return obj.raw();
1953 } else if (strcmp(arg, "bool-true") == 0) {
1954 return Bool::True().raw();
1955 } else if (strcmp(arg, "bool-false") == 0) {
1956 return Bool::False().raw();
1957 } else if (strcmp(arg, "null") == 0) {
1958 return Object::null();
1959 } else if (strcmp(arg, "not-initialized") == 0) {
1960 return Object::sentinel().raw();
1961 } else if (strcmp(arg, "being-initialized") == 0) {
1962 return Object::transition_sentinel().raw();
1963 }
1964
1965 ObjectIdRing* ring = isolate->object_id_ring();
1966 ASSERT(ring != NULL);
1967 intptr_t id = -1;
1968 if (!GetIntegerId(arg, &id)) {
1969 *kind = ObjectIdRing::kInvalid;
1970 return Object::null();
1971 }
1972 return ring->GetObjectForId(id, kind);
1973 }
1974
1975
1976 static RawClass* GetMetricsClass(Isolate* isolate) { 2323 static RawClass* GetMetricsClass(Isolate* isolate) {
1977 const Library& prof_lib = 2324 const Library& prof_lib =
1978 Library::Handle(isolate, Library::ProfilerLibrary()); 2325 Library::Handle(isolate, Library::ProfilerLibrary());
1979 ASSERT(!prof_lib.IsNull()); 2326 ASSERT(!prof_lib.IsNull());
1980 const String& metrics_cls_name = 2327 const String& metrics_cls_name =
1981 String::Handle(isolate, String::New("Metrics")); 2328 String::Handle(isolate, String::New("Metrics"));
1982 ASSERT(!metrics_cls_name.IsNull()); 2329 ASSERT(!metrics_cls_name.IsNull());
1983 const Class& metrics_cls = 2330 const Class& metrics_cls =
1984 Class::Handle(isolate, prof_lib.LookupClass(metrics_cls_name)); 2331 Class::Handle(isolate, prof_lib.LookupClass(metrics_cls_name));
1985 ASSERT(!metrics_cls.IsNull()); 2332 ASSERT(!metrics_cls.IsNull());
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
2088 if (js->num_arguments() > 2) { 2435 if (js->num_arguments() > 2) {
2089 PrintError(js, "Command too long"); 2436 PrintError(js, "Command too long");
2090 return true; 2437 return true;
2091 } 2438 }
2092 return HandleMetric(isolate, js, arg); 2439 return HandleMetric(isolate, js, arg);
2093 } 2440 }
2094 2441
2095 2442
2096 static bool HandleObjects(Isolate* isolate, JSONStream* js) { 2443 static bool HandleObjects(Isolate* isolate, JSONStream* js) {
2097 REQUIRE_COLLECTION_ID("objects"); 2444 REQUIRE_COLLECTION_ID("objects");
2098 if (js->num_arguments() < 2) { 2445 if (js->num_arguments() != 2) {
2099 PrintError(js, "expected at least 2 arguments but found %" Pd "\n", 2446 PrintError(js, "expected at least 2 arguments but found %" Pd "\n",
2100 js->num_arguments()); 2447 js->num_arguments());
2101 return true; 2448 return true;
2102 } 2449 }
2103 const char* arg = js->GetArgument(1); 2450 const char* arg = js->GetArgument(1);
2104 2451
2105 // Handle special non-objects first. 2452 // Handle special non-objects first.
2106 if (strcmp(arg, "optimized-out") == 0) { 2453 if (strcmp(arg, "optimized-out") == 0) {
2107 if (js->num_arguments() > 2) { 2454 if (js->num_arguments() > 2) {
2108 PrintError(js, "expected at most 2 arguments but found %" Pd "\n", 2455 PrintError(js, "expected at most 2 arguments but found %" Pd "\n",
(...skipping 23 matching lines...) Expand all
2132 } 2479 }
2133 2480
2134 // Lookup the object. 2481 // Lookup the object.
2135 Object& obj = Object::Handle(isolate); 2482 Object& obj = Object::Handle(isolate);
2136 ObjectIdRing::LookupResult kind = ObjectIdRing::kInvalid; 2483 ObjectIdRing::LookupResult kind = ObjectIdRing::kInvalid;
2137 obj = LookupObjectId(isolate, arg, &kind); 2484 obj = LookupObjectId(isolate, arg, &kind);
2138 if (kind == ObjectIdRing::kInvalid) { 2485 if (kind == ObjectIdRing::kInvalid) {
2139 PrintError(js, "unrecognized object id '%s'", arg); 2486 PrintError(js, "unrecognized object id '%s'", arg);
2140 return true; 2487 return true;
2141 } 2488 }
2142 if (js->num_arguments() == 2) { 2489
2143 // Print. 2490 // Print.
2144 if (kind == ObjectIdRing::kCollected) { 2491 if (kind == ObjectIdRing::kCollected) {
2145 // The object has been collected by the gc. 2492 // The object has been collected by the gc.
2146 PrintSentinel(js, "objects/collected", "<collected>"); 2493 PrintSentinel(js, "objects/collected", "<collected>");
2147 return true; 2494 return true;
2148 } else if (kind == ObjectIdRing::kExpired) { 2495 } else if (kind == ObjectIdRing::kExpired) {
2149 // The object id has expired. 2496 // The object id has expired.
2150 PrintSentinel(js, "objects/expired", "<expired>"); 2497 PrintSentinel(js, "objects/expired", "<expired>");
2151 return true;
2152 }
2153 obj.PrintJSON(js, false);
2154 return true; 2498 return true;
2155 } 2499 }
2156 return HandleInstanceCommands(isolate, &obj, kind, js, 2); 2500 obj.PrintJSON(js, false);
2501 return true;
2157 } 2502 }
2158 2503
2159 2504
2160 static bool HandleScriptsEnumerate(Isolate* isolate, JSONStream* js) { 2505 static bool HandleScriptsEnumerate(Isolate* isolate, JSONStream* js) {
2161 JSONObject jsobj(js); 2506 JSONObject jsobj(js);
2162 jsobj.AddProperty("type", "ScriptList"); 2507 jsobj.AddProperty("type", "ScriptList");
2163 jsobj.AddProperty("id", "scripts"); 2508 jsobj.AddProperty("id", "scripts");
2164 JSONArray members(&jsobj, "members"); 2509 JSONArray members(&jsobj, "members");
2165 const GrowableObjectArray& libs = 2510 const GrowableObjectArray& libs =
2166 GrowableObjectArray::Handle(isolate->object_store()->libraries()); 2511 GrowableObjectArray::Handle(isolate->object_store()->libraries());
(...skipping 19 matching lines...) Expand all
2186 static bool HandleScripts(Isolate* isolate, JSONStream* js) { 2531 static bool HandleScripts(Isolate* isolate, JSONStream* js) {
2187 if (js->num_arguments() == 1) { 2532 if (js->num_arguments() == 1) {
2188 // Enumerate all scripts. 2533 // Enumerate all scripts.
2189 return HandleScriptsEnumerate(isolate, js); 2534 return HandleScriptsEnumerate(isolate, js);
2190 } 2535 }
2191 PrintError(js, "Command too long"); 2536 PrintError(js, "Command too long");
2192 return true; 2537 return true;
2193 } 2538 }
2194 2539
2195 2540
2196 static bool HandleDebugResume(Isolate* isolate, 2541 static bool HandleIsolateResume(Isolate* isolate, JSONStream* js) {
2197 const char* step_option, 2542 const char* step_option = js->LookupOption("step");
2198 JSONStream* js) {
2199 if (isolate->message_handler()->paused_on_start()) { 2543 if (isolate->message_handler()->paused_on_start()) {
2200 isolate->message_handler()->set_pause_on_start(false); 2544 isolate->message_handler()->set_pause_on_start(false);
2201 JSONObject jsobj(js); 2545 JSONObject jsobj(js);
2202 jsobj.AddProperty("type", "Success"); 2546 jsobj.AddProperty("type", "Success");
2203 jsobj.AddProperty("id", ""); 2547 jsobj.AddProperty("id", "");
2204 return true; 2548 return true;
2205 } 2549 }
2206 if (isolate->message_handler()->paused_on_exit()) { 2550 if (isolate->message_handler()->paused_on_exit()) {
2207 isolate->message_handler()->set_pause_on_exit(false); 2551 isolate->message_handler()->set_pause_on_exit(false);
2208 JSONObject jsobj(js); 2552 JSONObject jsobj(js);
(...skipping 19 matching lines...) Expand all
2228 jsobj.AddProperty("type", "Success"); 2572 jsobj.AddProperty("type", "Success");
2229 jsobj.AddProperty("id", ""); 2573 jsobj.AddProperty("id", "");
2230 return true; 2574 return true;
2231 } 2575 }
2232 2576
2233 PrintError(js, "VM was not paused"); 2577 PrintError(js, "VM was not paused");
2234 return true; 2578 return true;
2235 } 2579 }
2236 2580
2237 2581
2238 static bool HandleDebug(Isolate* isolate, JSONStream* js) { 2582 static bool HandleIsolateGetBreakpoints(Isolate* isolate, JSONStream* js) {
2239 if (js->num_arguments() == 1) { 2583 JSONObject jsobj(js);
2240 PrintError(js, "Must specify a subcommand"); 2584 jsobj.AddProperty("type", "BreakpointList");
2241 return true; 2585 JSONArray jsarr(&jsobj, "breakpoints");
2242 } 2586 isolate->debugger()->PrintBreakpointsToJSONArray(&jsarr);
2243 const char* command = js->GetArgument(1); 2587 return true;
2244 if (strcmp(command, "breakpoints") == 0) {
2245 if (js->num_arguments() == 2) {
2246 // Print breakpoint list.
2247 JSONObject jsobj(js);
2248 jsobj.AddProperty("type", "BreakpointList");
2249 jsobj.AddProperty("id", "debug/breakpoints");
2250 JSONArray jsarr(&jsobj, "breakpoints");
2251 isolate->debugger()->PrintBreakpointsToJSONArray(&jsarr);
2252 return true;
2253 } else {
2254 intptr_t id = 0;
2255 SourceBreakpoint* bpt = NULL;
2256 if (GetIntegerId(js->GetArgument(2), &id)) {
2257 bpt = isolate->debugger()->GetBreakpointById(id);
2258 }
2259 if (bpt == NULL) {
2260 PrintError(js, "Unrecognized breakpoint id: %s", js->GetArgument(2));
2261 return true;
2262 }
2263 if (js->num_arguments() == 3) {
2264 // Print individual breakpoint.
2265 bpt->PrintJSON(js);
2266 return true;
2267 } else if (js->num_arguments() == 4) {
2268 const char* sub_command = js->GetArgument(3);
2269 if (strcmp(sub_command, "clear") == 0) {
2270 // Clear this breakpoint.
2271 isolate->debugger()->RemoveBreakpoint(id);
2272
2273 JSONObject jsobj(js);
2274 jsobj.AddProperty("type", "Success");
2275 jsobj.AddProperty("id", "");
2276 return true;
2277 } else {
2278 PrintError(js, "Unrecognized subcommand: %s", sub_command);
2279 return true;
2280 }
2281 } else {
2282 PrintError(js, "Command too long");
2283 return true;
2284 }
2285 }
2286 } else if (strcmp(command, "pause") == 0) {
2287 if (js->num_arguments() == 2) {
2288 // TODO(turnidge): Don't double-interrupt the isolate here.
2289 isolate->ScheduleInterrupts(Isolate::kApiInterrupt);
2290 JSONObject jsobj(js);
2291 jsobj.AddProperty("type", "Success");
2292 jsobj.AddProperty("id", "");
2293 return true;
2294 } else {
2295 PrintError(js, "Command too long");
2296 return true;
2297 }
2298 } else if (strcmp(command, "resume") == 0) {
2299 if (js->num_arguments() == 2) {
2300 const char* step_option = js->LookupOption("step");
2301 return HandleDebugResume(isolate, step_option, js);
2302 } else {
2303 PrintError(js, "Command too long");
2304 return true;
2305 }
2306 } else {
2307 PrintError(js, "Unrecognized subcommand '%s'", js->GetArgument(1));
2308 return true;
2309 }
2310 } 2588 }
2311 2589
2312 2590
2591 static bool HandleIsolatePause(Isolate* isolate, JSONStream* js) {
2592 // TODO(turnidge): Don't double-interrupt the isolate here.
2593 isolate->ScheduleInterrupts(Isolate::kApiInterrupt);
2594 JSONObject jsobj(js);
2595 jsobj.AddProperty("type", "Success");
2596 jsobj.AddProperty("id", "");
2597 return true;
2598 }
2599
2600
2313 static bool HandleNullCode(uintptr_t pc, JSONStream* js) { 2601 static bool HandleNullCode(uintptr_t pc, JSONStream* js) {
2314 // TODO(turnidge): Consider adding/using Object::null_code() for 2602 // TODO(turnidge): Consider adding/using Object::null_code() for
2315 // consistent "type". 2603 // consistent "type".
2316 Object::null_object().PrintJSON(js, false); 2604 Object::null_object().PrintJSON(js, false);
2317 return true; 2605 return true;
2318 } 2606 }
2319 2607
2320 2608
2321 static bool HandleCode(Isolate* isolate, JSONStream* js) { 2609 static bool HandleCode(Isolate* isolate, JSONStream* js) {
2322 REQUIRE_COLLECTION_ID("code"); 2610 REQUIRE_COLLECTION_ID("code");
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
2366 Code& code = Code::Handle(Code::FindCode(pc, timestamp)); 2654 Code& code = Code::Handle(Code::FindCode(pc, timestamp));
2367 if (!code.IsNull()) { 2655 if (!code.IsNull()) {
2368 code.PrintJSON(js, false); 2656 code.PrintJSON(js, false);
2369 return true; 2657 return true;
2370 } 2658 }
2371 PrintError(js, "Could not find code with id: %s", command); 2659 PrintError(js, "Could not find code with id: %s", command);
2372 return true; 2660 return true;
2373 } 2661 }
2374 2662
2375 2663
2376 static bool HandleProfile(Isolate* isolate, JSONStream* js) { 2664 static bool HandleIsolateGetTagProfile(Isolate* isolate, JSONStream* js) {
2377 if (js->num_arguments() == 2) { 2665 JSONObject miniProfile(js);
2378 const char* sub_command = js->GetArgument(1); 2666 miniProfile.AddProperty("type", "TagProfile");
2379 if (!strcmp(sub_command, "tag")) { 2667 miniProfile.AddProperty("id", "profile/tag");
2380 { 2668 isolate->vm_tag_counters()->PrintToJSONObject(&miniProfile);
2381 JSONObject miniProfile(js); 2669 return true;
2382 miniProfile.AddProperty("type", "TagProfile"); 2670 }
2383 miniProfile.AddProperty("id", "profile/tag"); 2671
2384 isolate->vm_tag_counters()->PrintToJSONObject(&miniProfile); 2672 static bool HandleIsolateGetCpuProfile(Isolate* isolate, JSONStream* js) {
2385 }
2386 return true;
2387 } else {
2388 PrintError(js, "Unrecognized subcommand '%s'", sub_command);
2389 return true;
2390 }
2391 }
2392 // A full profile includes disassembly of all Dart code objects. 2673 // A full profile includes disassembly of all Dart code objects.
2393 // TODO(johnmccutchan): Add sub command to trigger full code dump. 2674 // TODO(johnmccutchan): Add sub command to trigger full code dump.
2394 bool full_profile = false; 2675 bool full_profile = false;
2395 const char* tags_option = js->LookupOption("tags"); 2676 const char* tags_option = js->LookupOption("tags");
2396 Profiler::TagOrder tag_order = Profiler::kUserVM; 2677 Profiler::TagOrder tag_order = Profiler::kUserVM;
2397 if (js->HasOption("tags")) { 2678 if (js->HasOption("tags")) {
2398 if (js->OptionIs("tags", "hide")) { 2679 if (js->OptionIs("tags", "None")) {
2399 tag_order = Profiler::kNoTags; 2680 tag_order = Profiler::kNoTags;
2400 } else if (js->OptionIs("tags", "uv")) { 2681 } else if (js->OptionIs("tags", "UserVM")) {
2401 tag_order = Profiler::kUserVM; 2682 tag_order = Profiler::kUserVM;
2402 } else if (js->OptionIs("tags", "u")) { 2683 } else if (js->OptionIs("tags", "UserOnly")) {
2403 tag_order = Profiler::kUser; 2684 tag_order = Profiler::kUser;
2404 } else if (js->OptionIs("tags", "vu")) { 2685 } else if (js->OptionIs("tags", "VMUser")) {
2405 tag_order = Profiler::kVMUser; 2686 tag_order = Profiler::kVMUser;
2406 } else if (js->OptionIs("tags", "v")) { 2687 } else if (js->OptionIs("tags", "VMOnly")) {
2407 tag_order = Profiler::kVM; 2688 tag_order = Profiler::kVM;
2408 } else { 2689 } else {
2409 PrintError(js, "Invalid tags option value: %s\n", tags_option); 2690 PrintError(js, "Invalid tags option value: %s\n", tags_option);
2410 return true; 2691 return true;
2411 } 2692 }
2412 } 2693 }
2413 Profiler::PrintJSON(isolate, js, full_profile, tag_order); 2694 Profiler::PrintJSON(isolate, js, full_profile, tag_order);
2414 return true; 2695 return true;
2415 } 2696 }
2416 2697
2417 static bool HandleCoverage(Isolate* isolate, JSONStream* js) {
2418 CodeCoverage::PrintJSON(isolate, js, NULL);
2419 return true;
2420 }
2421
2422 2698
2423 static bool HandleAllocationProfile(Isolate* isolate, JSONStream* js) { 2699 static bool HandleIsolateGetAllocationProfile(Isolate* isolate,
2700 JSONStream* js) {
2424 bool should_reset_accumulator = false; 2701 bool should_reset_accumulator = false;
2425 bool should_collect = false; 2702 bool should_collect = false;
2426 if (js->num_arguments() != 1) {
2427 PrintError(js, "Command too long");
2428 return true;
2429 }
2430 if (js->HasOption("reset")) { 2703 if (js->HasOption("reset")) {
2431 if (js->OptionIs("reset", "true")) { 2704 if (js->OptionIs("reset", "true")) {
2432 should_reset_accumulator = true; 2705 should_reset_accumulator = true;
2433 } else { 2706 } else {
2434 PrintError(js, "Unrecognized reset option '%s'", 2707 PrintError(js, "Unrecognized reset option '%s'",
2435 js->LookupOption("reset")); 2708 js->LookupOption("reset"));
2436 return true; 2709 return true;
2437 } 2710 }
2438 } 2711 }
2439 if (js->HasOption("gc")) { 2712 if (js->HasOption("gc")) {
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
2502 if ((id < 0) || (id >= table_size) || (table.At(id) == Object::null())) { 2775 if ((id < 0) || (id >= table_size) || (table.At(id) == Object::null())) {
2503 PrintError(js, "%" Pd " is not a valid typearguments id.", id); 2776 PrintError(js, "%" Pd " is not a valid typearguments id.", id);
2504 return true; 2777 return true;
2505 } 2778 }
2506 type_args ^= table.At(id); 2779 type_args ^= table.At(id);
2507 type_args.PrintJSON(js, false); 2780 type_args.PrintJSON(js, false);
2508 return true; 2781 return true;
2509 } 2782 }
2510 2783
2511 2784
2512 static bool HandleHeapMap(Isolate* isolate, JSONStream* js) { 2785 static bool HandleIsolateGetHeapMap(Isolate* isolate, JSONStream* js) {
2513 isolate->heap()->PrintHeapMapToJSONStream(isolate, js); 2786 isolate->heap()->PrintHeapMapToJSONStream(isolate, js);
2514 return true; 2787 return true;
2515 } 2788 }
2516 2789
2517 2790
2518 static bool HandleGraph(Isolate* isolate, JSONStream* js) { 2791 static bool HandleIsolateRequestHeapSnapshot(Isolate* isolate, JSONStream* js) {
2519 Service::SendGraphEvent(isolate); 2792 Service::SendGraphEvent(isolate);
2520 // TODO(koda): Provide some id that ties this request to async response(s). 2793 // TODO(koda): Provide some id that ties this request to async response(s).
2521 JSONObject jsobj(js); 2794 JSONObject jsobj(js);
2522 jsobj.AddProperty("type", "OK"); 2795 jsobj.AddProperty("type", "OK");
2523 jsobj.AddProperty("id", "ok"); 2796 jsobj.AddProperty("id", "ok");
2524 return true; 2797 return true;
2525 } 2798 }
2526 2799
2527 2800
2528 void Service::SendGraphEvent(Isolate* isolate) { 2801 void Service::SendGraphEvent(Isolate* isolate) {
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
2599 2872
2600 2873
2601 static bool HandleMalformedObject(Isolate* isolate, JSONStream* js) { 2874 static bool HandleMalformedObject(Isolate* isolate, JSONStream* js) {
2602 JSONObject jsobj(js); 2875 JSONObject jsobj(js);
2603 jsobj.AddProperty("bart", "simpson"); 2876 jsobj.AddProperty("bart", "simpson");
2604 return true; 2877 return true;
2605 } 2878 }
2606 2879
2607 2880
2608 static IsolateMessageHandlerEntry isolate_handlers[] = { 2881 static IsolateMessageHandlerEntry isolate_handlers[] = {
2609 { "_malformedjson", HandleMalformedJson }, 2882 { "_malformedjson", HandleMalformedJson }, // debug
2610 { "_malformedobject", HandleMalformedObject }, 2883 { "_malformedobject", HandleMalformedObject }, // debug
2611 { "_echo", HandleIsolateEcho }, 2884 { "_echo", HandleIsolateEcho }, // debug
2612 { "", HandleIsolate }, 2885 { "", HandleIsolate }, // getObject
2613 { "address", HandleAddress }, 2886 { "address", HandleAddress }, // to do
2614 { "allocationprofile", HandleAllocationProfile }, 2887 { "classes", HandleClasses }, // getObject
2615 { "classes", HandleClasses }, 2888 { "code", HandleCode }, // getObject
2616 { "code", HandleCode }, 2889 { "libraries", HandleLibraries }, // getObject
2617 { "coverage", HandleCoverage }, 2890 { "metrics", HandleMetrics }, // to do - complex?
2618 { "debug", HandleDebug }, 2891 { "objects", HandleObjects }, // getObject
2619 { "graph", HandleGraph }, 2892 { "scripts", HandleScripts }, // getObject
2620 { "heapmap", HandleHeapMap }, 2893 { "typearguments", HandleTypeArguments }, // confusing
2621 { "libraries", HandleLibraries },
2622 { "metrics", HandleMetrics },
2623 { "objects", HandleObjects },
2624 { "profile", HandleProfile },
2625 { "scripts", HandleScripts },
2626 { "stacktrace", HandleStackTrace },
2627 { "typearguments", HandleTypeArguments },
2628 }; 2894 };
2629 2895
2630 2896
2631 static IsolateMessageHandler FindIsolateMessageHandler(const char* command) { 2897 static IsolateMessageHandler FindIsolateMessageHandler(const char* command) {
2632 intptr_t num_message_handlers = sizeof(isolate_handlers) / 2898 intptr_t num_message_handlers = sizeof(isolate_handlers) /
2633 sizeof(isolate_handlers[0]); 2899 sizeof(isolate_handlers[0]);
2634 for (intptr_t i = 0; i < num_message_handlers; i++) { 2900 for (intptr_t i = 0; i < num_message_handlers; i++) {
2635 const IsolateMessageHandlerEntry& entry = isolate_handlers[i]; 2901 const IsolateMessageHandlerEntry& entry = isolate_handlers[i];
2636 if (strcmp(command, entry.command) == 0) { 2902 if (strcmp(command, entry.command) == 0) {
2637 return entry.handler; 2903 return entry.handler;
2638 } 2904 }
2639 } 2905 }
2640 if (FLAG_trace_service) { 2906 if (FLAG_trace_service) {
2641 OS::Print("vm-service: No isolate message handler for <%s>.\n", command); 2907 OS::Print("vm-service: No isolate message handler for <%s>.\n", command);
2642 } 2908 }
2643 return NULL; 2909 return NULL;
2644 } 2910 }
2645 2911
2646 2912
2913 static bool HandleIsolateGetObject(Isolate* isolate, JSONStream* js) {
2914 const char* id = js->LookupOption("id");
2915 if (id == NULL) {
2916 // TODO(turnidge): Print the isolate here instead.
2917 PrintError(js, "GetObject expects an 'id' parameter\n",
2918 js->num_arguments());
2919 return true;
2920 }
2921
2922 // Handle heap objects.
2923 ObjectIdRing::LookupResult lookup_result;
2924 const Object& obj =
2925 Object::Handle(LookupHeapObject(isolate, id, &lookup_result));
2926 if (obj.raw() != Object::sentinel().raw()) {
2927 // We found a heap object for this id. Return it.
2928 obj.PrintJSON(js, false);
2929 return true;
2930 } else if (lookup_result == ObjectIdRing::kCollected) {
2931 PrintSentinel(js, "objects/collected", "<collected>");
2932 } else if (lookup_result == ObjectIdRing::kExpired) {
2933 PrintSentinel(js, "objects/expired", "<expired>");
2934 }
2935
2936 // Handle non-heap objects.
2937 SourceBreakpoint* bpt = LookupBreakpoint(isolate, id);
2938 if (bpt != NULL) {
2939 bpt->PrintJSON(js);
2940 return true;
2941 }
2942
2943 PrintError(js, "Unrecognized object id: %s\n", id);
2944 return true;
2945 }
2946
2947
2948 static IsolateMessageHandlerEntry isolate_handlers_new[] = {
2949 { "getObject", HandleIsolateGetObject },
2950 { "getBreakpoints", HandleIsolateGetBreakpoints },
2951 { "pause", HandleIsolatePause },
2952 { "resume", HandleIsolateResume },
2953 { "getStack", HandleIsolateGetStack },
2954 { "getCpuProfile", HandleIsolateGetCpuProfile },
2955 { "getTagProfile", HandleIsolateGetTagProfile },
2956 { "getAllocationProfile", HandleIsolateGetAllocationProfile },
2957 { "getHeapMap", HandleIsolateGetHeapMap },
2958 { "addBreakpoint", HandleIsolateAddBreakpoint },
2959 { "removeBreakpoint", HandleIsolateRemoveBreakpoint },
2960 { "getCoverage", HandleIsolateGetCoverage },
2961 { "eval", HandleIsolateEval },
2962 { "getRetainedSize", HandleIsolateGetRetainedSize },
2963 { "getRetainingPath", HandleIsolateGetRetainingPath },
2964 { "getInboundReferences", HandleIsolateGetInboundReferences },
2965 { "getInstances", HandleIsolateGetInstances },
2966 { "requestHeapSnapshot", HandleIsolateRequestHeapSnapshot },
2967 };
2968
2969
2970 static IsolateMessageHandler FindIsolateMessageHandlerNew(const char* command) {
2971 intptr_t num_message_handlers = sizeof(isolate_handlers_new) /
2972 sizeof(isolate_handlers_new[0]);
2973 for (intptr_t i = 0; i < num_message_handlers; i++) {
2974 const IsolateMessageHandlerEntry& entry = isolate_handlers_new[i];
2975 if (strcmp(command, entry.command) == 0) {
2976 return entry.handler;
2977 }
2978 }
2979 if (FLAG_trace_service) {
2980 OS::Print("Service has no isolate message handler for <%s>\n", command);
2981 }
2982 return NULL;
2983 }
2984
2985
2647 void Service::HandleRootMessage(const Instance& msg) { 2986 void Service::HandleRootMessage(const Instance& msg) {
2648 Isolate* isolate = Isolate::Current(); 2987 Isolate* isolate = Isolate::Current();
2649 ASSERT(!msg.IsNull()); 2988 ASSERT(!msg.IsNull());
2650 ASSERT(msg.IsArray()); 2989 ASSERT(msg.IsArray());
2651 2990
2652 { 2991 {
2653 StackZone zone(isolate); 2992 StackZone zone(isolate);
2654 HANDLESCOPE(isolate); 2993 HANDLESCOPE(isolate);
2655 2994
2656 const Array& message = Array::Cast(msg); 2995 const Array& message = Array::Cast(msg);
(...skipping 340 matching lines...) Expand 10 before | Expand all | Expand 10 after
2997 while (current != NULL) { 3336 while (current != NULL) {
2998 if (strcmp(name, current->name()) == 0) { 3337 if (strcmp(name, current->name()) == 0) {
2999 return current; 3338 return current;
3000 } 3339 }
3001 current = current->next(); 3340 current = current->next();
3002 } 3341 }
3003 return NULL; 3342 return NULL;
3004 } 3343 }
3005 3344
3006 } // namespace dart 3345 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/service.h ('k') | runtime/vm/service/message.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698