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 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 220 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 231 bool get isRoot => ROOT == _id; | 231 bool get isRoot => ROOT == _id; |
| 232 bool get isStack => vmCid == _graph._kStackCid; | 232 bool get isStack => vmCid == _graph._kStackCid; |
| 233 | 233 |
| 234 bool operator ==(other) => _id == other._id && _graph == other._graph; | 234 bool operator ==(other) => _id == other._id && _graph == other._graph; |
| 235 int get hashCode => _id; | 235 int get hashCode => _id; |
| 236 | 236 |
| 237 int get retainedSize => _graph._retainedSizes[_id]; | 237 int get retainedSize => _graph._retainedSizes[_id]; |
| 238 ObjectVertex get dominator => new ObjectVertex._(_graph._doms[_id], _graph); | 238 ObjectVertex get dominator => new ObjectVertex._(_graph._doms[_id], _graph); |
| 239 | 239 |
| 240 int get shallowSize => _graph._shallowSizes[_id]; | 240 int get shallowSize => _graph._shallowSizes[_id]; |
| 241 int get externalSize => _graph._externalSizes[_id]; | |
| 241 int get vmCid => _graph._cids[_id]; | 242 int get vmCid => _graph._cids[_id]; |
| 242 | 243 |
| 243 get successors => new _SuccessorsIterable(_graph, _id); | 244 get successors => new _SuccessorsIterable(_graph, _id); |
| 244 | 245 |
| 245 String get address { | 246 String get address { |
| 246 // Note that everywhere else in this file, "address" really means an address | 247 // Note that everywhere else in this file, "address" really means an address |
| 247 // scaled down by kObjectAlignment. They were scaled down so they would fit | 248 // scaled down by kObjectAlignment. They were scaled down so they would fit |
| 248 // into Smis on the client. | 249 // into Smis on the client. |
| 249 | 250 |
| 250 var high32 = _graph._addressesHigh[_id]; | 251 var high32 = _graph._addressesHigh[_id]; |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 314 var cids = _graph._cids; | 315 var cids = _graph._cids; |
| 315 var size = 0; | 316 var size = 0; |
| 316 var sibling = _id; | 317 var sibling = _id; |
| 317 while (sibling != SENTINEL && cids[sibling] == cids[_id]) { | 318 while (sibling != SENTINEL && cids[sibling] == cids[_id]) { |
| 318 size += _graph._shallowSizes[sibling]; | 319 size += _graph._shallowSizes[sibling]; |
| 319 sibling = _graph._mergedDomNext[sibling]; | 320 sibling = _graph._mergedDomNext[sibling]; |
| 320 } | 321 } |
| 321 return size; | 322 return size; |
| 322 } | 323 } |
| 323 | 324 |
| 325 int get externalSize { | |
| 326 var cids = _graph._cids; | |
| 327 var size = 0; | |
| 328 var sibling = _id; | |
| 329 while (sibling != SENTINEL && cids[sibling] == cids[_id]) { | |
| 330 size += _graph._externalSizes[sibling]; | |
| 331 sibling = _graph._mergedDomNext[sibling]; | |
| 332 } | |
| 333 return size; | |
| 334 } | |
| 335 | |
| 324 int get retainedSize { | 336 int get retainedSize { |
| 325 var cids = _graph._cids; | 337 var cids = _graph._cids; |
| 326 var size = 0; | 338 var size = 0; |
| 327 var sibling = _id; | 339 var sibling = _id; |
| 328 while (sibling != SENTINEL && cids[sibling] == cids[_id]) { | 340 while (sibling != SENTINEL && cids[sibling] == cids[_id]) { |
| 329 size += _graph._retainedSizes[sibling]; | 341 size += _graph._retainedSizes[sibling]; |
| 330 sibling = _graph._mergedDomNext[sibling]; | 342 sibling = _graph._mergedDomNext[sibling]; |
| 331 } | 343 } |
| 332 return size; | 344 return size; |
| 333 } | 345 } |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 416 current = new ObjectVertex._(_nextId++, _graph); | 428 current = new ObjectVertex._(_nextId++, _graph); |
| 417 return true; | 429 return true; |
| 418 } | 430 } |
| 419 } | 431 } |
| 420 | 432 |
| 421 class ObjectGraph { | 433 class ObjectGraph { |
| 422 ObjectGraph(List<ByteData> chunks, int nodeCount) | 434 ObjectGraph(List<ByteData> chunks, int nodeCount) |
| 423 : this._chunks = chunks, | 435 : this._chunks = chunks, |
| 424 this._N = nodeCount; | 436 this._N = nodeCount; |
| 425 | 437 |
| 426 int get size => _size; | 438 int get internalSize => _internalSize; |
| 439 int get externalSize => _externalSize; | |
| 427 int get vertexCount => _N; | 440 int get vertexCount => _N; |
| 428 int get edgeCount => _E; | 441 int get edgeCount => _E; |
| 429 | 442 |
| 430 ObjectVertex get root => new ObjectVertex._(ROOT, this); | 443 ObjectVertex get root => new ObjectVertex._(ROOT, this); |
| 431 MergedObjectVertex get mergedRoot => new MergedObjectVertex._(ROOT, this); | 444 MergedObjectVertex get mergedRoot => new MergedObjectVertex._(ROOT, this); |
| 432 Iterable<ObjectVertex> get vertices => new _VerticesIterable(this); | 445 Iterable<ObjectVertex> get vertices => new _VerticesIterable(this); |
| 433 | 446 |
| 434 Iterable<ObjectVertex> getMostRetained({int classId, int limit}) { | 447 Iterable<ObjectVertex> getMostRetained({int classId, int limit}) { |
| 435 List<ObjectVertex> _mostRetained = | 448 List<ObjectVertex> _mostRetained = |
| 436 new List<ObjectVertex>.from(vertices.where((u) => !u.isRoot)); | 449 new List<ObjectVertex>.from(vertices.where((u) => !u.isRoot)); |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 496 return controller.stream; | 509 return controller.stream; |
| 497 } | 510 } |
| 498 | 511 |
| 499 List<ByteData> _chunks; | 512 List<ByteData> _chunks; |
| 500 | 513 |
| 501 int _kObjectAlignment; | 514 int _kObjectAlignment; |
| 502 int _kStackCid; | 515 int _kStackCid; |
| 503 int _N; // Objects in the snapshot. | 516 int _N; // Objects in the snapshot. |
| 504 int _Nconnected; // Objects reachable from root. | 517 int _Nconnected; // Objects reachable from root. |
| 505 int _E; // References in the snapshot. | 518 int _E; // References in the snapshot. |
| 506 int _size; | 519 int _internalSize; |
| 520 int _externalSize; | |
| 507 | 521 |
| 508 // Indexed by node id, with id 0 representing invalid/uninitialized. | 522 // Indexed by node id, with id 0 representing invalid/uninitialized. |
| 509 // From snapshot. | 523 // From snapshot. |
| 510 Uint16List _cids; | 524 Uint16List _cids; |
| 511 Uint32List _shallowSizes; | 525 Uint32List _shallowSizes; |
| 526 Uint32List _externalSizes; | |
| 512 Uint32List _firstSuccs; | 527 Uint32List _firstSuccs; |
| 513 Uint32List _succs; | 528 Uint32List _succs; |
| 514 Uint32List _addressesLow; // No Uint64List in Javascript. | 529 Uint32List _addressesLow; // No Uint64List in Javascript. |
| 515 Uint32List _addressesHigh; | 530 Uint32List _addressesHigh; |
| 516 | 531 |
| 517 // Intermediates. | 532 // Intermediates. |
| 518 AddressMapper _addrToId; | 533 AddressMapper _addrToId; |
| 519 Uint32List _vertex; | 534 Uint32List _vertex; |
| 520 Uint32List _parent; | 535 Uint32List _parent; |
| 521 Uint32List _semi; | 536 Uint32List _semi; |
| 522 Uint32List _firstPreds; // Offset into preds. | 537 Uint32List _firstPreds; // Offset into preds. |
| 523 Uint32List _preds; | 538 Uint32List _preds; |
| 524 | 539 |
| 525 // Outputs. | 540 // Outputs. |
| 526 Uint32List _doms; | 541 Uint32List _doms; |
| 527 Uint32List _retainedSizes; | 542 Uint32List _retainedSizes; |
| 528 Uint32List _mergedDomHead; | 543 Uint32List _mergedDomHead; |
| 529 Uint32List _mergedDomNext; | 544 Uint32List _mergedDomNext; |
| 530 | 545 |
| 531 void _remapNodes() { | 546 void _remapNodes() { |
| 532 var N = _N; | 547 var N = _N; |
| 533 var E = 0; | 548 var E = 0; |
| 534 var addrToId = new AddressMapper(N); | 549 var addrToId = new AddressMapper(N); |
| 535 | 550 |
| 536 var addressesHigh = new Uint32List(N + 1); | 551 var addressesHigh = new Uint32List(N + 1); |
| 537 var addressesLow = new Uint32List(N + 1); | 552 var addressesLow = new Uint32List(N + 1); |
| 538 var shallowSizes = new Uint32List(N + 1); | 553 var shallowSizes = new Uint32List(N + 1); |
| 554 var externalSizes = new Uint32List(N + 1); | |
| 539 var cids = new Uint16List(N + 1); | 555 var cids = new Uint16List(N + 1); |
| 540 | 556 |
| 541 var stream = new ReadStream(_chunks); | 557 var stream = new ReadStream(_chunks); |
| 542 stream.readUnsigned(); | 558 stream.readUnsigned(); |
| 543 _kObjectAlignment = stream.clampedUint32; | 559 _kObjectAlignment = stream.clampedUint32; |
| 544 stream.readUnsigned(); | 560 stream.readUnsigned(); |
| 545 _kStackCid = stream.clampedUint32; | 561 _kStackCid = stream.clampedUint32; |
| 546 | 562 |
| 547 var id = ROOT; | 563 var id = ROOT; |
| 548 while (stream.pendingBytes > 0) { | 564 while (id <= N) { |
| 549 stream.readUnsigned(); // addr | 565 stream.readUnsigned(); // addr |
| 550 addrToId.put(stream.high, stream.mid, stream.low, id); | 566 addrToId.put(stream.high, stream.mid, stream.low, id); |
| 551 addressesHigh[id] = stream.highUint32; | 567 addressesHigh[id] = stream.highUint32; |
| 552 addressesLow[id] = stream.lowUint32; | 568 addressesLow[id] = stream.lowUint32; |
| 553 stream.readUnsigned(); // shallowSize | 569 stream.readUnsigned(); // shallowSize |
| 554 shallowSizes[id] = stream.clampedUint32; | 570 shallowSizes[id] = stream.clampedUint32; |
| 555 stream.readUnsigned(); // cid | 571 stream.readUnsigned(); // cid |
| 556 cids[id] = stream.clampedUint32; | 572 cids[id] = stream.clampedUint32; |
| 557 | 573 |
| 558 stream.readUnsigned(); | 574 stream.readUnsigned(); |
| 559 while (!stream.isZero) { | 575 while (!stream.isZero) { |
| 560 E++; | 576 E++; |
| 561 stream.readUnsigned(); | 577 stream.readUnsigned(); |
| 562 } | 578 } |
| 563 id++; | 579 id++; |
| 564 } | 580 } |
| 565 assert(id == (N + 1)); | 581 assert(id == (N + 1)); |
|
cbernaschina
2017/08/28 16:15:18
Is this assertion still needed?
rmacnak
2017/08/28 17:08:20
No, this isn't useful anymore. Removed.
| |
| 566 | 582 |
| 567 assert(ROOT == addrToId.get(0, 0, 0)); | 583 assert(ROOT == addrToId.get(0, 0, 0)); |
| 568 | 584 |
| 585 stream.readUnsigned(); | |
| 586 assert(stream.isZero); | |
| 587 | |
| 588 stream.readUnsigned(); // addr | |
| 589 while (!stream.isZero) { | |
| 590 var nodeId = addrToId.get(stream.high, stream.mid, stream.low); | |
| 591 stream.readUnsigned(); // externalSize | |
| 592 externalSizes[nodeId] += stream.clampedUint32; | |
| 593 | |
| 594 stream.readUnsigned(); // addr | |
| 595 } | |
| 596 | |
| 569 _E = E; | 597 _E = E; |
| 570 _addrToId = addrToId; | 598 _addrToId = addrToId; |
| 571 _addressesLow = addressesLow; | 599 _addressesLow = addressesLow; |
| 572 _addressesHigh = addressesHigh; | 600 _addressesHigh = addressesHigh; |
| 573 _shallowSizes = shallowSizes; | 601 _shallowSizes = shallowSizes; |
| 602 _externalSizes = externalSizes; | |
| 574 _cids = cids; | 603 _cids = cids; |
| 575 } | 604 } |
| 576 | 605 |
| 577 void _remapEdges() { | 606 void _remapEdges() { |
| 578 var N = _N; | 607 var N = _N; |
| 579 var E = _E; | 608 var E = _E; |
| 580 var addrToId = _addrToId; | 609 var addrToId = _addrToId; |
| 581 | 610 |
| 582 var firstSuccs = new Uint32List(N + 2); | 611 var firstSuccs = new Uint32List(N + 2); |
| 583 var succs = new Uint32List(E); | 612 var succs = new Uint32List(E); |
| 584 | 613 |
| 585 var stream = new ReadStream(_chunks); | 614 var stream = new ReadStream(_chunks); |
| 586 stream.skipUnsigned(); // kObjectAlignment | 615 stream.skipUnsigned(); // kObjectAlignment |
| 587 stream.skipUnsigned(); // kStackCid | 616 stream.skipUnsigned(); // kStackCid |
| 588 | 617 |
| 589 var id = 1, edge = 0; | 618 var id = 1, edge = 0; |
| 590 while (stream.pendingBytes > 0) { | 619 while (id <= N) { |
| 591 stream.skipUnsigned(); // addr | 620 stream.skipUnsigned(); // addr |
| 592 stream.skipUnsigned(); // shallowSize | 621 stream.skipUnsigned(); // shallowSize |
| 593 stream.skipUnsigned(); // cid | 622 stream.skipUnsigned(); // cid |
| 594 | 623 |
| 595 firstSuccs[id] = edge; | 624 firstSuccs[id] = edge; |
| 596 | 625 |
| 597 stream.readUnsigned(); | 626 stream.readUnsigned(); |
| 598 while (!stream.isZero) { | 627 while (!stream.isZero) { |
| 599 var childId = addrToId.get(stream.high, stream.mid, stream.low); | 628 var childId = addrToId.get(stream.high, stream.mid, stream.low); |
| 600 if (childId != null) { | 629 if (childId != null) { |
| (...skipping 307 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 908 var w = vertex[i]; | 937 var w = vertex[i]; |
| 909 if (dom[w] != vertex[semi[w]]) { | 938 if (dom[w] != vertex[semi[w]]) { |
| 910 dom[w] = dom[dom[w]]; | 939 dom[w] = dom[dom[w]]; |
| 911 } | 940 } |
| 912 } | 941 } |
| 913 | 942 |
| 914 _doms = dom; | 943 _doms = dom; |
| 915 } | 944 } |
| 916 | 945 |
| 917 void _calculateRetainedSizes() { | 946 void _calculateRetainedSizes() { |
| 947 var N = _N; | |
| 918 var Nconnected = _Nconnected; | 948 var Nconnected = _Nconnected; |
| 919 | 949 |
| 920 var size = 0; | 950 var internalSize = 0; |
| 951 var externalSize = 0; | |
| 921 var shallowSizes = _shallowSizes; | 952 var shallowSizes = _shallowSizes; |
| 953 var externalSizes = _externalSizes; | |
| 922 var vertex = _vertex; | 954 var vertex = _vertex; |
| 923 var doms = _doms; | 955 var doms = _doms; |
| 924 | 956 |
| 925 // Sum shallow sizes. | 957 // Sum internal and external sizes. |
| 926 for (var i = 1; i <= Nconnected; i++) { | 958 for (var i = 1; i <= Nconnected; i++) { |
| 927 var v = vertex[i]; | 959 var v = vertex[i]; |
| 928 size += shallowSizes[v]; | 960 internalSize += shallowSizes[v]; |
| 961 externalSize += externalSizes[v]; | |
| 929 } | 962 } |
| 930 | 963 |
| 931 // Start with retained size as shallow size. | 964 // Start with retained size as shallow size + external size. |
| 932 var retainedSizes = new Uint32List.fromList(shallowSizes); | 965 var retainedSizes = new Uint32List(N + 1); |
| 966 for (var i = 0; i < N + 1; i++) { | |
| 967 retainedSizes[i] = shallowSizes[i] + externalSizes[i]; | |
| 968 } | |
| 933 | 969 |
| 934 // In post order (bottom up), add retained size to dominator's retained | 970 // In post order (bottom up), add retained size to dominator's retained |
| 935 // size, skipping root. | 971 // size, skipping root. |
| 936 for (var i = Nconnected; i > 1; i--) { | 972 for (var i = Nconnected; i > 1; i--) { |
| 937 var v = vertex[i]; | 973 var v = vertex[i]; |
| 938 assert(v != ROOT); | 974 assert(v != ROOT); |
| 939 retainedSizes[doms[v]] += retainedSizes[v]; | 975 retainedSizes[doms[v]] += retainedSizes[v]; |
| 940 } | 976 } |
| 941 | 977 |
| 942 assert(retainedSizes[ROOT] == size); // Root retains everything. | 978 // Root retains everything. |
| 979 assert(retainedSizes[ROOT] == (internalSize + externalSize)); | |
| 943 | 980 |
| 944 _retainedSizes = retainedSizes; | 981 _retainedSizes = retainedSizes; |
| 945 _size = size; | 982 _internalSize = internalSize; |
| 983 _externalSize = externalSize; | |
| 946 } | 984 } |
| 947 | 985 |
| 948 // Build linked lists of the children for each node in the dominator tree. | 986 // Build linked lists of the children for each node in the dominator tree. |
| 949 void _linkDominatorChildren() { | 987 void _linkDominatorChildren() { |
| 950 var N = _N; | 988 var N = _N; |
| 951 var doms = _doms; | 989 var doms = _doms; |
| 952 var head = new Uint32List(N + 1); | 990 var head = new Uint32List(N + 1); |
| 953 var next = new Uint32List(N + 1); | 991 var next = new Uint32List(N + 1); |
| 954 | 992 |
| 955 for (var child = ROOT; child <= N; child++) { | 993 for (var child = ROOT; child <= N; child++) { |
| (...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1094 | 1132 |
| 1095 // From all the siblings between child and after, take their children, | 1133 // From all the siblings between child and after, take their children, |
| 1096 // merge them and given to child. | 1134 // merge them and given to child. |
| 1097 mergeChildrenAndSort(child, after); | 1135 mergeChildrenAndSort(child, after); |
| 1098 | 1136 |
| 1099 child = after; | 1137 child = after; |
| 1100 } | 1138 } |
| 1101 } | 1139 } |
| 1102 } | 1140 } |
| 1103 } | 1141 } |
| OLD | NEW |