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

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