Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, 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 part of service; | 5 part of service; |
| 6 | 6 |
| 7 /// An RpcException represents an exceptional event that happened | 7 /// An RpcException represents an exceptional event that happened |
| 8 /// while invoking an rpc. | 8 /// while invoking an rpc. |
| 9 abstract class RpcException implements Exception { | 9 abstract class RpcException implements Exception { |
| 10 RpcException(this.message); | 10 RpcException(this.message); |
| (...skipping 761 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 772 totalCollectionTimeInSeconds = heapMap['time']; | 772 totalCollectionTimeInSeconds = heapMap['time']; |
| 773 averageCollectionPeriodInMillis = heapMap['avgCollectionPeriodMillis']; | 773 averageCollectionPeriodInMillis = heapMap['avgCollectionPeriodMillis']; |
| 774 } | 774 } |
| 775 } | 775 } |
| 776 | 776 |
| 777 class HeapSnapshot { | 777 class HeapSnapshot { |
| 778 final ObjectGraph graph; | 778 final ObjectGraph graph; |
| 779 final DateTime timeStamp; | 779 final DateTime timeStamp; |
| 780 final Isolate isolate; | 780 final Isolate isolate; |
| 781 | 781 |
| 782 HeapSnapshot(this.isolate, ByteData data) : | 782 HeapSnapshot(this.isolate, chunks, nodeCount) : |
| 783 graph = new ObjectGraph(new ReadStream(data)), | 783 graph = new ObjectGraph(chunks, nodeCount), |
| 784 timeStamp = new DateTime.now() { | 784 timeStamp = new DateTime.now(); |
| 785 } | |
| 786 | 785 |
| 787 List<Future<ServiceObject>> getMostRetained({int classId, int limit}) { | 786 List<Future<ServiceObject>> getMostRetained({int classId, int limit}) { |
| 788 var result = []; | 787 var result = []; |
| 789 for (var v in graph.getMostRetained(classId: classId, limit: limit)) { | 788 for (var v in graph.getMostRetained(classId: classId, limit: limit)) { |
| 790 var address = v.addressForWordSize(isolate.vm.architectureBits ~/ 8); | 789 var address = v.addressForWordSize(isolate.vm.architectureBits ~/ 8); |
| 791 result.add(isolate.getObjectByAddress(address.toRadixString(16)).then((obj ) { | 790 result.add(isolate.getObjectByAddress(address.toRadixString(16)).then((obj ) { |
| 792 obj.retainedSize = v.retainedSize; | 791 obj.retainedSize = v.retainedSize; |
| 793 return new Future(() => obj); | 792 return new Future(() => obj); |
| 794 })); | 793 })); |
| 795 } | 794 } |
| 796 return result; | 795 return result; |
| 797 } | 796 } |
| 798 | |
| 799 | |
| 800 } | 797 } |
| 801 | 798 |
| 802 /// State for a running isolate. | 799 /// State for a running isolate. |
| 803 class Isolate extends ServiceObjectOwner with Coverage { | 800 class Isolate extends ServiceObjectOwner with Coverage { |
| 804 @reflectable VM get vm => owner; | 801 @reflectable VM get vm => owner; |
| 805 @reflectable Isolate get isolate => this; | 802 @reflectable Isolate get isolate => this; |
| 806 @observable int number; | 803 @observable int number; |
| 807 @observable DateTime startTime; | 804 @observable DateTime startTime; |
| 808 @observable Duration get upTime => | 805 @observable Duration get upTime => |
| 809 (new DateTime.now().difference(startTime)); | 806 (new DateTime.now().difference(startTime)); |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 850 } | 847 } |
| 851 | 848 |
| 852 /// Fetches and builds the class hierarchy for this isolate. Returns the | 849 /// Fetches and builds the class hierarchy for this isolate. Returns the |
| 853 /// Object class object. | 850 /// Object class object. |
| 854 Future<Class> getClassHierarchy() { | 851 Future<Class> getClassHierarchy() { |
| 855 return invokeRpc('getClassList', {}) | 852 return invokeRpc('getClassList', {}) |
| 856 .then(_loadClasses) | 853 .then(_loadClasses) |
| 857 .then(_buildClassHierarchy); | 854 .then(_buildClassHierarchy); |
| 858 } | 855 } |
| 859 | 856 |
| 857 Future<List<Class>> getClassRefs() async { | |
| 858 ServiceMap classList = await invokeRpc('getClassList', {}); | |
| 859 assert(classList.type == 'ClassList'); | |
| 860 var classRefs = []; | |
| 861 for (var cls in classList['classes']) { | |
| 862 // Skip over non-class classes. | |
| 863 if (cls is Class) { | |
| 864 _classesByCid[cls.vmCid] = cls; | |
| 865 classRefs.add(cls); | |
| 866 } | |
| 867 } | |
| 868 return classRefs; | |
| 869 } | |
| 870 | |
| 860 /// Given the class list, loads each class. | 871 /// Given the class list, loads each class. |
| 861 Future<List<Class>> _loadClasses(ServiceMap classList) { | 872 Future<List<Class>> _loadClasses(ServiceMap classList) { |
|
koda
2015/05/19 20:12:35
Is this one still needed?
rmacnak
2015/05/19 22:16:08
Used by getClassHierarchy.
| |
| 862 assert(classList.type == 'ClassList'); | 873 assert(classList.type == 'ClassList'); |
| 863 var futureClasses = []; | 874 var futureClasses = []; |
| 864 for (var cls in classList['classes']) { | 875 for (var cls in classList['classes']) { |
| 865 // Skip over non-class classes. | 876 // Skip over non-class classes. |
| 866 if (cls is Class) { | 877 if (cls is Class) { |
| 878 _classesByCid[cls.vmCid] = cls; | |
| 867 futureClasses.add(cls.load()); | 879 futureClasses.add(cls.load()); |
| 868 } | 880 } |
| 869 } | 881 } |
| 870 return Future.wait(futureClasses); | 882 return Future.wait(futureClasses); |
| 871 } | 883 } |
| 872 | 884 |
| 873 /// Builds the class hierarchy and returns the Object class. | 885 /// Builds the class hierarchy and returns the Object class. |
| 874 Future<Class> _buildClassHierarchy(List<Class> classes) { | 886 Future<Class> _buildClassHierarchy(List<Class> classes) { |
| 875 rootClasses.clear(); | 887 rootClasses.clear(); |
| 876 objectClass = null; | 888 objectClass = null; |
| 877 for (var cls in classes) { | 889 for (var cls in classes) { |
| 878 if (cls.superclass == null) { | 890 if (cls.superclass == null) { |
| 879 rootClasses.add(cls); | 891 rootClasses.add(cls); |
| 880 } | 892 } |
| 881 if ((cls.vmName == 'Object') && (cls.isPatch == false)) { | 893 if ((cls.vmName == 'Object') && (cls.isPatch == false)) { |
| 882 objectClass = cls; | 894 objectClass = cls; |
| 883 } | 895 } |
| 884 } | 896 } |
| 885 assert(objectClass != null); | 897 assert(objectClass != null); |
| 886 return new Future.value(objectClass); | 898 return new Future.value(objectClass); |
| 887 } | 899 } |
| 888 | 900 |
| 901 Class getClassByCid(int cid) => _classesByCid[cid]; | |
| 902 | |
| 889 ServiceObject getFromMap(ObservableMap map) { | 903 ServiceObject getFromMap(ObservableMap map) { |
| 890 if (map == null) { | 904 if (map == null) { |
| 891 return null; | 905 return null; |
| 892 } | 906 } |
| 893 var mapType = _stripRef(map['type']); | 907 var mapType = _stripRef(map['type']); |
| 894 if (mapType == 'Isolate') { | 908 if (mapType == 'Isolate') { |
| 895 // There are sometimes isolate refs in ServiceEvents. | 909 // There are sometimes isolate refs in ServiceEvents. |
| 896 return vm.getFromMap(map); | 910 return vm.getFromMap(map); |
| 897 } | 911 } |
| 898 String mapId = map['id']; | 912 String mapId = map['id']; |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 931 }; | 945 }; |
| 932 return isolate.invokeRpc('getObject', params); | 946 return isolate.invokeRpc('getObject', params); |
| 933 } | 947 } |
| 934 | 948 |
| 935 Future<ObservableMap> _fetchDirect() { | 949 Future<ObservableMap> _fetchDirect() { |
| 936 return invokeRpcNoUpgrade('getIsolate', {}); | 950 return invokeRpcNoUpgrade('getIsolate', {}); |
| 937 } | 951 } |
| 938 | 952 |
| 939 @observable Class objectClass; | 953 @observable Class objectClass; |
| 940 @observable final rootClasses = new ObservableList<Class>(); | 954 @observable final rootClasses = new ObservableList<Class>(); |
| 955 Map<int, Class> _classesByCid = new Map<int, Class>(); | |
| 941 | 956 |
| 942 @observable Library rootLibrary; | 957 @observable Library rootLibrary; |
| 943 @observable ObservableList<Library> libraries = | 958 @observable ObservableList<Library> libraries = |
| 944 new ObservableList<Library>(); | 959 new ObservableList<Library>(); |
| 945 @observable ObservableMap topFrame; | 960 @observable ObservableMap topFrame; |
| 946 | 961 |
| 947 @observable String name; | 962 @observable String name; |
| 948 @observable String vmName; | 963 @observable String vmName; |
| 949 @observable ServiceFunction entry; | 964 @observable ServiceFunction entry; |
| 950 | 965 |
| 951 @observable final Map<String, double> timers = | 966 @observable final Map<String, double> timers = |
| 952 toObservable(new Map<String, double>()); | 967 toObservable(new Map<String, double>()); |
| 953 | 968 |
| 954 final HeapSpace newSpace = new HeapSpace(); | 969 final HeapSpace newSpace = new HeapSpace(); |
| 955 final HeapSpace oldSpace = new HeapSpace(); | 970 final HeapSpace oldSpace = new HeapSpace(); |
| 956 | 971 |
| 957 @observable String fileAndLine; | 972 @observable String fileAndLine; |
| 958 | 973 |
| 959 @observable DartError error; | 974 @observable DartError error; |
| 960 @observable HeapSnapshot latestSnapshot; | 975 @observable HeapSnapshot latestSnapshot; |
| 961 Completer<HeapSnapshot> _snapshotFetch; | 976 StreamController _snapshotFetch; |
| 977 | |
| 978 var chunksInProgress; | |
| 962 | 979 |
| 963 void _loadHeapSnapshot(ServiceEvent event) { | 980 void _loadHeapSnapshot(ServiceEvent event) { |
| 964 latestSnapshot = new HeapSnapshot(this, event.data); | 981 // Occasionally these actually arrive out of order. |
| 982 var i = event.i; | |
| 983 var n = event.n; | |
| 984 if (chunksInProgress == null) { | |
| 985 chunksInProgress = new List(n); | |
| 986 } | |
| 987 chunksInProgress[i] = event.data; | |
| 988 _snapshotFetch.add("Receiving snapshot chunk ${i + 1} of $n..."); | |
| 989 | |
| 990 for (i = 0; i < n; i++) { | |
| 991 if (chunksInProgress[i] == null) return; | |
| 992 } | |
| 993 | |
| 994 var chunks = chunksInProgress; | |
| 995 chunksInProgress = null; | |
| 996 | |
| 997 latestSnapshot = new HeapSnapshot(this, chunks, event.nodeCount); | |
| 965 if (_snapshotFetch != null) { | 998 if (_snapshotFetch != null) { |
| 966 _snapshotFetch.complete(latestSnapshot); | 999 latestSnapshot.graph.process(_snapshotFetch).then((graph) { |
| 1000 _snapshotFetch.add(latestSnapshot); | |
| 1001 _snapshotFetch.close(); | |
| 1002 }); | |
| 967 } | 1003 } |
| 968 } | 1004 } |
| 969 | 1005 |
| 970 Future<HeapSnapshot> fetchHeapSnapshot() { | 1006 Stream fetchHeapSnapshot() { |
| 971 if (_snapshotFetch == null || _snapshotFetch.isCompleted) { | 1007 if (_snapshotFetch == null || _snapshotFetch.isClosed) { |
| 972 _snapshotFetch = new Completer<HeapSnapshot>(); | 1008 _snapshotFetch = new StreamController(); |
| 973 isolate.invokeRpcNoUpgrade('requestHeapSnapshot', {}); | 1009 isolate.invokeRpcNoUpgrade('requestHeapSnapshot', {}); |
| 974 } | 1010 } |
| 975 return _snapshotFetch.future; | 1011 return _snapshotFetch.stream; |
| 976 } | 1012 } |
| 977 | 1013 |
| 978 void updateHeapsFromMap(ObservableMap map) { | 1014 void updateHeapsFromMap(ObservableMap map) { |
| 979 newSpace.update(map['new']); | 1015 newSpace.update(map['new']); |
| 980 oldSpace.update(map['old']); | 1016 oldSpace.update(map['old']); |
| 981 } | 1017 } |
| 982 | 1018 |
| 983 void _update(ObservableMap map, bool mapIsRef) { | 1019 void _update(ObservableMap map, bool mapIsRef) { |
| 984 name = map['name']; | 1020 name = map['name']; |
| 985 vmName = map['name']; | 1021 vmName = map['name']; |
| (...skipping 431 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1417 } | 1453 } |
| 1418 | 1454 |
| 1419 @observable String eventType; | 1455 @observable String eventType; |
| 1420 @observable Breakpoint breakpoint; | 1456 @observable Breakpoint breakpoint; |
| 1421 @observable ServiceMap topFrame; | 1457 @observable ServiceMap topFrame; |
| 1422 @observable ServiceMap exception; | 1458 @observable ServiceMap exception; |
| 1423 @observable ServiceObject inspectee; | 1459 @observable ServiceObject inspectee; |
| 1424 @observable ByteData data; | 1460 @observable ByteData data; |
| 1425 @observable int count; | 1461 @observable int count; |
| 1426 @observable String reason; | 1462 @observable String reason; |
| 1463 int i, n, nodeCount; | |
|
koda
2015/05/19 20:12:35
Consider more descriptive names.
| |
| 1427 | 1464 |
| 1428 @observable bool get isPauseEvent { | 1465 @observable bool get isPauseEvent { |
| 1429 return (eventType == kPauseStart || | 1466 return (eventType == kPauseStart || |
| 1430 eventType == kPauseExit || | 1467 eventType == kPauseExit || |
| 1431 eventType == kPauseBreakpoint || | 1468 eventType == kPauseBreakpoint || |
| 1432 eventType == kPauseInterrupted || | 1469 eventType == kPauseInterrupted || |
| 1433 eventType == kPauseException); | 1470 eventType == kPauseException); |
| 1434 } | 1471 } |
| 1435 | 1472 |
| 1436 void _update(ObservableMap map, bool mapIsRef) { | 1473 void _update(ObservableMap map, bool mapIsRef) { |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 1449 } | 1486 } |
| 1450 if (map['exception'] != null) { | 1487 if (map['exception'] != null) { |
| 1451 exception = map['exception']; | 1488 exception = map['exception']; |
| 1452 } | 1489 } |
| 1453 if (map['inspectee'] != null) { | 1490 if (map['inspectee'] != null) { |
| 1454 inspectee = map['inspectee']; | 1491 inspectee = map['inspectee']; |
| 1455 } | 1492 } |
| 1456 if (map['_data'] != null) { | 1493 if (map['_data'] != null) { |
| 1457 data = map['_data']; | 1494 data = map['_data']; |
| 1458 } | 1495 } |
| 1496 if (map['i'] != null) { | |
| 1497 i = map['i']; | |
| 1498 } | |
| 1499 if (map['n'] != null) { | |
| 1500 n = map['n']; | |
| 1501 } | |
| 1502 if (map['nodeCount'] != null) { | |
| 1503 nodeCount = map['nodeCount']; | |
| 1504 } | |
| 1459 if (map['count'] != null) { | 1505 if (map['count'] != null) { |
| 1460 count = map['count']; | 1506 count = map['count']; |
| 1461 } | 1507 } |
| 1462 } | 1508 } |
| 1463 | 1509 |
| 1464 String toString() { | 1510 String toString() { |
| 1465 if (data == null) { | 1511 if (data == null) { |
| 1466 return "ServiceEvent(owner='${owner.id}', type='${eventType}')"; | 1512 return "ServiceEvent(owner='${owner.id}', type='${eventType}')"; |
| 1467 } else { | 1513 } else { |
| 1468 return "ServiceEvent(owner='${owner.id}', type='${eventType}', " | 1514 return "ServiceEvent(owner='${owner.id}', type='${eventType}', " |
| (...skipping 1641 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3110 var v = list[i]; | 3156 var v = list[i]; |
| 3111 if ((v is ObservableMap) && _isServiceMap(v)) { | 3157 if ((v is ObservableMap) && _isServiceMap(v)) { |
| 3112 list[i] = owner.getFromMap(v); | 3158 list[i] = owner.getFromMap(v); |
| 3113 } else if (v is ObservableList) { | 3159 } else if (v is ObservableList) { |
| 3114 _upgradeObservableList(v, owner); | 3160 _upgradeObservableList(v, owner); |
| 3115 } else if (v is ObservableMap) { | 3161 } else if (v is ObservableMap) { |
| 3116 _upgradeObservableMap(v, owner); | 3162 _upgradeObservableMap(v, owner); |
| 3117 } | 3163 } |
| 3118 } | 3164 } |
| 3119 } | 3165 } |
| OLD | NEW |