Chromium Code Reviews| Index: runtime/observatory/lib/src/service/object.dart |
| diff --git a/runtime/observatory/lib/src/service/object.dart b/runtime/observatory/lib/src/service/object.dart |
| index 98a128b06ed86ea9a92b296de83aa854877c4fc4..b60526e0c8283b91e5cb6ef258eb0b9119eac8ef 100644 |
| --- a/runtime/observatory/lib/src/service/object.dart |
| +++ b/runtime/observatory/lib/src/service/object.dart |
| @@ -779,10 +779,9 @@ class HeapSnapshot { |
| final DateTime timeStamp; |
| final Isolate isolate; |
| - HeapSnapshot(this.isolate, ByteData data) : |
| - graph = new ObjectGraph(new ReadStream(data)), |
| - timeStamp = new DateTime.now() { |
| - } |
| + HeapSnapshot(this.isolate, chunks, nodeCount) : |
| + graph = new ObjectGraph(chunks, nodeCount), |
| + timeStamp = new DateTime.now(); |
| List<Future<ServiceObject>> getMostRetained({int classId, int limit}) { |
| var result = []; |
| @@ -795,8 +794,6 @@ class HeapSnapshot { |
| } |
| return result; |
| } |
| - |
| - |
| } |
| /// State for a running isolate. |
| @@ -857,6 +854,20 @@ class Isolate extends ServiceObjectOwner with Coverage { |
| .then(_buildClassHierarchy); |
| } |
| + Future<List<Class>> getClassRefs() async { |
| + ServiceMap classList = await invokeRpc('getClassList', {}); |
| + assert(classList.type == 'ClassList'); |
| + var classRefs = []; |
| + for (var cls in classList['classes']) { |
| + // Skip over non-class classes. |
| + if (cls is Class) { |
| + _classesByCid[cls.vmCid] = cls; |
| + classRefs.add(cls); |
| + } |
| + } |
| + return classRefs; |
| + } |
| + |
| /// Given the class list, loads each class. |
| 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.
|
| assert(classList.type == 'ClassList'); |
| @@ -864,6 +875,7 @@ class Isolate extends ServiceObjectOwner with Coverage { |
| for (var cls in classList['classes']) { |
| // Skip over non-class classes. |
| if (cls is Class) { |
| + _classesByCid[cls.vmCid] = cls; |
| futureClasses.add(cls.load()); |
| } |
| } |
| @@ -886,6 +898,8 @@ class Isolate extends ServiceObjectOwner with Coverage { |
| return new Future.value(objectClass); |
| } |
| + Class getClassByCid(int cid) => _classesByCid[cid]; |
| + |
| ServiceObject getFromMap(ObservableMap map) { |
| if (map == null) { |
| return null; |
| @@ -938,6 +952,7 @@ class Isolate extends ServiceObjectOwner with Coverage { |
| @observable Class objectClass; |
| @observable final rootClasses = new ObservableList<Class>(); |
| + Map<int, Class> _classesByCid = new Map<int, Class>(); |
| @observable Library rootLibrary; |
| @observable ObservableList<Library> libraries = |
| @@ -958,21 +973,42 @@ class Isolate extends ServiceObjectOwner with Coverage { |
| @observable DartError error; |
| @observable HeapSnapshot latestSnapshot; |
| - Completer<HeapSnapshot> _snapshotFetch; |
| + StreamController _snapshotFetch; |
| + |
| + var chunksInProgress; |
| void _loadHeapSnapshot(ServiceEvent event) { |
| - latestSnapshot = new HeapSnapshot(this, event.data); |
| + // Occasionally these actually arrive out of order. |
| + var i = event.i; |
| + var n = event.n; |
| + if (chunksInProgress == null) { |
| + chunksInProgress = new List(n); |
| + } |
| + chunksInProgress[i] = event.data; |
| + _snapshotFetch.add("Receiving snapshot chunk ${i + 1} of $n..."); |
| + |
| + for (i = 0; i < n; i++) { |
| + if (chunksInProgress[i] == null) return; |
| + } |
| + |
| + var chunks = chunksInProgress; |
| + chunksInProgress = null; |
| + |
| + latestSnapshot = new HeapSnapshot(this, chunks, event.nodeCount); |
| if (_snapshotFetch != null) { |
| - _snapshotFetch.complete(latestSnapshot); |
| + latestSnapshot.graph.process(_snapshotFetch).then((graph) { |
| + _snapshotFetch.add(latestSnapshot); |
| + _snapshotFetch.close(); |
| + }); |
| } |
| } |
| - Future<HeapSnapshot> fetchHeapSnapshot() { |
| - if (_snapshotFetch == null || _snapshotFetch.isCompleted) { |
| - _snapshotFetch = new Completer<HeapSnapshot>(); |
| + Stream fetchHeapSnapshot() { |
| + if (_snapshotFetch == null || _snapshotFetch.isClosed) { |
| + _snapshotFetch = new StreamController(); |
| isolate.invokeRpcNoUpgrade('requestHeapSnapshot', {}); |
| } |
| - return _snapshotFetch.future; |
| + return _snapshotFetch.stream; |
| } |
| void updateHeapsFromMap(ObservableMap map) { |
| @@ -1424,6 +1460,7 @@ class ServiceEvent extends ServiceObject { |
| @observable ByteData data; |
| @observable int count; |
| @observable String reason; |
| + int i, n, nodeCount; |
|
koda
2015/05/19 20:12:35
Consider more descriptive names.
|
| @observable bool get isPauseEvent { |
| return (eventType == kPauseStart || |
| @@ -1456,6 +1493,15 @@ class ServiceEvent extends ServiceObject { |
| if (map['_data'] != null) { |
| data = map['_data']; |
| } |
| + if (map['i'] != null) { |
| + i = map['i']; |
| + } |
| + if (map['n'] != null) { |
| + n = map['n']; |
| + } |
| + if (map['nodeCount'] != null) { |
| + nodeCount = map['nodeCount']; |
| + } |
| if (map['count'] != null) { |
| count = map['count']; |
| } |