| 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 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 109 | 109 |
| 110 int get clampedUint32 { | 110 int get clampedUint32 { |
| 111 if (high != 0 || mid > 0xF) { | 111 if (high != 0 || mid > 0xF) { |
| 112 return 0xFFFFFFFF; | 112 return 0xFFFFFFFF; |
| 113 } else { | 113 } else { |
| 114 // Not shift as JS shifts are signed 32-bit. | 114 // Not shift as JS shifts are signed 32-bit. |
| 115 return mid * 0x10000000 + low; | 115 return mid * 0x10000000 + low; |
| 116 } | 116 } |
| 117 } | 117 } |
| 118 | 118 |
| 119 int get highUint32 { |
| 120 return high * (1 << 24) + (mid >> 4); |
| 121 } |
| 122 |
| 123 int get lowUint32 { |
| 124 return (mid & 0xF) * (1 << 28) + low; |
| 125 } |
| 126 |
| 119 bool get isZero { | 127 bool get isZero { |
| 120 return (high == 0) && (mid == 0) && (low == 0); | 128 return (high == 0) && (mid == 0) && (low == 0); |
| 121 } | 129 } |
| 122 | 130 |
| 123 void readUnsigned() { | 131 void readUnsigned() { |
| 124 low = 0; | 132 low = 0; |
| 125 mid = 0; | 133 mid = 0; |
| 126 high = 0; | 134 high = 0; |
| 127 | 135 |
| 128 // Low 28 bits. | 136 // Low 28 bits. |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 217 ObjectVertex._(this._id, this._graph); | 225 ObjectVertex._(this._id, this._graph); |
| 218 | 226 |
| 219 bool get isRoot => _id == 1; | 227 bool get isRoot => _id == 1; |
| 220 | 228 |
| 221 bool operator ==(other) => _id == other._id && _graph == other._graph; | 229 bool operator ==(other) => _id == other._id && _graph == other._graph; |
| 222 int get hashCode => _id; | 230 int get hashCode => _id; |
| 223 | 231 |
| 224 int get retainedSize => _graph._retainedSizes[_id]; | 232 int get retainedSize => _graph._retainedSizes[_id]; |
| 225 ObjectVertex get dominator => new ObjectVertex._(_graph._doms[_id], _graph); | 233 ObjectVertex get dominator => new ObjectVertex._(_graph._doms[_id], _graph); |
| 226 | 234 |
| 227 int get shallowSize { | 235 int get shallowSize => _graph._shallowSizes[_id]; |
| 228 var stream = new ReadStream(_graph._chunks); | 236 int get vmCid => _graph._cids[_id]; |
| 229 stream.position = _graph._positions[_id]; | |
| 230 stream.skipUnsigned(); // addr | |
| 231 stream.readUnsigned(); // shallowSize | |
| 232 return stream.clampedUint32; | |
| 233 } | |
| 234 | |
| 235 int get vmCid { | |
| 236 var stream = new ReadStream(_graph._chunks); | |
| 237 stream.position = _graph._positions[_id]; | |
| 238 stream.skipUnsigned(); // addr | |
| 239 stream.skipUnsigned(); // shallowSize | |
| 240 stream.readUnsigned(); // cid | |
| 241 return stream.clampedUint32; | |
| 242 } | |
| 243 | 237 |
| 244 get successors => new _SuccessorsIterable(_graph, _id); | 238 get successors => new _SuccessorsIterable(_graph, _id); |
| 245 | 239 |
| 246 String get address { | 240 String get address { |
| 247 // Note that everywhere else in this file, "address" really means an address | 241 // Note that everywhere else in this file, "address" really means an address |
| 248 // scaled down by kObjectAlignment. They were scaled down so they would fit | 242 // scaled down by kObjectAlignment. They were scaled down so they would fit |
| 249 // into Smis on the client. | 243 // into Smis on the client. |
| 250 var stream = new ReadStream(_graph._chunks); | |
| 251 stream.position = _graph._positions[_id]; | |
| 252 stream.readUnsigned(); | |
| 253 | 244 |
| 254 // Complicated way to do (high:mid:low * _kObjectAlignment).toHexString() | 245 var high32 = _graph._addressesHigh[_id]; |
| 246 var low32 = _graph._addressesLow[_id]; |
| 247 |
| 248 // Complicated way to do (high:low * _kObjectAlignment).toHexString() |
| 255 // without intermediate values exceeding int32. | 249 // without intermediate values exceeding int32. |
| 256 | 250 |
| 257 var strAddr = ""; | 251 var strAddr = ""; |
| 258 var carry = 0; | 252 var carry = 0; |
| 259 combine4(nibble) { | 253 combine4(nibble) { |
| 260 nibble = nibble * _graph._kObjectAlignment + carry; | 254 nibble = nibble * _graph._kObjectAlignment + carry; |
| 261 carry = nibble >> 4; | 255 carry = nibble >> 4; |
| 262 nibble = nibble & 0xF; | 256 nibble = nibble & 0xF; |
| 263 strAddr = nibble.toRadixString(16) + strAddr; | 257 strAddr = nibble.toRadixString(16) + strAddr; |
| 264 } | 258 } |
| 265 combine28(twentyEightBits) { | 259 combine32(thirtyTwoBits) { |
| 266 for (int shift = 0; shift < 28; shift += 4) { | 260 for (int shift = 0; shift < 32; shift += 4) { |
| 267 combine4((twentyEightBits >> shift) & 0xF); | 261 combine4((thirtyTwoBits >> shift) & 0xF); |
| 268 } | 262 } |
| 269 } | 263 } |
| 270 combine28(stream.low); | 264 combine32(low32); |
| 271 combine28(stream.mid); | 265 combine32(high32); |
| 272 combine28(stream.high); | |
| 273 return strAddr; | 266 return strAddr; |
| 274 } | 267 } |
| 275 | 268 |
| 276 List<ObjectVertex> dominatorTreeChildren() { | 269 List<ObjectVertex> dominatorTreeChildren() { |
| 277 var N = _graph._N; | 270 var N = _graph._N; |
| 278 var doms = _graph._doms; | 271 var doms = _graph._doms; |
| 279 | 272 |
| 280 var parentId = _id; | 273 var parentId = _id; |
| 281 var domChildren = []; | 274 var domChildren = []; |
| 282 | 275 |
| (...skipping 11 matching lines...) Expand all Loading... |
| 294 final ObjectGraph _graph; | 287 final ObjectGraph _graph; |
| 295 final int _id; | 288 final int _id; |
| 296 | 289 |
| 297 _SuccessorsIterable(this._graph, this._id); | 290 _SuccessorsIterable(this._graph, this._id); |
| 298 | 291 |
| 299 Iterator<ObjectVertex> get iterator => new _SuccessorsIterator(_graph, _id); | 292 Iterator<ObjectVertex> get iterator => new _SuccessorsIterator(_graph, _id); |
| 300 } | 293 } |
| 301 | 294 |
| 302 class _SuccessorsIterator implements Iterator<ObjectVertex> { | 295 class _SuccessorsIterator implements Iterator<ObjectVertex> { |
| 303 final ObjectGraph _graph; | 296 final ObjectGraph _graph; |
| 304 ReadStream _stream; | 297 int _nextSuccIndex; |
| 298 int _limitSuccIndex; |
| 305 | 299 |
| 306 ObjectVertex current; | 300 ObjectVertex current; |
| 307 | 301 |
| 308 _SuccessorsIterator(this._graph, int id) { | 302 _SuccessorsIterator(this._graph, int id) { |
| 309 _stream = new ReadStream(this._graph._chunks); | 303 _nextSuccIndex = _graph._firstSuccs[id]; |
| 310 _stream.position = _graph._positions[id]; | 304 _limitSuccIndex = _graph._firstSuccs[id + 1]; |
| 311 _stream.skipUnsigned(); // addr | |
| 312 _stream.skipUnsigned(); // shallowSize | |
| 313 _stream.skipUnsigned(); // cid | |
| 314 } | 305 } |
| 315 | 306 |
| 316 bool moveNext() { | 307 bool moveNext() { |
| 317 while (true) { | 308 if (_nextSuccIndex < _limitSuccIndex) { |
| 318 _stream.readUnsigned(); | 309 var succId = _graph._succs[_nextSuccIndex++]; |
| 319 if (_stream.isZero) return false; | 310 current = new ObjectVertex._(succId, _graph); |
| 320 var nextId = _graph._addrToId.get(_stream.high, _stream.mid, _stream.low); | |
| 321 if (nextId == null) continue; // Reference to VM isolate's heap. | |
| 322 current = new ObjectVertex._(nextId, _graph); | |
| 323 return true; | 311 return true; |
| 324 } | 312 } |
| 313 return false; |
| 325 } | 314 } |
| 326 } | 315 } |
| 327 | 316 |
| 328 class _VerticesIterable extends IterableBase<ObjectVertex> { | 317 class _VerticesIterable extends IterableBase<ObjectVertex> { |
| 329 final ObjectGraph _graph; | 318 final ObjectGraph _graph; |
| 330 | 319 |
| 331 _VerticesIterable(this._graph); | 320 _VerticesIterable(this._graph); |
| 332 | 321 |
| 333 Iterator<ObjectVertex> get iterator => new _VerticesIterator(_graph); | 322 Iterator<ObjectVertex> get iterator => new _VerticesIterator(_graph); |
| 334 } | 323 } |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 372 if (limit != null) { | 361 if (limit != null) { |
| 373 result = result.take(limit); | 362 result = result.take(limit); |
| 374 } | 363 } |
| 375 return result; | 364 return result; |
| 376 } | 365 } |
| 377 | 366 |
| 378 Future process(statusReporter) async { | 367 Future process(statusReporter) async { |
| 379 // We build futures here instead of marking the steps as async to avoid the | 368 // We build futures here instead of marking the steps as async to avoid the |
| 380 // heavy lifting being inside a transformed method. | 369 // heavy lifting being inside a transformed method. |
| 381 | 370 |
| 382 statusReporter.add("Finding node positions..."); | 371 statusReporter.add("Remapping $_N objects..."); |
| 383 await new Future(() => _buildPositions()); | 372 await new Future(() => _remapNodes()); |
| 373 |
| 374 statusReporter.add("Remapping $_E references..."); |
| 375 await new Future(() => _remapEdges()); |
| 376 |
| 377 _addrToId = null; |
| 378 _chunks = null; |
| 384 | 379 |
| 385 statusReporter.add("Finding post order..."); | 380 statusReporter.add("Finding post order..."); |
| 386 await new Future(() => _buildPostOrder()); | 381 await new Future(() => _buildPostOrder()); |
| 387 | 382 |
| 388 statusReporter.add("Finding predecessors..."); | 383 statusReporter.add("Finding predecessors..."); |
| 389 await new Future(() => _buildPredecessors()); | 384 await new Future(() => _buildPredecessors()); |
| 390 | 385 |
| 391 statusReporter.add("Finding dominators..."); | 386 statusReporter.add("Finding dominators..."); |
| 392 await new Future(() => _buildDominators()); | 387 await new Future(() => _buildDominators()); |
| 393 | 388 |
| 394 _firstPreds = null; | 389 _firstPreds = null; |
| 395 _preds = null; | 390 _preds = null; |
| 396 _postOrderIndices = null; | 391 _postOrderIndices = null; |
| 397 | 392 |
| 398 statusReporter.add("Finding retained sizes..."); | 393 statusReporter.add("Finding retained sizes..."); |
| 399 await new Future(() => _calculateRetainedSizes()); | 394 await new Future(() => _calculateRetainedSizes()); |
| 400 | 395 |
| 401 _postOrderOrdinals = null; | 396 _postOrderOrdinals = null; |
| 402 | 397 |
| 403 statusReporter.add("Loaded"); | 398 statusReporter.add("Loaded"); |
| 404 return this; | 399 return this; |
| 405 } | 400 } |
| 406 | 401 |
| 407 final List<ByteData> _chunks; | 402 List<ByteData> _chunks; |
| 408 | 403 |
| 409 int _kObjectAlignment; | 404 int _kObjectAlignment; |
| 410 int _N; | 405 int _N; |
| 411 int _E; | 406 int _E; |
| 412 int _size; | 407 int _size; |
| 413 | 408 |
| 409 // Indexed by node id, with id 0 representing invalid/uninitialized. |
| 410 // From snapshot. |
| 411 Uint16List _cids; |
| 412 Uint32List _shallowSizes; |
| 413 Uint32List _firstSuccs; |
| 414 Uint32List _succs; |
| 415 Uint32List _addressesLow; // No Uint64List in Javascript. |
| 416 Uint32List _addressesHigh; |
| 417 |
| 418 // Intermediates. |
| 414 AddressMapper _addrToId; | 419 AddressMapper _addrToId; |
| 415 | |
| 416 // Indexed by node id, with id 0 representing invalid/uninitialized. | |
| 417 Uint32List _positions; // Position of the node in the snapshot. | |
| 418 Uint32List _postOrderOrdinals; // post-order index -> id | 420 Uint32List _postOrderOrdinals; // post-order index -> id |
| 419 Uint32List _postOrderIndices; // id -> post-order index | 421 Uint32List _postOrderIndices; // id -> post-order index |
| 420 Uint32List _firstPreds; // Offset into preds. | 422 Uint32List _firstPreds; // Offset into preds. |
| 421 Uint32List _preds; | 423 Uint32List _preds; |
| 424 |
| 425 // Outputs. |
| 422 Uint32List _doms; | 426 Uint32List _doms; |
| 423 Uint32List _retainedSizes; | 427 Uint32List _retainedSizes; |
| 424 | 428 |
| 425 void _buildPositions() { | 429 void _remapNodes() { |
| 426 var N = _N; | 430 var N = _N; |
| 431 var E = 0; |
| 427 var addrToId = new AddressMapper(N); | 432 var addrToId = new AddressMapper(N); |
| 428 | 433 |
| 429 var positions = new Uint32List(N + 1); | 434 var addressesHigh = new Uint32List(N + 1); |
| 435 var addressesLow = new Uint32List(N + 1); |
| 436 var shallowSizes = new Uint32List(N + 1); |
| 437 var cids = new Uint16List(N + 1); |
| 430 | 438 |
| 431 var stream = new ReadStream(_chunks); | 439 var stream = new ReadStream(_chunks); |
| 432 stream.readUnsigned(); | 440 stream.readUnsigned(); |
| 433 _kObjectAlignment = stream.clampedUint32; | 441 _kObjectAlignment = stream.clampedUint32; |
| 434 | 442 |
| 435 var id = 1; | 443 var id = 1; |
| 436 while (stream.pendingBytes > 0) { | 444 while (stream.pendingBytes > 0) { |
| 437 positions[id] = stream.position; | |
| 438 stream.readUnsigned(); // addr | 445 stream.readUnsigned(); // addr |
| 439 addrToId.put(stream.high, stream.mid, stream.low, id); | 446 addrToId.put(stream.high, stream.mid, stream.low, id); |
| 440 stream.skipUnsigned(); // shallowSize | 447 addressesHigh[id] = stream.highUint32; |
| 441 stream.skipUnsigned(); // cid | 448 addressesLow[id] = stream.lowUint32; |
| 449 stream.readUnsigned(); // shallowSize |
| 450 shallowSizes[id] = stream.clampedUint32; |
| 451 stream.readUnsigned(); // cid |
| 452 cids[id] = stream.clampedUint32; |
| 442 | 453 |
| 443 stream.readUnsigned(); | 454 stream.readUnsigned(); |
| 444 while (!stream.isZero) { | 455 while (!stream.isZero) { |
| 456 E++; |
| 445 stream.readUnsigned(); | 457 stream.readUnsigned(); |
| 446 } | 458 } |
| 447 id++; | 459 id++; |
| 448 } | 460 } |
| 449 assert(id == (N + 1)); | 461 assert(id == (N + 1)); |
| 450 | 462 |
| 451 var root = addrToId.get(0, 0, 0); | 463 var root = addrToId.get(0, 0, 0); |
| 452 assert(root == 1); | 464 assert(root == 1); |
| 453 | 465 |
| 466 _E = E; |
| 454 _addrToId = addrToId; | 467 _addrToId = addrToId; |
| 455 _positions = positions; | 468 _addressesLow = addressesLow; |
| 469 _addressesHigh = addressesHigh; |
| 470 _shallowSizes = shallowSizes; |
| 471 _cids = cids; |
| 472 } |
| 473 |
| 474 void _remapEdges() { |
| 475 var N = _N; |
| 476 var E = _E; |
| 477 var addrToId = _addrToId; |
| 478 |
| 479 var firstSuccs = new Uint32List(N + 2); |
| 480 var succs = new Uint32List(E); |
| 481 |
| 482 var stream = new ReadStream(_chunks); |
| 483 stream.skipUnsigned(); // addr alignment |
| 484 |
| 485 var id = 1, edge = 0; |
| 486 while (stream.pendingBytes > 0) { |
| 487 stream.skipUnsigned(); // addr |
| 488 stream.skipUnsigned(); // shallowSize |
| 489 stream.skipUnsigned(); // cid |
| 490 |
| 491 firstSuccs[id] = edge; |
| 492 |
| 493 stream.readUnsigned(); |
| 494 while (!stream.isZero) { |
| 495 var childId = addrToId.get(stream.high, stream.mid, stream.low); |
| 496 if (childId != null) { |
| 497 succs[edge] = childId; |
| 498 edge++; |
| 499 } else { |
| 500 // Reference into VM isolate's heap. |
| 501 } |
| 502 stream.readUnsigned(); |
| 503 } |
| 504 id++; |
| 505 } |
| 506 firstSuccs[id] = edge; // Extra entry for cheap boundary detection. |
| 507 |
| 508 assert(id == N + 1); |
| 509 assert(edge <= E); // edge is smaller because E was computed before we knew |
| 510 // if references pointed into the VM isolate |
| 511 |
| 512 _E = edge; |
| 513 _firstSuccs = firstSuccs; |
| 514 _succs = succs; |
| 456 } | 515 } |
| 457 | 516 |
| 458 void _buildPostOrder() { | 517 void _buildPostOrder() { |
| 459 var N = _N; | 518 var N = _N; |
| 460 var E = 0; | 519 var E = _E; |
| 461 var addrToId = _addrToId; | 520 var firstSuccs = _firstSuccs; |
| 462 var positions = _positions; | 521 var succs = _succs; |
| 463 | 522 |
| 464 var postOrderOrdinals = new Uint32List(N); | 523 var postOrderOrdinals = new Uint32List(N); |
| 465 var postOrderIndices = new Uint32List(N + 1); | 524 var postOrderIndices = new Uint32List(N + 1); |
| 466 var stackNodes = new Uint32List(N); | 525 var stackNodes = new Uint32List(N); |
| 467 var stackCurrentEdgePos = new Uint32List(N); | 526 var stackCurrentEdgePos = new Uint32List(N); |
| 468 | 527 |
| 469 var visited = new Uint8List(N + 1); | 528 var visited = new Uint8List(N + 1); |
| 470 var postOrderIndex = 0; | 529 var postOrderIndex = 0; |
| 471 var stackTop = 0; | 530 var stackTop = 0; |
| 472 var root = 1; | 531 var root = 1; |
| 473 | 532 |
| 474 stackNodes[0] = root; | 533 stackNodes[0] = root; |
| 475 | 534 stackCurrentEdgePos[0] = firstSuccs[root]; |
| 476 var stream = new ReadStream(_chunks); | |
| 477 stream.position = positions[root]; | |
| 478 stream.skipUnsigned(); // addr | |
| 479 stream.skipUnsigned(); // shallowSize | |
| 480 stream.skipUnsigned(); // cid | |
| 481 stackCurrentEdgePos[0] = stream.position; | |
| 482 visited[root] = 1; | 535 visited[root] = 1; |
| 483 | 536 |
| 484 while (stackTop >= 0) { | 537 while (stackTop >= 0) { |
| 485 var n = stackNodes[stackTop]; | 538 var n = stackNodes[stackTop]; |
| 486 var edgePos = stackCurrentEdgePos[stackTop]; | 539 var edgePos = stackCurrentEdgePos[stackTop]; |
| 487 | 540 |
| 488 stream.position = edgePos; | 541 if (edgePos < firstSuccs[n + 1]) { |
| 489 stream.readUnsigned(); // childAddr | 542 var childId = succs[edgePos]; |
| 490 if (!stream.isZero) { | 543 edgePos++; |
| 491 stackCurrentEdgePos[stackTop] = stream.position; | 544 stackCurrentEdgePos[stackTop] = edgePos; |
| 492 var childId = addrToId.get(stream.high, stream.mid, stream.low); | |
| 493 if (childId == null) continue; // Reference to VM isolate's heap. | |
| 494 E++; | |
| 495 if (visited[childId] == 1) continue; | 545 if (visited[childId] == 1) continue; |
| 496 | 546 |
| 547 // Push child. |
| 497 stackTop++; | 548 stackTop++; |
| 498 stackNodes[stackTop] = childId; | 549 stackNodes[stackTop] = childId; |
| 499 | 550 edgePos = firstSuccs[childId]; |
| 500 stream.position = positions[childId]; | 551 stackCurrentEdgePos[stackTop] = edgePos; |
| 501 stream.skipUnsigned(); // addr | |
| 502 stream.skipUnsigned(); // shallowSize | |
| 503 stream.skipUnsigned(); // cid | |
| 504 stackCurrentEdgePos[stackTop] = stream.position; // i.e., first edge | |
| 505 visited[childId] = 1; | 552 visited[childId] = 1; |
| 506 } else { | 553 } else { |
| 507 // Done with all children. | 554 // Done with all children. |
| 508 postOrderIndices[n] = postOrderIndex; | 555 postOrderIndices[n] = postOrderIndex; |
| 509 postOrderOrdinals[postOrderIndex++] = n; | 556 postOrderOrdinals[postOrderIndex++] = n; |
| 510 stackTop--; | 557 stackTop--; |
| 511 } | 558 } |
| 512 } | 559 } |
| 513 | 560 |
| 514 assert(postOrderIndex == N); | 561 assert(postOrderIndex == N); |
| 515 assert(postOrderOrdinals[N - 1] == root); | 562 assert(postOrderOrdinals[N - 1] == root); |
| 516 | 563 |
| 517 _postOrderOrdinals = postOrderOrdinals; | 564 _postOrderOrdinals = postOrderOrdinals; |
| 518 _postOrderIndices = postOrderIndices; | 565 _postOrderIndices = postOrderIndices; |
| 519 _E = E; | 566 _E = E; |
| 520 } | 567 } |
| 521 | 568 |
| 522 void _buildPredecessors() { | 569 void _buildPredecessors() { |
| 523 var N = _N; | 570 var N = _N; |
| 524 var E = _E; | 571 var E = _E; |
| 525 var addrToId = _addrToId; | 572 var firstSuccs = _firstSuccs; |
| 526 var positions = _positions; | 573 var succs = _succs; |
| 527 | 574 |
| 528 // This is first filled with the predecessor counts, then reused to hold the | 575 // This is first filled with the predecessor counts, then reused to hold the |
| 529 // offset to the first predecessor (see alias below). | 576 // offset to the first predecessor (see alias below). |
| 530 // + 1 because 0 is a sentinel | 577 // + 1 because 0 is a sentinel |
| 531 // + 1 so the number of predecessors can be found from the difference with | 578 // + 1 so the number of predecessors can be found from the difference with |
| 532 // the next node's offset. | 579 // the next node's offset. |
| 533 var numPreds = new Uint32List(N + 2); | 580 var numPreds = new Uint32List(N + 2); |
| 534 var preds = new Uint32List(E); | 581 var preds = new Uint32List(E); |
| 535 | 582 |
| 536 // Count predecessors of each node. | 583 // Count predecessors of each node. |
| 537 var stream = new ReadStream(_chunks); | 584 for (var succIndex = 0; succIndex < E; succIndex++) { |
| 538 for (var i = 1; i <= N; i++) { | 585 var succId = succs[succIndex]; |
| 539 stream.position = positions[i]; | 586 numPreds[succId]++; |
| 540 stream.skipUnsigned(); // addr | |
| 541 stream.skipUnsigned(); // shallowSize | |
| 542 stream.skipUnsigned(); // cid | |
| 543 stream.readUnsigned(); // succAddr | |
| 544 while (!stream.isZero) { | |
| 545 var succId = addrToId.get(stream.high, stream.mid, stream.low); | |
| 546 if (succId != null) { | |
| 547 numPreds[succId]++; | |
| 548 } else { | |
| 549 // Reference to VM isolate's heap. | |
| 550 } | |
| 551 stream.readUnsigned(); // succAddr | |
| 552 } | |
| 553 } | 587 } |
| 554 | 588 |
| 555 // Assign indices into predecessors array. | 589 // Assign indices into predecessors array. |
| 556 var firstPreds = numPreds; // Alias. | 590 var firstPreds = numPreds; // Alias. |
| 557 var nextPreds = new Uint32List(N + 1); | 591 var nextPreds = new Uint32List(N + 1); |
| 558 var predIndex = 0; | 592 var predIndex = 0; |
| 559 for (var i = 1; i <= N; i++) { | 593 for (var i = 1; i <= N; i++) { |
| 560 var thisPredIndex = predIndex; | 594 var thisPredIndex = predIndex; |
| 561 predIndex += numPreds[i]; | 595 predIndex += numPreds[i]; |
| 562 firstPreds[i] = thisPredIndex; | 596 firstPreds[i] = thisPredIndex; |
| 563 nextPreds[i] = thisPredIndex; | 597 nextPreds[i] = thisPredIndex; |
| 564 } | 598 } |
| 565 assert(predIndex == E); | 599 assert(predIndex == E); |
| 566 firstPreds[N + 1] = E; // Extra entry for cheap boundary detection. | 600 firstPreds[N + 1] = E; // Extra entry for cheap boundary detection. |
| 567 | 601 |
| 568 // Fill predecessors array. | 602 // Fill predecessors array. |
| 569 for (var i = 1; i <= N; i++) { | 603 for (var i = 1; i <= N; i++) { |
| 570 stream.position = positions[i]; | 604 var startSuccIndex = firstSuccs[i]; |
| 571 stream.skipUnsigned(); // addr | 605 var limitSuccIndex = firstSuccs[i + 1]; |
| 572 stream.skipUnsigned(); // shallowSize | 606 for (var succIndex = startSuccIndex; |
| 573 stream.skipUnsigned(); // cid | 607 succIndex < limitSuccIndex; |
| 574 stream.readUnsigned(); // succAddr | 608 succIndex++) { |
| 575 while (!stream.isZero) { | 609 var succId = succs[succIndex]; |
| 576 var succId = addrToId.get(stream.high, stream.mid, stream.low); | 610 var predIndex = nextPreds[succId]++; |
| 577 if (succId != null) { | 611 preds[predIndex] = i; |
| 578 var predIndex = nextPreds[succId]++; | |
| 579 preds[predIndex] = i; | |
| 580 } else { | |
| 581 // Reference to VM isolate's heap. | |
| 582 } | |
| 583 stream.readUnsigned(); // succAddr | |
| 584 } | 612 } |
| 585 } | 613 } |
| 586 | 614 |
| 587 _firstPreds = firstPreds; | 615 _firstPreds = firstPreds; |
| 588 _preds = preds; | 616 _preds = preds; |
| 589 } | 617 } |
| 590 | 618 |
| 591 // "A Simple, Fast Dominance Algorithm" | 619 // "A Simple, Fast Dominance Algorithm" |
| 592 // Keith D. Cooper, Timothy J. Harvey, and Ken Kennedy | 620 // Keith D. Cooper, Timothy J. Harvey, and Ken Kennedy |
| 593 void _buildDominators() { | 621 void _buildDominators() { |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 667 | 695 |
| 668 domById[root] = 0; | 696 domById[root] = 0; |
| 669 | 697 |
| 670 _doms = domById; | 698 _doms = domById; |
| 671 } | 699 } |
| 672 | 700 |
| 673 void _calculateRetainedSizes() { | 701 void _calculateRetainedSizes() { |
| 674 var N = _N; | 702 var N = _N; |
| 675 | 703 |
| 676 var size = 0; | 704 var size = 0; |
| 677 var positions = _positions; | 705 var shallowSizes = _shallowSizes; |
| 678 var postOrderOrdinals = _postOrderOrdinals; | 706 var postOrderOrdinals = _postOrderOrdinals; |
| 679 var doms = _doms; | 707 var doms = _doms; |
| 680 var retainedSizes = new Uint32List(N + 1); | 708 |
| 709 // Sum shallow sizes. |
| 710 for (var i = 1; i < N; i++) { |
| 711 size += shallowSizes[i]; |
| 712 } |
| 681 | 713 |
| 682 // Start with retained size as shallow size. | 714 // Start with retained size as shallow size. |
| 683 var reader = new ReadStream(_chunks); | 715 var retainedSizes = new Uint32List.fromList(shallowSizes); |
| 684 for (var i = 1; i <= N; i++) { | |
| 685 reader.position = positions[i]; | |
| 686 reader.skipUnsigned(); // addr | |
| 687 reader.readUnsigned(); // shallowSize | |
| 688 var shallowSize = reader.clampedUint32; | |
| 689 retainedSizes[i] = shallowSize; | |
| 690 size += shallowSize; | |
| 691 } | |
| 692 | 716 |
| 693 // In post order (bottom up), add retained size to dominator's retained | 717 // In post order (bottom up), add retained size to dominator's retained |
| 694 // size, skipping root. | 718 // size, skipping root. |
| 695 for (var o = 0; o < (N - 1); o++) { | 719 for (var o = 0; o < (N - 1); o++) { |
| 696 var i = postOrderOrdinals[o]; | 720 var i = postOrderOrdinals[o]; |
| 697 assert(i != 1); | 721 assert(i != 1); |
| 698 retainedSizes[doms[i]] += retainedSizes[i]; | 722 retainedSizes[doms[i]] += retainedSizes[i]; |
| 699 } | 723 } |
| 700 | 724 |
| 701 _retainedSizes = retainedSizes; | 725 _retainedSizes = retainedSizes; |
| 702 _size = size; | 726 _size = size; |
| 703 } | 727 } |
| 704 } | 728 } |
| OLD | NEW |