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

Unified Diff: runtime/observatory/lib/object_graph.dart

Issue 2480293003: Observatory: Add view of dominator tree with siblings merged by class. (Closed)
Patch Set: . Created 4 years, 1 month 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 side-by-side diff with in-line comments
Download patch
Index: runtime/observatory/lib/object_graph.dart
diff --git a/runtime/observatory/lib/object_graph.dart b/runtime/observatory/lib/object_graph.dart
index c2b4169e7d8cbf6ba61e2647b57ec074b0eb8fdd..33a727aea258ff17d8db55190a2bf0fecf903620 100644
--- a/runtime/observatory/lib/object_graph.dart
+++ b/runtime/observatory/lib/object_graph.dart
@@ -282,6 +282,75 @@ class ObjectVertex {
}
}
+
+class MergedObjectVertex {
Cutch 2016/11/14 17:24:13 Doc comment explaining what this represents at a h
rmacnak 2016/11/15 00:44:15 Added comment. This class does *not* implement Obj
+ // 0 represents invalid/uninitialized, 1 is the root.
Cutch 2016/11/14 17:24:13 Let's use a constant for 0 where you mean the inva
+ final int _id;
+ final ObjectGraph _graph;
+
+ MergedObjectVertex._(this._id, this._graph);
+
+ bool get isRoot => _id == 1;
+
+ bool operator ==(other) => _id == other._id && _graph == other._graph;
+ int get hashCode => _id;
+
+ int get vmCid => _graph._cids[_id];
+
+ int get shallowSize {
+ var cids = _graph._cids;
+ var size = 0;
+ var sibling = _id;
+ while (sibling != 0 &&
+ cids[sibling] == cids[_id]) {
+ size += _graph._shallowSizes[sibling];
+ sibling = _graph._mergedDomNext[sibling];
+ }
+ return size;
+ }
+ int get retainedSize {
+ var cids = _graph._cids;
+ var size = 0;
+ var sibling = _id;
+ while (sibling != 0 &&
Cutch 2016/11/14 17:24:13 here and elsewhere != invalidNodeIndex
+ cids[sibling] == cids[_id]) {
+ size += _graph._retainedSizes[sibling];
+ sibling = _graph._mergedDomNext[sibling];
+ }
+ return size;
+ }
+ int get instanceCount {
+ var cids = _graph._cids;
+ var count = 0;
+ var sibling = _id;
+ while (sibling != 0 &&
+ cids[sibling] == cids[_id]) {
+ count++;
+ sibling = _graph._mergedDomNext[sibling];
+ }
+ return count;
+ }
+
+ List<ObjectVertex> dominatorTreeChildren() {
+ var next = _graph._mergedDomNext;
+ var cids = _graph._cids;
+
+ var domChildren = [];
+ var prev = 0;
+ var child = _graph._mergedDomHead[_id];
+ while (child != 0) {
Cutch 2016/11/14 17:24:13 Scan the list of siblings, creating MergedObjectVe
rmacnak 2016/11/15 00:44:15 Done.
+ if (prev == 0 ||
+ cids[prev] != cids[child]) {
+ domChildren.add(new MergedObjectVertex._(child, _graph));
+ }
+ prev = child;
+ child = next[child];
+ }
+
+ return domChildren;
+ }
+}
+
class _SuccessorsIterable extends IterableBase<ObjectVertex> {
final ObjectGraph _graph;
final int _id;
@@ -346,6 +415,7 @@ class ObjectGraph {
int get edgeCount => _E;
ObjectVertex get root => new ObjectVertex._(1, this);
+ MergedObjectVertex get mergedRoot => new MergedObjectVertex._(1, this);
Iterable<ObjectVertex> get vertices => new _VerticesIterable(this);
Iterable<ObjectVertex> getMostRetained({int classId, int limit}) {
@@ -381,10 +451,10 @@ class ObjectGraph {
controller.add(["Finding depth-first order...", 30.0]);
await new Future(() => _dfs());
- controller.add(["Finding predecessors...", 45.0]);
+ controller.add(["Finding predecessors...", 40.0]);
await new Future(() => _buildPredecessors());
- controller.add(["Finding dominators...", 60.0]);
+ controller.add(["Finding dominators...", 50.0]);
await new Future(() => _buildDominators());
_firstPreds = null;
@@ -393,12 +463,21 @@ class ObjectGraph {
_semi = null;
_parent = null;
- controller.add(["Finding retained sizes...", 75.0]);
+ controller.add(["Finding retained sizes...", 60.0]);
await new Future(() => _calculateRetainedSizes());
_vertex = null;
- controller.add(["Loaded", 100.0]);
+ controller.add(["Linking dominator tree children...", 70.0]);
+ await new Future(() => _linkDominatorChildren());
+
+ controller.add(["Sorting dominator tree children...", 80.0]);
+ await new Future(() => _sortDominatorChildren());
+
+ controller.add(["Merging dominator tree siblings...", 90.0]);
+ await new Future(() => _mergeDominatorSiblings());
+
+ controller.add(["Processed", 100.0]);
controller.close();
}());
return controller.stream;
@@ -431,6 +510,8 @@ class ObjectGraph {
// Outputs.
Uint32List _doms;
Uint32List _retainedSizes;
+ Uint32List _mergedDomHead;
+ Uint32List _mergedDomNext;
void _remapNodes() {
var N = _N;
@@ -812,4 +893,150 @@ class ObjectGraph {
_retainedSizes = retainedSizes;
_size = size;
}
+
+ void _linkDominatorChildren() {
Cutch 2016/11/14 17:24:13 // Build a set of linked lists of children dominat
+ var N = _N;
Cutch 2016/11/14 17:24:13 Let's start typing local variables ....
rmacnak 2016/11/15 00:44:15 Not while we can still write Dart.
+ var doms = _doms;
+ var head = new Uint32List(N + 1);
Cutch 2016/11/14 17:24:13 We need to start commenting at a high level what i
+ var next = new Uint32List(N + 1);
+
+ for (var child = 1; child <= N; child++) {
+ var parent = doms[child];
+ next[child] = head[parent];
+ head[parent] = child;
+ }
+
+ _mergedDomHead = head;
+ _mergedDomNext = next;
+ }
+
+ static int _mergeSorted(int head1, int head2,
+ Uint32List next, Uint16List key) {
+ var head = head1;
+ var beforeInsert = 0;
+ var afterInsert = head1;
+ var startInsert = head2;
+
+ while (startInsert != 0) {
+ while ((afterInsert != 0) &&
+ (key[afterInsert] <= key[startInsert])) {
+ beforeInsert = afterInsert;
+ afterInsert = next[beforeInsert];
+ }
+
+ var endInsert = startInsert;
+ var peek = next[endInsert];
+
+ while ((peek != 0) && (key[peek] < key[afterInsert])) {
+ endInsert = peek;
+ peek = next[endInsert];
+ }
+ assert(endInsert != 0);
+
+ if (beforeInsert == 0) {
+ head = startInsert;
+ } else {
+ next[beforeInsert] = startInsert;
+ }
+ next[endInsert] = afterInsert;
+
+ startInsert = peek;
+ beforeInsert = endInsert;
+ }
+
+ return head;
+ }
+
+ void _sortDominatorChildren() {
+ var N = _N;
+ var cids = _cids;
+ var head = _mergedDomHead;
+ var next = _mergedDomNext;
+
+ int sort(int head) {
Cutch 2016/11/14 17:24:13 /// Returns the first node index in the list after
+ if (head == 0) return 0;
Cutch 2016/11/14 17:24:13 ... == invalidNodeIndex) { return invalidNodeInd
+ if (next[head] == 0) return head;
+
Cutch 2016/11/14 17:24:13 // Determine the mid and end point of the list by
+ int head1 = head;
+ int slow = head;
+ int fast = head;
+ while (next[fast] != 0 &&
+ next[next[fast]] != 0) {
+ slow = next[slow];
+ fast = next[next[fast]];
+ }
+
+ int head2 = next[slow];
Cutch 2016/11/14 17:24:13 // Split the list in half.
+ next[slow] = 0;
+
+ assert(head1 != head2);
+ int newHead1 = sort(head1);
Cutch 2016/11/14 17:24:13 Recursively sort each of the sublists
+ int newHead2 = sort(head2);
+ return _mergeSorted(newHead1, newHead2, next, cids);
Cutch 2016/11/14 17:24:13 Merge them
+ }
+
+ for (var parent = 1; parent <= N; parent++) {
Cutch 2016/11/14 17:24:13 Sort all of the merged dominator sibling lists so
+ head[parent] = sort(head[parent]);
+ }
+ }
+
+ void _mergeDominatorSiblings() {
+ var N = _N;
+ var cids = _cids;
+ var head = _mergedDomHead;
+ var next = _mergedDomNext;
+ var workStack = new Uint32List(N);
+ var workStackTop = 0;
+
+ mergeChildrenAndSort(var parent1, var end) {
+ assert(parent1 != 0);
+ if (next[parent1] == end) return;
+
+ int cid = cids[parent1];
+ int slow = parent1;
+ int fast = parent1;
+ while (next[fast] != end &&
+ next[next[fast]] != end) {
Cutch 2016/11/14 17:24:13 this should be factored out and reused with the co
+ slow = next[slow];
+ fast = next[next[fast]];
+ }
+
+ int parent2 = next[slow];
+
+ assert(parent2 != 0);
+ assert(parent1 != parent2);
+ assert(cids[parent1] == cids[parent2]);
+
+ mergeChildrenAndSort(parent1, parent2);
+ mergeChildrenAndSort(parent2, end);
+
+ head[parent1] = _mergeSorted(head[parent1], head[parent2], next, cids);
+ head[parent2] = 0;
Cutch 2016/11/14 17:24:12 // We have merged the siblings of parent2 into par
+ }
+
+ // Push root.
+ workStack[workStackTop++] = 1;
+
+ while (workStackTop > 0) {
+ var parent = workStack[--workStackTop];
+
+ var prev = 0;
+ var child = head[parent];
+ while (child != 0) {
+ // Push child.
+ workStack[workStackTop++] = child;
+
+ // Next sibling with a different cid.
+ var after = child;
+ while (after != 0 &&
+ cids[after] == cids[child]) {
+ after = next[after];
+ }
+
+ mergeChildrenAndSort(child, after);
Cutch 2016/11/14 17:24:13 // child is the first node with cid A and after is
+
+ child = after;
+ }
+ }
+ }
}

Powered by Google App Engine
This is Rietveld 408576698