OLD | NEW |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #include "vm/service.h" | 5 #include "vm/service.h" |
6 | 6 |
7 #include "include/dart_api.h" | 7 #include "include/dart_api.h" |
8 | 8 |
9 #include "vm/compiler.h" | 9 #include "vm/compiler.h" |
10 #include "vm/coverage.h" | 10 #include "vm/coverage.h" |
(...skipping 698 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
709 r = strtoul(s, &end_ptr, base); | 709 r = strtoul(s, &end_ptr, base); |
710 if (end_ptr == s) { | 710 if (end_ptr == s) { |
711 // String was not advanced at all, cannot be valid. | 711 // String was not advanced at all, cannot be valid. |
712 return false; | 712 return false; |
713 } | 713 } |
714 *id = r; | 714 *id = r; |
715 return true; | 715 return true; |
716 } | 716 } |
717 | 717 |
718 | 718 |
| 719 static bool GetInteger64Id(const char* s, int64_t* id, int base = 10) { |
| 720 if ((s == NULL) || (*s == '\0')) { |
| 721 // Empty string. |
| 722 return false; |
| 723 } |
| 724 if (id == NULL) { |
| 725 // No id pointer. |
| 726 return false; |
| 727 } |
| 728 int64_t r = 0; |
| 729 char* end_ptr = NULL; |
| 730 r = strtoll(s, &end_ptr, base); |
| 731 if (end_ptr == s) { |
| 732 // String was not advanced at all, cannot be valid. |
| 733 return false; |
| 734 } |
| 735 *id = r; |
| 736 return true; |
| 737 } |
| 738 |
| 739 // Scans the string until the '-' character. Returns pointer to string |
| 740 // at '-' character. Returns NULL if not found. |
| 741 const char* ScanUntilDash(const char* s) { |
| 742 if ((s == NULL) || (*s == '\0')) { |
| 743 // Empty string. |
| 744 return NULL; |
| 745 } |
| 746 while (*s != '\0') { |
| 747 if (*s == '-') { |
| 748 return s; |
| 749 } |
| 750 s++; |
| 751 } |
| 752 return NULL; |
| 753 } |
| 754 |
| 755 |
| 756 static bool GetCodeId(const char* s, int64_t* timestamp, uword* address) { |
| 757 if ((s == NULL) || (*s == '\0')) { |
| 758 // Empty string. |
| 759 return false; |
| 760 } |
| 761 if ((timestamp == NULL) || (address == NULL)) { |
| 762 // Bad arguments. |
| 763 return false; |
| 764 } |
| 765 // Extract the timestamp. |
| 766 if (!GetInteger64Id(s, timestamp, 16) || (*timestamp < 0)) { |
| 767 return false; |
| 768 } |
| 769 s = ScanUntilDash(s); |
| 770 if (s == NULL) { |
| 771 return false; |
| 772 } |
| 773 // Skip the dash. |
| 774 s++; |
| 775 // Extract the PC. |
| 776 if (!GetUnsignedIntegerId(s, address, 16)) { |
| 777 return false; |
| 778 } |
| 779 return true; |
| 780 } |
| 781 |
| 782 |
719 static bool HandleClassesClosures(Isolate* isolate, const Class& cls, | 783 static bool HandleClassesClosures(Isolate* isolate, const Class& cls, |
720 JSONStream* js) { | 784 JSONStream* js) { |
721 intptr_t id; | 785 intptr_t id; |
722 if (js->num_arguments() > 4) { | 786 if (js->num_arguments() > 4) { |
723 PrintError(js, "Command too long"); | 787 PrintError(js, "Command too long"); |
724 return true; | 788 return true; |
725 } | 789 } |
726 if (!GetIntegerId(js->GetArgument(3), &id)) { | 790 if (!GetIntegerId(js->GetArgument(3), &id)) { |
727 PrintError(js, "Must specify collection object id: closures/id"); | 791 PrintError(js, "Must specify collection object id: closures/id"); |
728 return true; | 792 return true; |
(...skipping 453 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1182 static bool HandleNullCode(uintptr_t pc, JSONStream* js) { | 1246 static bool HandleNullCode(uintptr_t pc, JSONStream* js) { |
1183 // TODO(turnidge): Consider adding/using Object::null_code() for | 1247 // TODO(turnidge): Consider adding/using Object::null_code() for |
1184 // consistent "type". | 1248 // consistent "type". |
1185 Object::null_object().PrintToJSONStream(js, false); | 1249 Object::null_object().PrintToJSONStream(js, false); |
1186 return true; | 1250 return true; |
1187 } | 1251 } |
1188 | 1252 |
1189 | 1253 |
1190 static bool HandleCode(Isolate* isolate, JSONStream* js) { | 1254 static bool HandleCode(Isolate* isolate, JSONStream* js) { |
1191 REQUIRE_COLLECTION_ID("code"); | 1255 REQUIRE_COLLECTION_ID("code"); |
1192 uintptr_t pc; | 1256 uword pc; |
1193 if (js->num_arguments() > 3) { | 1257 if (js->num_arguments() > 2) { |
1194 PrintError(js, "Command too long"); | 1258 PrintError(js, "Command too long"); |
1195 return true; | 1259 return true; |
1196 } | 1260 } |
1197 if (js->num_arguments() == 3) { | 1261 ASSERT(js->num_arguments() == 2); |
1198 const char* command = js->GetArgument(1); | 1262 static const char* kCollectedPrefix = "collected-"; |
1199 if ((strcmp("collected", command) == 0) || | 1263 static intptr_t kCollectedPrefixLen = strlen(kCollectedPrefix); |
1200 (strcmp("native", command) == 0)) { | 1264 static const char* kNativePrefix = "native-"; |
1201 if (!GetUnsignedIntegerId(js->GetArgument(1), &pc, 16)) { | 1265 static intptr_t kNativePrefixLen = strlen(kNativePrefix); |
1202 PrintError(js, "Must specify code address: code/%s/c0deadd0.", command); | 1266 static const char* kReusedPrefix = "reused-"; |
1203 return true; | 1267 static intptr_t kReusedPrefixLen = strlen(kReusedPrefix); |
1204 } | 1268 const char* command = js->GetArgument(1); |
1205 return HandleNullCode(pc, js); | 1269 if (strncmp(kCollectedPrefix, command, kCollectedPrefixLen) == 0) { |
1206 } else { | 1270 if (!GetUnsignedIntegerId(&command[kCollectedPrefixLen], &pc, 16)) { |
1207 PrintError(js, "Unrecognized subcommand '%s'", js->GetArgument(1)); | 1271 PrintError(js, "Must specify code address: code/%sc0deadd0.", |
| 1272 kCollectedPrefix); |
1208 return true; | 1273 return true; |
1209 } | 1274 } |
| 1275 return HandleNullCode(pc, js); |
1210 } | 1276 } |
1211 ASSERT(js->num_arguments() == 2); | 1277 if (strncmp(kNativePrefix, command, kNativePrefixLen) == 0) { |
1212 if (!GetUnsignedIntegerId(js->GetArgument(1), &pc, 16)) { | 1278 if (!GetUnsignedIntegerId(&command[kNativePrefixLen], &pc, 16)) { |
1213 PrintError(js, "Must specify code address: code/c0deadd0."); | 1279 PrintError(js, "Must specify code address: code/%sc0deadd0.", |
| 1280 kNativePrefix); |
| 1281 return true; |
| 1282 } |
| 1283 // TODO(johnmccutchan): Support native Code. |
| 1284 return HandleNullCode(pc, js); |
| 1285 } |
| 1286 if (strncmp(kReusedPrefix, command, kReusedPrefixLen) == 0) { |
| 1287 if (!GetUnsignedIntegerId(&command[kReusedPrefixLen], &pc, 16)) { |
| 1288 PrintError(js, "Must specify code address: code/%sc0deadd0.", |
| 1289 kReusedPrefix); |
| 1290 return true; |
| 1291 } |
| 1292 return HandleNullCode(pc, js); |
| 1293 } |
| 1294 int64_t timestamp = 0; |
| 1295 if (!GetCodeId(command, ×tamp, &pc) || (timestamp < 0)) { |
| 1296 PrintError(js, "Malformed code id: %s", command); |
1214 return true; | 1297 return true; |
1215 } | 1298 } |
1216 Code& code = Code::Handle(); | 1299 Code& code = Code::Handle(Code::FindCode(pc, timestamp)); |
1217 code ^= Code::LookupCode(pc); | |
1218 if (!code.IsNull()) { | 1300 if (!code.IsNull()) { |
1219 code.PrintToJSONStream(js, false); | 1301 code.PrintToJSONStream(js, false); |
1220 return true; | 1302 return true; |
1221 } | 1303 } |
1222 code ^= Code::LookupCodeInVmIsolate(pc); | 1304 PrintError(js, "Could not find code with id: %s", command); |
1223 if (!code.IsNull()) { | |
1224 code.PrintToJSONStream(js, false); | |
1225 return true; | |
1226 } | |
1227 PrintError(js, "Could not find code at %" Px "", pc); | |
1228 return true; | 1305 return true; |
1229 } | 1306 } |
1230 | 1307 |
1231 | 1308 |
1232 static bool HandleProfile(Isolate* isolate, JSONStream* js) { | 1309 static bool HandleProfile(Isolate* isolate, JSONStream* js) { |
1233 // A full profile includes disassembly of all Dart code objects. | 1310 // A full profile includes disassembly of all Dart code objects. |
1234 // TODO(johnmccutchan): Add sub command to trigger full code dump. | 1311 // TODO(johnmccutchan): Add sub command to trigger full code dump. |
1235 bool full_profile = false; | 1312 bool full_profile = false; |
1236 Profiler::PrintToJSONStream(isolate, js, full_profile); | 1313 Profiler::PrintToJSONStream(isolate, js, full_profile); |
1237 return true; | 1314 return true; |
(...skipping 267 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1505 while (current != NULL) { | 1582 while (current != NULL) { |
1506 if (strcmp(name, current->name()) == 0) { | 1583 if (strcmp(name, current->name()) == 0) { |
1507 return current; | 1584 return current; |
1508 } | 1585 } |
1509 current = current->next(); | 1586 current = current->next(); |
1510 } | 1587 } |
1511 return NULL; | 1588 return NULL; |
1512 } | 1589 } |
1513 | 1590 |
1514 } // namespace dart | 1591 } // namespace dart |
OLD | NEW |