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

Side by Side 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 unified diff | Download patch
« no previous file with comments | « no previous file | runtime/observatory/lib/src/elements/heap_snapshot.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) 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 library object_graph; 5 library object_graph;
6 6
7 import 'dart:async'; 7 import 'dart:async';
8 import 'dart:collection'; 8 import 'dart:collection';
9 import 'dart:typed_data'; 9 import 'dart:typed_data';
10 10
(...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after
214 static const int maxUnsignedDataPerByte = byteMask; 214 static const int maxUnsignedDataPerByte = byteMask;
215 } 215 }
216 216
217 class ObjectVertex { 217 class ObjectVertex {
218 // 0 represents invalid/uninitialized, 1 is the root. 218 // 0 represents invalid/uninitialized, 1 is the root.
219 final int _id; 219 final int _id;
220 final ObjectGraph _graph; 220 final ObjectGraph _graph;
221 221
222 ObjectVertex._(this._id, this._graph); 222 ObjectVertex._(this._id, this._graph);
223 223
224 bool get isRoot => _id == 1; 224 bool get isRoot => ROOT == _id;
225 225
226 bool operator ==(other) => _id == other._id && _graph == other._graph; 226 bool operator ==(other) => _id == other._id && _graph == other._graph;
227 int get hashCode => _id; 227 int get hashCode => _id;
228 228
229 int get retainedSize => _graph._retainedSizes[_id]; 229 int get retainedSize => _graph._retainedSizes[_id];
230 ObjectVertex get dominator => new ObjectVertex._(_graph._doms[_id], _graph); 230 ObjectVertex get dominator => new ObjectVertex._(_graph._doms[_id], _graph);
231 231
232 int get shallowSize => _graph._shallowSizes[_id]; 232 int get shallowSize => _graph._shallowSizes[_id];
233 int get vmCid => _graph._cids[_id]; 233 int get vmCid => _graph._cids[_id];
234 234
(...skipping 30 matching lines...) Expand all
265 return strAddr; 265 return strAddr;
266 } 266 }
267 267
268 List<ObjectVertex> dominatorTreeChildren() { 268 List<ObjectVertex> dominatorTreeChildren() {
269 var N = _graph._N; 269 var N = _graph._N;
270 var doms = _graph._doms; 270 var doms = _graph._doms;
271 271
272 var parentId = _id; 272 var parentId = _id;
273 var domChildren = []; 273 var domChildren = [];
274 274
275 for (var childId = 1; childId <= N; childId++) { 275 for (var childId = ROOT; childId <= N; childId++) {
276 if (doms[childId] == parentId) { 276 if (doms[childId] == parentId) {
277 domChildren.add(new ObjectVertex._(childId, _graph)); 277 domChildren.add(new ObjectVertex._(childId, _graph));
278 } 278 }
279 } 279 }
280 280
281 return domChildren; 281 return domChildren;
282 } 282 }
283 } 283 }
284 284
285 // A node in the dominator tree where siblings with the same class are merged.
286 // That is, a set of objects with the same cid whose parent chains in the
287 // dominator tree have the same cids at each level. [id_] is the representative
288 // object of this set. The other members of the set are found by walking the
289 // mergedDomNext links until finding the sentinel node or a node with a
290 // different class.
291 class MergedObjectVertex {
292 final int _id;
293 final ObjectGraph _graph;
294
295 MergedObjectVertex._(this._id, this._graph);
296
297 bool get isRoot => ROOT == _id;
298
299 bool operator ==(other) => _id == other._id && _graph == other._graph;
300 int get hashCode => _id;
301
302 int get vmCid => _graph._cids[_id];
303
304 int get shallowSize {
305 var cids = _graph._cids;
306 var size = 0;
307 var sibling = _id;
308 while (sibling != SENTINEL &&
309 cids[sibling] == cids[_id]) {
310 size += _graph._shallowSizes[sibling];
311 sibling = _graph._mergedDomNext[sibling];
312 }
313 return size;
314 }
315 int get retainedSize {
316 var cids = _graph._cids;
317 var size = 0;
318 var sibling = _id;
319 while (sibling != SENTINEL &&
320 cids[sibling] == cids[_id]) {
321 size += _graph._retainedSizes[sibling];
322 sibling = _graph._mergedDomNext[sibling];
323 }
324 return size;
325 }
326 int get instanceCount {
327 var cids = _graph._cids;
328 var count = 0;
329 var sibling = _id;
330 while (sibling != SENTINEL &&
331 cids[sibling] == cids[_id]) {
332 count++;
333 sibling = _graph._mergedDomNext[sibling];
334 }
335 return count;
336 }
337
338 List<ObjectVertex> dominatorTreeChildren() {
339 var next = _graph._mergedDomNext;
340 var cids = _graph._cids;
341
342 var domChildren = [];
343 var prev = SENTINEL;
344 var child = _graph._mergedDomHead[_id];
345 // Walk the list of children and look for the representative objects, i.e.
346 // the first sibling of each cid.
347 while (child != SENTINEL) {
348 if (prev == SENTINEL ||
349 cids[prev] != cids[child]) {
350 domChildren.add(new MergedObjectVertex._(child, _graph));
351 }
352 prev = child;
353 child = next[child];
354 }
355
356 return domChildren;
357 }
358 }
359
285 class _SuccessorsIterable extends IterableBase<ObjectVertex> { 360 class _SuccessorsIterable extends IterableBase<ObjectVertex> {
286 final ObjectGraph _graph; 361 final ObjectGraph _graph;
287 final int _id; 362 final int _id;
288 363
289 _SuccessorsIterable(this._graph, this._id); 364 _SuccessorsIterable(this._graph, this._id);
290 365
291 Iterator<ObjectVertex> get iterator => new _SuccessorsIterator(_graph, _id); 366 Iterator<ObjectVertex> get iterator => new _SuccessorsIterator(_graph, _id);
292 } 367 }
293 368
294 class _SuccessorsIterator implements Iterator<ObjectVertex> { 369 class _SuccessorsIterator implements Iterator<ObjectVertex> {
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
329 404
330 _VerticesIterator(this._graph); 405 _VerticesIterator(this._graph);
331 406
332 bool moveNext() { 407 bool moveNext() {
333 if (_nextId == _graph._N) return false; 408 if (_nextId == _graph._N) return false;
334 current = new ObjectVertex._(_nextId++, _graph); 409 current = new ObjectVertex._(_nextId++, _graph);
335 return true; 410 return true;
336 } 411 }
337 } 412 }
338 413
414 const ROOT = 1;
Cutch 2016/11/15 14:50:42 move these to the top and add doc comments
rmacnak 2016/11/15 17:40:28 Done.
415 const SENTINEL = 0;
416
339 class ObjectGraph { 417 class ObjectGraph {
340 ObjectGraph(List<ByteData> chunks, int nodeCount) 418 ObjectGraph(List<ByteData> chunks, int nodeCount)
341 : this._chunks = chunks, 419 : this._chunks = chunks,
342 this._N = nodeCount; 420 this._N = nodeCount;
343 421
344 int get size => _size; 422 int get size => _size;
345 int get vertexCount => _N; 423 int get vertexCount => _N;
346 int get edgeCount => _E; 424 int get edgeCount => _E;
347 425
348 ObjectVertex get root => new ObjectVertex._(1, this); 426 ObjectVertex get root => new ObjectVertex._(ROOT, this);
427 MergedObjectVertex get mergedRoot => new MergedObjectVertex._(ROOT, this);
349 Iterable<ObjectVertex> get vertices => new _VerticesIterable(this); 428 Iterable<ObjectVertex> get vertices => new _VerticesIterable(this);
350 429
351 Iterable<ObjectVertex> getMostRetained({int classId, int limit}) { 430 Iterable<ObjectVertex> getMostRetained({int classId, int limit}) {
352 List<ObjectVertex> _mostRetained = 431 List<ObjectVertex> _mostRetained =
353 new List<ObjectVertex>.from(vertices.where((u) => !u.isRoot)); 432 new List<ObjectVertex>.from(vertices.where((u) => !u.isRoot));
354 _mostRetained.sort((u, v) => v.retainedSize - u.retainedSize); 433 _mostRetained.sort((u, v) => v.retainedSize - u.retainedSize);
355 434
356 var result = _mostRetained; 435 var result = _mostRetained;
357 if (classId != null) { 436 if (classId != null) {
358 result = result.where((u) => u.vmCid == classId); 437 result = result.where((u) => u.vmCid == classId);
(...skipping 15 matching lines...) Expand all
374 453
375 controller.add(["Remapping $_E references...", 15.0]); 454 controller.add(["Remapping $_E references...", 15.0]);
376 await new Future(() => _remapEdges()); 455 await new Future(() => _remapEdges());
377 456
378 _addrToId = null; 457 _addrToId = null;
379 _chunks = null; 458 _chunks = null;
380 459
381 controller.add(["Finding depth-first order...", 30.0]); 460 controller.add(["Finding depth-first order...", 30.0]);
382 await new Future(() => _dfs()); 461 await new Future(() => _dfs());
383 462
384 controller.add(["Finding predecessors...", 45.0]); 463 controller.add(["Finding predecessors...", 40.0]);
385 await new Future(() => _buildPredecessors()); 464 await new Future(() => _buildPredecessors());
386 465
387 controller.add(["Finding dominators...", 60.0]); 466 controller.add(["Finding dominators...", 50.0]);
388 await new Future(() => _buildDominators()); 467 await new Future(() => _buildDominators());
389 468
390 _firstPreds = null; 469 _firstPreds = null;
391 _preds = null; 470 _preds = null;
392 471
393 _semi = null; 472 _semi = null;
394 _parent = null; 473 _parent = null;
395 474
396 controller.add(["Finding retained sizes...", 75.0]); 475 controller.add(["Finding retained sizes...", 60.0]);
397 await new Future(() => _calculateRetainedSizes()); 476 await new Future(() => _calculateRetainedSizes());
398 477
399 _vertex = null; 478 _vertex = null;
400 479
401 controller.add(["Loaded", 100.0]); 480 controller.add(["Linking dominator tree children...", 70.0]);
481 await new Future(() => _linkDominatorChildren());
482
483 controller.add(["Sorting dominator tree children...", 80.0]);
484 await new Future(() => _sortDominatorChildren());
485
486 controller.add(["Merging dominator tree siblings...", 90.0]);
487 await new Future(() => _mergeDominatorSiblings());
488
489 controller.add(["Processed", 100.0]);
402 controller.close(); 490 controller.close();
403 }()); 491 }());
404 return controller.stream; 492 return controller.stream;
405 } 493 }
406 494
407 List<ByteData> _chunks; 495 List<ByteData> _chunks;
408 496
409 int _kObjectAlignment; 497 int _kObjectAlignment;
410 int _N; 498 int _N;
411 int _E; 499 int _E;
(...skipping 12 matching lines...) Expand all
424 AddressMapper _addrToId; 512 AddressMapper _addrToId;
425 Uint32List _vertex; 513 Uint32List _vertex;
426 Uint32List _parent; 514 Uint32List _parent;
427 Uint32List _semi; 515 Uint32List _semi;
428 Uint32List _firstPreds; // Offset into preds. 516 Uint32List _firstPreds; // Offset into preds.
429 Uint32List _preds; 517 Uint32List _preds;
430 518
431 // Outputs. 519 // Outputs.
432 Uint32List _doms; 520 Uint32List _doms;
433 Uint32List _retainedSizes; 521 Uint32List _retainedSizes;
522 Uint32List _mergedDomHead;
523 Uint32List _mergedDomNext;
434 524
435 void _remapNodes() { 525 void _remapNodes() {
436 var N = _N; 526 var N = _N;
437 var E = 0; 527 var E = 0;
438 var addrToId = new AddressMapper(N); 528 var addrToId = new AddressMapper(N);
439 529
440 var addressesHigh = new Uint32List(N + 1); 530 var addressesHigh = new Uint32List(N + 1);
441 var addressesLow = new Uint32List(N + 1); 531 var addressesLow = new Uint32List(N + 1);
442 var shallowSizes = new Uint32List(N + 1); 532 var shallowSizes = new Uint32List(N + 1);
443 var cids = new Uint16List(N + 1); 533 var cids = new Uint16List(N + 1);
444 534
445 var stream = new ReadStream(_chunks); 535 var stream = new ReadStream(_chunks);
446 stream.readUnsigned(); 536 stream.readUnsigned();
447 _kObjectAlignment = stream.clampedUint32; 537 _kObjectAlignment = stream.clampedUint32;
448 538
449 var id = 1; 539 var id = ROOT;
450 while (stream.pendingBytes > 0) { 540 while (stream.pendingBytes > 0) {
451 stream.readUnsigned(); // addr 541 stream.readUnsigned(); // addr
452 addrToId.put(stream.high, stream.mid, stream.low, id); 542 addrToId.put(stream.high, stream.mid, stream.low, id);
453 addressesHigh[id] = stream.highUint32; 543 addressesHigh[id] = stream.highUint32;
454 addressesLow[id] = stream.lowUint32; 544 addressesLow[id] = stream.lowUint32;
455 stream.readUnsigned(); // shallowSize 545 stream.readUnsigned(); // shallowSize
456 shallowSizes[id] = stream.clampedUint32; 546 shallowSizes[id] = stream.clampedUint32;
457 stream.readUnsigned(); // cid 547 stream.readUnsigned(); // cid
458 cids[id] = stream.clampedUint32; 548 cids[id] = stream.clampedUint32;
459 549
460 stream.readUnsigned(); 550 stream.readUnsigned();
461 while (!stream.isZero) { 551 while (!stream.isZero) {
462 E++; 552 E++;
463 stream.readUnsigned(); 553 stream.readUnsigned();
464 } 554 }
465 id++; 555 id++;
466 } 556 }
467 assert(id == (N + 1)); 557 assert(id == (N + 1));
468 558
469 var root = addrToId.get(0, 0, 0); 559 assert(ROOT == addrToId.get(0, 0, 0));
470 assert(root == 1);
471 560
472 _E = E; 561 _E = E;
473 _addrToId = addrToId; 562 _addrToId = addrToId;
474 _addressesLow = addressesLow; 563 _addressesLow = addressesLow;
475 _addressesHigh = addressesHigh; 564 _addressesHigh = addressesHigh;
476 _shallowSizes = shallowSizes; 565 _shallowSizes = shallowSizes;
477 _cids = cids; 566 _cids = cids;
478 } 567 }
479 568
480 void _remapEdges() { 569 void _remapEdges() {
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
527 616
528 var stackNodes = new Uint32List(N); 617 var stackNodes = new Uint32List(N);
529 var stackCurrentEdgePos = new Uint32List(N); 618 var stackCurrentEdgePos = new Uint32List(N);
530 619
531 var vertex = new Uint32List(N + 1); 620 var vertex = new Uint32List(N + 1);
532 var semi = new Uint32List(N + 1); 621 var semi = new Uint32List(N + 1);
533 var parent = new Uint32List(N + 1); 622 var parent = new Uint32List(N + 1);
534 var dfsNumber = 0; 623 var dfsNumber = 0;
535 624
536 var stackTop = 0; 625 var stackTop = 0;
537 var root = 1;
538 626
539 // Push root. 627 // Push root.
540 stackNodes[0] = root; 628 stackNodes[0] = ROOT;
541 stackCurrentEdgePos[0] = firstSuccs[root]; 629 stackCurrentEdgePos[0] = firstSuccs[ROOT];
542 630
543 while (stackTop >= 0) { 631 while (stackTop >= 0) {
544 var v = stackNodes[stackTop]; 632 var v = stackNodes[stackTop];
545 var edgePos = stackCurrentEdgePos[stackTop]; 633 var edgePos = stackCurrentEdgePos[stackTop];
546 634
547 if (semi[v] == 0) { 635 if (semi[v] == 0) {
548 // First visit. 636 // First visit.
549 dfsNumber++; 637 dfsNumber++;
550 semi[v] = dfsNumber; 638 semi[v] = dfsNumber;
551 vertex[dfsNumber] = v; 639 vertex[dfsNumber] = v;
(...skipping 12 matching lines...) Expand all
564 stackNodes[stackTop] = childId; 652 stackNodes[stackTop] = childId;
565 stackCurrentEdgePos[stackTop] = firstSuccs[childId]; 653 stackCurrentEdgePos[stackTop] = firstSuccs[childId];
566 } 654 }
567 } else { 655 } else {
568 // Done with all children. 656 // Done with all children.
569 stackTop--; 657 stackTop--;
570 } 658 }
571 } 659 }
572 660
573 assert(dfsNumber == N); 661 assert(dfsNumber == N);
574 for (var i = 1; i <= N; i++) { 662 for (var i = ROOT; i <= N; i++) {
575 assert(semi[i] != 0); 663 assert(semi[i] != SENTINEL);
576 } 664 }
577 assert(parent[1] == 0); 665 assert(parent[ROOT] == SENTINEL);
578 for (var i = 2; i <= N; i++) { 666 for (var i = ROOT + 1; i <= N; i++) {
579 assert(parent[i] != 0); 667 assert(parent[i] != SENTINEL);
580 } 668 }
581 669
582 _vertex = vertex; 670 _vertex = vertex;
583 _semi = semi; 671 _semi = semi;
584 _parent = parent; 672 _parent = parent;
585 } 673 }
586 674
587 void _buildPredecessors() { 675 void _buildPredecessors() {
588 var N = _N; 676 var N = _N;
589 var E = _E; 677 var E = _E;
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
629 preds[predIndex] = i; 717 preds[predIndex] = i;
630 } 718 }
631 } 719 }
632 720
633 _firstPreds = firstPreds; 721 _firstPreds = firstPreds;
634 _preds = preds; 722 _preds = preds;
635 } 723 }
636 724
637 static int _eval(int v, Uint32List ancestor, Uint32List semi, 725 static int _eval(int v, Uint32List ancestor, Uint32List semi,
638 Uint32List label, Uint32List stackNode, Uint8List stackState) { 726 Uint32List label, Uint32List stackNode, Uint8List stackState) {
639 if (ancestor[v] == 0) { 727 if (ancestor[v] == SENTINEL) {
640 return label[v]; 728 return label[v];
641 } else { 729 } else {
642 { 730 {
643 // Inlined 'compress' with an explicit stack to prevent JS stack 731 // Inlined 'compress' with an explicit stack to prevent JS stack
644 // overflow. 732 // overflow.
645 var top = 0; 733 var top = 0;
646 stackNode[top] = v; 734 stackNode[top] = v;
647 stackState[top] = 0; 735 stackState[top] = 0;
648 while (top >= 0) { 736 while (top >= 0) {
649 var v = stackNode[top]; 737 var v = stackNode[top];
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
712 // in a Flowgraph." 800 // in a Flowgraph."
713 void _buildDominators() { 801 void _buildDominators() {
714 var N = _N; 802 var N = _N;
715 803
716 var vertex = _vertex; 804 var vertex = _vertex;
717 var semi = _semi; 805 var semi = _semi;
718 var parent = _parent; 806 var parent = _parent;
719 var firstPreds = _firstPreds; 807 var firstPreds = _firstPreds;
720 var preds = _preds; 808 var preds = _preds;
721 809
722 var root = 1;
723 var dom = new Uint32List(N + 1); 810 var dom = new Uint32List(N + 1);
724 811
725 var ancestor = new Uint32List(N + 1); 812 var ancestor = new Uint32List(N + 1);
726 var label = new Uint32List(N + 1); 813 var label = new Uint32List(N + 1);
727 for (var i = 1; i <= N; i++) { 814 for (var i = 1; i <= N; i++) {
728 label[i] = i; 815 label[i] = i;
729 } 816 }
730 var buckets = new List(N + 1); 817 var buckets = new List(N + 1);
731 var child = new Uint32List(N + 1); 818 var child = new Uint32List(N + 1);
732 var size = new Uint32List(N + 1); 819 var size = new Uint32List(N + 1);
733 for (var i = 1; i <= N; i++) { 820 for (var i = 1; i <= N; i++) {
734 size[i] = 1; 821 size[i] = 1;
735 } 822 }
736 var stackNode = new Uint32List(N + 1); 823 var stackNode = new Uint32List(N + 1);
737 var stackState = new Uint8List(N + 1); 824 var stackState = new Uint8List(N + 1);
738 825
739 for (var i = N; i > 1; i--) { 826 for (var i = N; i > 1; i--) {
740 var w = vertex[i]; 827 var w = vertex[i];
741 assert(w != root); 828 assert(w != ROOT);
742 829
743 // Lengauer & Tarjan Step 2. 830 // Lengauer & Tarjan Step 2.
744 var startPred = firstPreds[w]; 831 var startPred = firstPreds[w];
745 var limitPred = firstPreds[w + 1]; 832 var limitPred = firstPreds[w + 1];
746 for (var predIndex = startPred; predIndex < limitPred; predIndex++) { 833 for (var predIndex = startPred; predIndex < limitPred; predIndex++) {
747 var v = preds[predIndex]; 834 var v = preds[predIndex];
748 var u = _eval(v, ancestor, semi, label, stackNode, stackState); 835 var u = _eval(v, ancestor, semi, label, stackNode, stackState);
749 if (semi[u] < semi[w]) { 836 if (semi[u] < semi[w]) {
750 semi[w] = semi[u]; 837 semi[w] = semi[u];
751 } 838 }
(...skipping 12 matching lines...) Expand all
764 tmp = parent[w]; 851 tmp = parent[w];
765 var bucket = buckets[tmp]; 852 var bucket = buckets[tmp];
766 buckets[tmp] = null; 853 buckets[tmp] = null;
767 if (bucket != null) { 854 if (bucket != null) {
768 for (var v in bucket) { 855 for (var v in bucket) {
769 var u = _eval(v, ancestor, semi, label, stackNode, stackState); 856 var u = _eval(v, ancestor, semi, label, stackNode, stackState);
770 dom[v] = semi[u] < semi[v] ? u : parent[w]; 857 dom[v] = semi[u] < semi[v] ? u : parent[w];
771 } 858 }
772 } 859 }
773 } 860 }
774 for (var i = 1; i <= N; i++) { 861 for (var i = ROOT; i <= N; i++) {
775 assert(buckets[i] == null); 862 assert(buckets[i] == null);
776 } 863 }
777 // Lengauer & Tarjan Step 4. 864 // Lengauer & Tarjan Step 4.
778 for (var i = 2; i <= N; i++) { 865 for (var i = 2; i <= N; i++) {
779 var w = vertex[i]; 866 var w = vertex[i];
780 if (dom[w] != vertex[semi[w]]) { 867 if (dom[w] != vertex[semi[w]]) {
781 dom[w] = dom[dom[w]]; 868 dom[w] = dom[dom[w]];
782 } 869 }
783 } 870 }
784 871
785 _doms = dom; 872 _doms = dom;
786 } 873 }
787 874
788 void _calculateRetainedSizes() { 875 void _calculateRetainedSizes() {
789 var N = _N; 876 var N = _N;
790 877
791 var size = 0; 878 var size = 0;
792 var shallowSizes = _shallowSizes; 879 var shallowSizes = _shallowSizes;
793 var vertex = _vertex; 880 var vertex = _vertex;
794 var doms = _doms; 881 var doms = _doms;
795 882
796 // Sum shallow sizes. 883 // Sum shallow sizes.
797 for (var i = 1; i < N; i++) { 884 for (var i = ROOT; i < N; i++) {
798 size += shallowSizes[i]; 885 size += shallowSizes[i];
799 } 886 }
800 887
801 // Start with retained size as shallow size. 888 // Start with retained size as shallow size.
802 var retainedSizes = new Uint32List.fromList(shallowSizes); 889 var retainedSizes = new Uint32List.fromList(shallowSizes);
803 890
804 // In post order (bottom up), add retained size to dominator's retained 891 // In post order (bottom up), add retained size to dominator's retained
805 // size, skipping root. 892 // size, skipping root.
806 for (var i = N; i > 1; i--) { 893 for (var i = N; i > 1; i--) {
807 var v = vertex[i]; 894 var v = vertex[i];
808 assert(v != 1); 895 assert(v != ROOT);
809 retainedSizes[doms[i]] += retainedSizes[i]; 896 retainedSizes[doms[i]] += retainedSizes[i];
810 } 897 }
811 898
812 _retainedSizes = retainedSizes; 899 _retainedSizes = retainedSizes;
813 _size = size; 900 _size = size;
814 } 901 }
902
903 // Build linked lists of the children for each node in the dominator tree.
904 void _linkDominatorChildren() {
905 var N = _N;
906 var doms = _doms;
907 var head = new Uint32List(N + 1);
908 var next = new Uint32List(N + 1);
909
910 for (var child = ROOT; child <= N; child++) {
911 var parent = doms[child];
912 next[child] = head[parent];
913 head[parent] = child;
914 }
915
916 _mergedDomHead = head;
917 _mergedDomNext = next;
918 }
919
920 // Merge the given lists according to the given key in ascending order.
921 // Returns the head of the merged list.
922 static int _mergeSorted(int head1, int head2,
923 Uint32List next, Uint16List key) {
924 var head = head1;
925 var beforeInsert = SENTINEL;
926 var afterInsert = head1;
927 var startInsert = head2;
928
929 while (startInsert != SENTINEL) {
930 while ((afterInsert != SENTINEL) &&
931 (key[afterInsert] <= key[startInsert])) {
932 beforeInsert = afterInsert;
933 afterInsert = next[beforeInsert];
934 }
935
936 var endInsert = startInsert;
937 var peek = next[endInsert];
938
939 while ((peek != SENTINEL) && (key[peek] < key[afterInsert])) {
940 endInsert = peek;
941 peek = next[endInsert];
942 }
943 assert(endInsert != SENTINEL);
944
945 if (beforeInsert == SENTINEL) {
946 head = startInsert;
947 } else {
948 next[beforeInsert] = startInsert;
949 }
950 next[endInsert] = afterInsert;
951
952 startInsert = peek;
953 beforeInsert = endInsert;
954 }
955
956 return head;
957 }
958
959 void _sortDominatorChildren() {
960 var N = _N;
961 var cids = _cids;
962 var head = _mergedDomHead;
963 var next = _mergedDomNext;
964
965 // Returns the new head of the sorted list.
966 int sort(int head) {
967 if (head == SENTINEL) return SENTINEL;
968 if (next[head] == SENTINEL) return head;
969
970 // Find the middle of the list.
971 int head1 = head;
972 int slow = head;
973 int fast = head;
974 while (next[fast] != SENTINEL &&
975 next[next[fast]] != SENTINEL) {
976 slow = next[slow];
977 fast = next[next[fast]];
978 }
979
980 // Split the list in half.
981 int head2 = next[slow];
982 next[slow] = SENTINEL;
983
984 // Recursively sort the sublists and merge.
985 assert(head1 != head2);
986 int newHead1 = sort(head1);
987 int newHead2 = sort(head2);
988 return _mergeSorted(newHead1, newHead2, next, cids);
989 }
990
991 // Sort all list of dominator tree children by cid.
992 for (var parent = ROOT; parent <= N; parent++) {
993 head[parent] = sort(head[parent]);
994 }
995 }
996
997 void _mergeDominatorSiblings() {
998 var N = _N;
999 var cids = _cids;
1000 var head = _mergedDomHead;
1001 var next = _mergedDomNext;
1002 var workStack = new Uint32List(N);
1003 var workStackTop = 0;
1004
1005 mergeChildrenAndSort(var parent1, var end) {
1006 assert(parent1 != SENTINEL);
1007 if (next[parent1] == end) return;
1008
1009 // Find the middle of the list.
1010 int cid = cids[parent1];
1011 int slow = parent1;
1012 int fast = parent1;
1013 while (next[fast] != end &&
1014 next[next[fast]] != end) {
1015 slow = next[slow];
1016 fast = next[next[fast]];
1017 }
1018
1019 int parent2 = next[slow];
1020
1021 assert(parent2 != SENTINEL);
1022 assert(parent1 != parent2);
1023 assert(cids[parent1] == cids[parent2]);
1024
1025 // Recursively sort the sublists.
1026 mergeChildrenAndSort(parent1, parent2);
1027 mergeChildrenAndSort(parent2, end);
1028
1029 // Merge sorted sublists.
1030 head[parent1] = _mergeSorted(head[parent1], head[parent2], next, cids);
1031
1032 // Children moved to parent1.
1033 head[parent2] = SENTINEL;
1034 }
1035
1036 // Push root.
1037 workStack[workStackTop++] = ROOT;
1038
1039 while (workStackTop > 0) {
1040 var parent = workStack[--workStackTop];
1041
1042 var prev = SENTINEL;
1043 var child = head[parent];
1044 while (child != SENTINEL) {
1045 // Push child.
1046 workStack[workStackTop++] = child;
1047
1048 // Find next sibling with a different cid.
1049 var after = child;
1050 while (after != SENTINEL &&
1051 cids[after] == cids[child]) {
1052 after = next[after];
1053 }
1054
1055 // From all the siblings between child and after, take their children,
1056 // merge them and given to child.
1057 mergeChildrenAndSort(child, after);
1058
1059 child = after;
1060 }
1061 }
1062 }
815 } 1063 }
OLDNEW
« no previous file with comments | « no previous file | runtime/observatory/lib/src/elements/heap_snapshot.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698