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 |
11 import 'package:logging/logging.dart'; | 11 import 'package:logging/logging.dart'; |
12 | 12 |
13 // Map<[uint32, uint32, uint32], uint32> | |
14 class AddressMapper { | |
15 final Uint32List _table; | |
16 | |
17 // * 4 ~/3 for 75% load factor | |
18 // * 4 for four-tuple entries | |
19 AddressMapper(int N) : _table = new Uint32List((N * 4 ~/ 3) * 4); | |
20 | |
21 // Jenkin's smi hash. | |
22 static int combine(int hash, int value) { | |
23 hash = 0x1fffffff & (hash + value); | |
24 hash = 0x1fffffff & (hash + ((0x0007ffff & hash) << 10)); | |
25 return hash ^ (hash >> 6); | |
26 } | |
27 | |
28 static int finish(int hash) { | |
29 hash = 0x1fffffff & (hash + ((0x03ffffff & hash) << 3)); | |
30 hash = hash ^ (hash >> 11); | |
31 return 0x1fffffff & (hash + ((0x00003fff & hash) << 15)); | |
32 } | |
33 | |
34 static int hash3(a, b, c) => finish(combine(combine(combine(0, a), b), c)); | |
35 | |
36 int scanFor(int high, int mid, int low) { | |
37 var hash = hash3(high, mid, low); | |
38 var start = (hash % _table.length) & ~3; | |
39 var index = start; | |
40 do { | |
41 if (_table[index + 3] == 0) return index; | |
42 if (_table[index] == high && | |
43 _table[index + 1] == mid && | |
44 _table[index + 2] == low) return index; | |
45 index = (index + 4) % _table.length; | |
46 } while (index != start); | |
47 | |
48 throw new Exception("Interal error: table full"); | |
49 } | |
50 | |
51 int get(int high, int mid, int low) { | |
52 int index = scanFor(high, mid, low); | |
53 if (_table[index + 3] == 0) return null; | |
54 return _table[index + 3]; | |
55 } | |
56 | |
57 int put(int high, int mid, int low, int id) { | |
58 if (id == 0) throw new Exception("Invalid error: invalid key"); | |
59 | |
60 int index = scanFor(high, mid, low); | |
61 if ((_table[index + 3] != 0)) { | |
62 throw new Exception("Internal error: attempt to overwrite key"); | |
63 } | |
64 _table[index] = high; | |
65 _table[index + 1] = mid; | |
66 _table[index + 2] = low; | |
67 _table[index + 3] = id; | |
68 } | |
69 } | |
70 | |
71 | |
13 // Port of dart::ReadStream from vm/datastream.h. | 72 // Port of dart::ReadStream from vm/datastream.h. |
14 class _ReadStream { | 73 class _ReadStream { |
15 int position = 0; | 74 int position = 0; |
16 int _size = 0; | 75 int _size = 0; |
17 final List<ByteData> _chunks; | 76 final List<ByteData> _chunks; |
18 | 77 |
19 _ReadStream(this._chunks) { | 78 _ReadStream(this._chunks) { |
20 int n = _chunks.length; | 79 int n = _chunks.length; |
21 for (var i = 0; i < n; i++) { | 80 for (var i = 0; i < n; i++) { |
22 var chunk = _chunks[i]; | 81 var chunk = _chunks[i]; |
23 if (i + 1 != n) { | 82 if (i + 1 != n) { |
24 assert(chunk.lengthInBytes == (1 << 20)); | 83 assert(chunk.lengthInBytes == (1 << 20)); |
25 } | 84 } |
26 _size += chunk.lengthInBytes; | 85 _size += chunk.lengthInBytes; |
27 } | 86 } |
28 } | 87 } |
29 | 88 |
30 int get pendingBytes => _size - position; | 89 int get pendingBytes => _size - position; |
31 | 90 |
32 int getUint8(i) { | 91 int getUint8(i) { |
33 return _chunks[i >> 20].getUint8(i & 0xFFFFF); | 92 return _chunks[i >> 20].getUint8(i & 0xFFFFF); |
34 } | 93 } |
35 | 94 |
36 int readUnsigned() { | 95 int low = 0; |
37 int result = 0; | 96 int mid = 0; |
38 int shift = 0; | 97 int high = 0; |
39 while (getUint8(position) <= maxUnsignedDataPerByte) { | 98 |
40 result |= getUint8(position) << shift; | 99 int get smallValue { |
41 shift += dataBitsPerByte; | 100 assert(high == 0); |
42 position++; | 101 assert(mid == 0); |
102 return (high << 56) | (mid << 28) | low; | |
sra1
2015/07/01 17:09:33
why do this when they are zero?
You can get corre
rmacnak
2015/07/07 23:19:05
The intent was to still allow large values on Dart
| |
103 } | |
104 | |
105 bool get isZero { | |
106 return (high == 0) && (mid == 0) && (low == 0); | |
107 } | |
108 | |
109 void readUnsigned() { | |
110 low = 0; | |
111 mid = 0; | |
112 high = 0; | |
113 | |
114 // Low 28 bits. | |
115 var digit = getUint8(position++); | |
116 if (digit > maxUnsignedDataPerByte) { | |
117 low |= (digit & byteMask << 0); | |
118 return; | |
43 } | 119 } |
44 result |= (getUint8(position) & byteMask) << shift; | 120 low |= (digit << 0); |
45 position++; | 121 |
46 return result; | 122 digit = getUint8(position++); |
123 if (digit > maxUnsignedDataPerByte) { | |
124 low |= ((digit & byteMask) << 7); | |
125 return; | |
126 } | |
127 low |= (digit << 7); | |
128 | |
129 digit = getUint8(position++); | |
130 if (digit > maxUnsignedDataPerByte) { | |
131 low |= ((digit & byteMask) << 14); | |
132 return; | |
133 } | |
134 low |= (digit << 14); | |
135 | |
136 digit = getUint8(position++); | |
137 if (digit > maxUnsignedDataPerByte) { | |
138 low |= ((digit & byteMask) << 21); | |
139 return; | |
140 } | |
141 low |= (digit << 21); | |
142 | |
143 // Mid 28 bits. | |
144 digit = getUint8(position++); | |
145 if (digit > maxUnsignedDataPerByte) { | |
146 mid |= (digit & byteMask << 0); | |
147 return; | |
148 } | |
149 mid |= (digit << 0); | |
150 | |
151 digit = getUint8(position++); | |
152 if (digit > maxUnsignedDataPerByte) { | |
153 mid |= ((digit & byteMask) << 7); | |
154 return; | |
155 } | |
156 mid |= (digit << 7); | |
157 | |
158 digit = getUint8(position++); | |
159 if (digit > maxUnsignedDataPerByte) { | |
160 mid |= ((digit & byteMask) << 14); | |
161 return; | |
162 } | |
163 mid |= (digit << 14); | |
164 | |
165 digit = getUint8(position++); | |
166 if (digit > maxUnsignedDataPerByte) { | |
167 mid |= ((digit & byteMask) << 21); | |
168 return; | |
169 } | |
170 mid |= (digit << 21); | |
171 | |
172 // High 28 bits. | |
173 digit = getUint8(position++); | |
174 if (digit > maxUnsignedDataPerByte) { | |
175 high |= (digit & byteMask << 0); | |
176 return; | |
177 } | |
178 high |= (digit << 0); | |
179 | |
180 digit = getUint8(position++); | |
181 if (digit > maxUnsignedDataPerByte) { | |
182 high |= ((digit & byteMask) << 7); | |
183 return; | |
184 } | |
185 high |= (digit << 7); | |
186 throw new Exception("Format error: snapshot field exceeds 64 bits"); | |
187 } | |
188 | |
189 void skipUnsigned() { | |
190 while (getUint8(position++) <= maxUnsignedDataPerByte); | |
47 } | 191 } |
48 | 192 |
49 static const int dataBitsPerByte = 7; | 193 static const int dataBitsPerByte = 7; |
50 static const int byteMask = (1 << dataBitsPerByte) - 1; | 194 static const int byteMask = (1 << dataBitsPerByte) - 1; |
51 static const int maxUnsignedDataPerByte = byteMask; | 195 static const int maxUnsignedDataPerByte = byteMask; |
52 } | 196 } |
53 | 197 |
54 class ObjectVertex { | 198 class ObjectVertex { |
55 // 0 represents invalid/uninitialized, 1 is the root. | 199 // 0 represents invalid/uninitialized, 1 is the root. |
56 final int _id; | 200 final int _id; |
57 final ObjectGraph _graph; | 201 final ObjectGraph _graph; |
58 | 202 |
59 ObjectVertex._(this._id, this._graph); | 203 ObjectVertex._(this._id, this._graph); |
60 | 204 |
61 bool get isRoot => _id == 1; | 205 bool get isRoot => _id == 1; |
62 | 206 |
63 bool operator ==(other) => _id == other._id && _graph == other._graph; | 207 bool operator ==(other) => _id == other._id && _graph == other._graph; |
64 int get hashCode => _id; | 208 int get hashCode => _id; |
65 | 209 |
66 int get retainedSize => _graph._retainedSizes[_id]; | 210 int get retainedSize => _graph._retainedSizes[_id]; |
67 ObjectVertex get dominator => new ObjectVertex._(_graph._doms[_id], _graph); | 211 ObjectVertex get dominator => new ObjectVertex._(_graph._doms[_id], _graph); |
68 | 212 |
69 int get shallowSize { | 213 int get shallowSize { |
70 var stream = new _ReadStream(_graph._chunks); | 214 var stream = new _ReadStream(_graph._chunks); |
71 stream.position = _graph._positions[_id]; | 215 stream.position = _graph._positions[_id]; |
72 stream.readUnsigned(); // addr | 216 stream.skipUnsigned(); // addr |
73 return stream.readUnsigned(); // shallowSize | 217 stream.readUnsigned(); // shallowSize |
218 return stream.smallValue; | |
74 } | 219 } |
75 | 220 |
76 int get vmCid { | 221 int get vmCid { |
77 var stream = new _ReadStream(_graph._chunks); | 222 var stream = new _ReadStream(_graph._chunks); |
78 stream.position = _graph._positions[_id]; | 223 stream.position = _graph._positions[_id]; |
79 stream.readUnsigned(); // addr | 224 stream.skipUnsigned(); // addr |
80 stream.readUnsigned(); // shallowSize | 225 stream.skipUnsigned(); // shallowSize |
81 return stream.readUnsigned(); // cid | 226 stream.readUnsigned(); // cid |
227 return stream.smallValue; | |
82 } | 228 } |
83 | 229 |
84 get successors => new _SuccessorsIterable(_graph, _id); | 230 get successors => new _SuccessorsIterable(_graph, _id); |
85 | 231 |
86 int get address { | 232 String get address { |
87 // Note that everywhere else in this file, "address" really means an address | 233 // Note that everywhere else in this file, "address" really means an address |
88 // scaled down by kObjectAlignment. They were scaled down so they would fit | 234 // scaled down by kObjectAlignment. They were scaled down so they would fit |
89 // into Smis on the client. | 235 // into Smis on the client. |
90 var stream = new _ReadStream(_graph._chunks); | 236 var stream = new _ReadStream(_graph._chunks); |
91 stream.position = _graph._positions[_id]; | 237 stream.position = _graph._positions[_id]; |
92 var scaledAddr = stream.readUnsigned(); | 238 stream.readUnsigned(); |
93 return scaledAddr * _graph._kObjectAlignment; | 239 |
240 // Complicated way to do (high:mid:low * _kObjectAlignment).toHexString() | |
241 // without intermediate values exceeding int32. | |
242 | |
243 var strAddr = ""; | |
244 var carry = 0; | |
245 combine4(nibble) { | |
246 nibble = nibble * _graph._kObjectAlignment + carry; | |
247 carry = nibble >> 4; | |
248 nibble = nibble & 0xF; | |
249 strAddr = nibble.toRadixString(16) + strAddr; | |
250 } | |
251 combine28(twentyEightBits) { | |
252 for (int shift = 0; shift < 28; shift += 4) { | |
253 combine4((twentyEightBits >> shift) & 0xF); | |
254 } | |
255 } | |
256 combine28(stream.low); | |
257 combine28(stream.mid); | |
258 combine28(stream.high); | |
sra1
2015/07/01 17:09:33
A trick which probably runs faster in dart2js is
rmacnak
2015/07/07 23:19:05
The hot path is the use of readUnsigned parsing th
| |
259 return strAddr; | |
94 } | 260 } |
95 | 261 |
96 List<ObjectVertex> dominatorTreeChildren() { | 262 List<ObjectVertex> dominatorTreeChildren() { |
97 var N = _graph._N; | 263 var N = _graph._N; |
98 var doms = _graph._doms; | 264 var doms = _graph._doms; |
99 | 265 |
100 var parentId = _id; | 266 var parentId = _id; |
101 var domChildren = []; | 267 var domChildren = []; |
102 | 268 |
103 for (var childId = 1; childId <= N; childId++) { | 269 for (var childId = 1; childId <= N; childId++) { |
(...skipping 17 matching lines...) Expand all Loading... | |
121 | 287 |
122 class _SuccessorsIterator implements Iterator<ObjectVertex> { | 288 class _SuccessorsIterator implements Iterator<ObjectVertex> { |
123 final ObjectGraph _graph; | 289 final ObjectGraph _graph; |
124 _ReadStream _stream; | 290 _ReadStream _stream; |
125 | 291 |
126 ObjectVertex current; | 292 ObjectVertex current; |
127 | 293 |
128 _SuccessorsIterator(this._graph, int id) { | 294 _SuccessorsIterator(this._graph, int id) { |
129 _stream = new _ReadStream(this._graph._chunks); | 295 _stream = new _ReadStream(this._graph._chunks); |
130 _stream.position = _graph._positions[id]; | 296 _stream.position = _graph._positions[id]; |
131 _stream.readUnsigned(); // addr | 297 _stream.skipUnsigned(); // addr |
132 _stream.readUnsigned(); // shallowSize | 298 _stream.skipUnsigned(); // shallowSize |
133 var cid = _stream.readUnsigned(); | 299 _stream.skipUnsigned(); // cid |
134 assert((cid & ~0xFFFF) == 0); // Sanity check: cid's are 16 bit. | |
135 } | 300 } |
136 | 301 |
137 bool moveNext() { | 302 bool moveNext() { |
138 while (true) { | 303 while (true) { |
139 var nextAddr = _stream.readUnsigned(); | 304 _stream.readUnsigned(); |
140 if (nextAddr == 0) return false; | 305 if (_stream.isZero) return false; |
141 var nextId = _graph._addrToId[nextAddr]; | 306 var nextId = _graph._addrToId.get(_stream.high, _stream.mid, _stream.low); |
142 if (nextId == null) continue; // Reference to VM isolate's heap. | 307 if (nextId == null) continue; // Reference to VM isolate's heap. |
143 current = new ObjectVertex._(nextId, _graph); | 308 current = new ObjectVertex._(nextId, _graph); |
144 return true; | 309 return true; |
145 } | 310 } |
146 } | 311 } |
147 } | 312 } |
148 | 313 |
149 class _VerticesIterable extends IterableBase<ObjectVertex> { | 314 class _VerticesIterable extends IterableBase<ObjectVertex> { |
150 final ObjectGraph _graph; | 315 final ObjectGraph _graph; |
151 | 316 |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
225 return this; | 390 return this; |
226 } | 391 } |
227 | 392 |
228 final List<ByteData> _chunks; | 393 final List<ByteData> _chunks; |
229 | 394 |
230 int _kObjectAlignment; | 395 int _kObjectAlignment; |
231 int _N; | 396 int _N; |
232 int _E; | 397 int _E; |
233 int _size; | 398 int _size; |
234 | 399 |
235 Map<int, int> _addrToId = new Map<int, int>(); | 400 AddressMapper _addrToId; |
236 | 401 |
237 // Indexed by node id, with id 0 representing invalid/uninitialized. | 402 // Indexed by node id, with id 0 representing invalid/uninitialized. |
238 Uint32List _positions; // Position of the node in the snapshot. | 403 Uint32List _positions; // Position of the node in the snapshot. |
239 Uint32List _postOrderOrdinals; // post-order index -> id | 404 Uint32List _postOrderOrdinals; // post-order index -> id |
240 Uint32List _postOrderIndices; // id -> post-order index | 405 Uint32List _postOrderIndices; // id -> post-order index |
241 Uint32List _firstPreds; // Offset into preds. | 406 Uint32List _firstPreds; // Offset into preds. |
242 Uint32List _preds; | 407 Uint32List _preds; |
243 Uint32List _doms; | 408 Uint32List _doms; |
244 Uint32List _retainedSizes; | 409 Uint32List _retainedSizes; |
245 | 410 |
246 void _buildPositions() { | 411 void _buildPositions() { |
247 var N = _N; | 412 var N = _N; |
248 var addrToId = _addrToId; | 413 var addrToId = new AddressMapper(N); |
249 | 414 |
250 var positions = new Uint32List(N + 1); | 415 var positions = new Uint32List(N + 1); |
251 | 416 |
252 var stream = new _ReadStream(_chunks); | 417 var stream = new _ReadStream(_chunks); |
253 _kObjectAlignment = stream.readUnsigned(); | 418 stream.readUnsigned(); |
419 _kObjectAlignment = stream.smallValue; | |
254 | 420 |
255 var id = 1; | 421 var id = 1; |
256 while (stream.pendingBytes > 0) { | 422 while (stream.pendingBytes > 0) { |
257 positions[id] = stream.position; | 423 positions[id] = stream.position; |
258 var addr = stream.readUnsigned(); | 424 stream.readUnsigned(); // addr |
259 stream.readUnsigned(); // shallowSize | 425 addrToId.put(stream.high, stream.mid, stream.low, id); |
260 stream.readUnsigned(); // cid | 426 stream.skipUnsigned(); // shallowSize |
261 addrToId[addr] = id; | 427 stream.skipUnsigned(); // cid |
262 | 428 |
263 var succAddr = stream.readUnsigned(); | 429 stream.readUnsigned(); |
264 while (succAddr != 0) { | 430 while (!stream.isZero) { |
265 succAddr = stream.readUnsigned(); | 431 stream.readUnsigned(); |
266 } | 432 } |
267 id++; | 433 id++; |
268 } | 434 } |
269 assert(id == (N + 1)); | 435 assert(id == (N + 1)); |
270 | 436 |
271 var root = addrToId[0]; | 437 var root = addrToId.get(0, 0, 0); |
272 assert(root == 1); | 438 assert(root == 1); |
273 | 439 |
440 _addrToId = addrToId; | |
274 _positions = positions; | 441 _positions = positions; |
275 } | 442 } |
276 | 443 |
277 void _buildPostOrder() { | 444 void _buildPostOrder() { |
278 var N = _N; | 445 var N = _N; |
279 var E = 0; | 446 var E = 0; |
280 var addrToId = _addrToId; | 447 var addrToId = _addrToId; |
281 var positions = _positions; | 448 var positions = _positions; |
282 | 449 |
283 var postOrderOrdinals = new Uint32List(N); | 450 var postOrderOrdinals = new Uint32List(N); |
284 var postOrderIndices = new Uint32List(N + 1); | 451 var postOrderIndices = new Uint32List(N + 1); |
285 var stackNodes = new Uint32List(N); | 452 var stackNodes = new Uint32List(N); |
286 var stackCurrentEdgePos = new Uint32List(N); | 453 var stackCurrentEdgePos = new Uint32List(N); |
287 | 454 |
288 var visited = new Uint8List(N + 1); | 455 var visited = new Uint8List(N + 1); |
289 var postOrderIndex = 0; | 456 var postOrderIndex = 0; |
290 var stackTop = 0; | 457 var stackTop = 0; |
291 var root = 1; | 458 var root = 1; |
292 | 459 |
293 stackNodes[0] = root; | 460 stackNodes[0] = root; |
294 | 461 |
295 var stream = new _ReadStream(_chunks); | 462 var stream = new _ReadStream(_chunks); |
296 stream.position = positions[root]; | 463 stream.position = positions[root]; |
297 stream.readUnsigned(); // addr | 464 stream.skipUnsigned(); // addr |
298 stream.readUnsigned(); // shallowSize | 465 stream.skipUnsigned(); // shallowSize |
299 stream.readUnsigned(); // cid | 466 stream.skipUnsigned(); // cid |
300 stackCurrentEdgePos[0] = stream.position; | 467 stackCurrentEdgePos[0] = stream.position; |
301 visited[root] = 1; | 468 visited[root] = 1; |
302 | 469 |
303 while (stackTop >= 0) { | 470 while (stackTop >= 0) { |
304 var n = stackNodes[stackTop]; | 471 var n = stackNodes[stackTop]; |
305 var edgePos = stackCurrentEdgePos[stackTop]; | 472 var edgePos = stackCurrentEdgePos[stackTop]; |
306 | 473 |
307 stream.position = edgePos; | 474 stream.position = edgePos; |
308 var childAddr = stream.readUnsigned(); | 475 stream.readUnsigned(); // childAddr |
309 if (childAddr != 0) { | 476 if (!stream.isZero) { |
310 stackCurrentEdgePos[stackTop] = stream.position; | 477 stackCurrentEdgePos[stackTop] = stream.position; |
311 var childId = addrToId[childAddr]; | 478 var childId = addrToId.get(stream.high, stream.mid, stream.low); |
312 if (childId == null) continue; // Reference to VM isolate's heap. | 479 if (childId == null) continue; // Reference to VM isolate's heap. |
313 E++; | 480 E++; |
314 if (visited[childId] == 1) continue; | 481 if (visited[childId] == 1) continue; |
315 | 482 |
316 stackTop++; | 483 stackTop++; |
317 stackNodes[stackTop] = childId; | 484 stackNodes[stackTop] = childId; |
318 | 485 |
319 stream.position = positions[childId]; | 486 stream.position = positions[childId]; |
320 stream.readUnsigned(); // addr | 487 stream.skipUnsigned(); // addr |
321 stream.readUnsigned(); // shallowSize | 488 stream.skipUnsigned(); // shallowSize |
322 stream.readUnsigned(); // cid | 489 stream.skipUnsigned(); // cid |
323 stackCurrentEdgePos[stackTop] = stream.position; // i.e., first edge | 490 stackCurrentEdgePos[stackTop] = stream.position; // i.e., first edge |
324 visited[childId] = 1; | 491 visited[childId] = 1; |
325 } else { | 492 } else { |
326 // Done with all children. | 493 // Done with all children. |
327 postOrderIndices[n] = postOrderIndex; | 494 postOrderIndices[n] = postOrderIndex; |
328 postOrderOrdinals[postOrderIndex++] = n; | 495 postOrderOrdinals[postOrderIndex++] = n; |
329 stackTop--; | 496 stackTop--; |
330 } | 497 } |
331 } | 498 } |
332 | 499 |
(...skipping 16 matching lines...) Expand all Loading... | |
349 // + 1 because 0 is a sentinel | 516 // + 1 because 0 is a sentinel |
350 // + 1 so the number of predecessors can be found from the difference with | 517 // + 1 so the number of predecessors can be found from the difference with |
351 // the next node's offset. | 518 // the next node's offset. |
352 var numPreds = new Uint32List(N + 2); | 519 var numPreds = new Uint32List(N + 2); |
353 var preds = new Uint32List(E); | 520 var preds = new Uint32List(E); |
354 | 521 |
355 // Count predecessors of each node. | 522 // Count predecessors of each node. |
356 var stream = new _ReadStream(_chunks); | 523 var stream = new _ReadStream(_chunks); |
357 for (var i = 1; i <= N; i++) { | 524 for (var i = 1; i <= N; i++) { |
358 stream.position = positions[i]; | 525 stream.position = positions[i]; |
359 stream.readUnsigned(); // addr | 526 stream.skipUnsigned(); // addr |
360 stream.readUnsigned(); // shallowSize | 527 stream.skipUnsigned(); // shallowSize |
361 stream.readUnsigned(); // cid | 528 stream.skipUnsigned(); // cid |
362 var succAddr = stream.readUnsigned(); | 529 stream.readUnsigned(); // succAddr |
363 while (succAddr != 0) { | 530 while (!stream.isZero) { |
364 var succId = addrToId[succAddr]; | 531 var succId = addrToId.get(stream.high, stream.mid, stream.low); |
365 if (succId != null) { | 532 if (succId != null) { |
366 numPreds[succId]++; | 533 numPreds[succId]++; |
367 } else { | 534 } else { |
368 // Reference to VM isolate's heap. | 535 // Reference to VM isolate's heap. |
369 } | 536 } |
370 succAddr = stream.readUnsigned(); | 537 stream.readUnsigned(); // succAddr |
371 } | 538 } |
372 } | 539 } |
373 | 540 |
374 // Assign indices into predecessors array. | 541 // Assign indices into predecessors array. |
375 var firstPreds = numPreds; // Alias. | 542 var firstPreds = numPreds; // Alias. |
376 var nextPreds = new Uint32List(N + 1); | 543 var nextPreds = new Uint32List(N + 1); |
377 var predIndex = 0; | 544 var predIndex = 0; |
378 for (var i = 1; i <= N; i++) { | 545 for (var i = 1; i <= N; i++) { |
379 var thisPredIndex = predIndex; | 546 var thisPredIndex = predIndex; |
380 predIndex += numPreds[i]; | 547 predIndex += numPreds[i]; |
381 firstPreds[i] = thisPredIndex; | 548 firstPreds[i] = thisPredIndex; |
382 nextPreds[i] = thisPredIndex; | 549 nextPreds[i] = thisPredIndex; |
383 } | 550 } |
384 assert(predIndex == E); | 551 assert(predIndex == E); |
385 firstPreds[N + 1] = E; // Extra entry for cheap boundary detection. | 552 firstPreds[N + 1] = E; // Extra entry for cheap boundary detection. |
386 | 553 |
387 // Fill predecessors array. | 554 // Fill predecessors array. |
388 for (var i = 1; i <= N; i++) { | 555 for (var i = 1; i <= N; i++) { |
389 stream.position = positions[i]; | 556 stream.position = positions[i]; |
390 stream.readUnsigned(); // addr | 557 stream.skipUnsigned(); // addr |
391 stream.readUnsigned(); // shallowSize | 558 stream.skipUnsigned(); // shallowSize |
392 stream.readUnsigned(); // cid | 559 stream.skipUnsigned(); // cid |
393 var succAddr = stream.readUnsigned(); | 560 stream.readUnsigned(); // succAddr |
394 while (succAddr != 0) { | 561 while (!stream.isZero) { |
395 var succId = addrToId[succAddr]; | 562 var succId = addrToId.get(stream.high, stream.mid, stream.low); |
396 if (succId != null) { | 563 if (succId != null) { |
397 var predIndex = nextPreds[succId]++; | 564 var predIndex = nextPreds[succId]++; |
398 preds[predIndex] = i; | 565 preds[predIndex] = i; |
399 } else { | 566 } else { |
400 // Reference to VM isolate's heap. | 567 // Reference to VM isolate's heap. |
401 } | 568 } |
402 succAddr = stream.readUnsigned(); | 569 stream.readUnsigned(); // succAddr |
403 } | 570 } |
404 } | 571 } |
405 | 572 |
406 _firstPreds = firstPreds; | 573 _firstPreds = firstPreds; |
407 _preds = preds; | 574 _preds = preds; |
408 } | 575 } |
409 | 576 |
410 // "A Simple, Fast Dominance Algorithm" | 577 // "A Simple, Fast Dominance Algorithm" |
411 // Keith D. Cooper, Timothy J. Harvey, and Ken Kennedy | 578 // Keith D. Cooper, Timothy J. Harvey, and Ken Kennedy |
412 void _buildDominators() { | 579 void _buildDominators() { |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
491 var size = 0; | 658 var size = 0; |
492 var positions = _positions; | 659 var positions = _positions; |
493 var postOrderOrdinals = _postOrderOrdinals; | 660 var postOrderOrdinals = _postOrderOrdinals; |
494 var doms = _doms; | 661 var doms = _doms; |
495 var retainedSizes = new Uint32List(N + 1); | 662 var retainedSizes = new Uint32List(N + 1); |
496 | 663 |
497 // Start with retained size as shallow size. | 664 // Start with retained size as shallow size. |
498 var reader = new _ReadStream(_chunks); | 665 var reader = new _ReadStream(_chunks); |
499 for (var i = 1; i <= N; i++) { | 666 for (var i = 1; i <= N; i++) { |
500 reader.position = positions[i]; | 667 reader.position = positions[i]; |
501 reader.readUnsigned(); // addr | 668 reader.skipUnsigned(); // addr |
502 var shallowSize = reader.readUnsigned(); | 669 reader.readUnsigned(); // shallowSize |
670 var shallowSize = reader.smallValue; | |
503 retainedSizes[i] = shallowSize; | 671 retainedSizes[i] = shallowSize; |
504 size += shallowSize; | 672 size += shallowSize; |
505 } | 673 } |
506 | 674 |
507 // In post order (bottom up), add retained size to dominator's retained | 675 // In post order (bottom up), add retained size to dominator's retained |
508 // size, skipping root. | 676 // size, skipping root. |
509 for (var o = 0; o < (N - 1); o++) { | 677 for (var o = 0; o < (N - 1); o++) { |
510 var i = postOrderOrdinals[o]; | 678 var i = postOrderOrdinals[o]; |
511 assert(i != 1); | 679 assert(i != 1); |
512 retainedSizes[doms[i]] += retainedSizes[i]; | 680 retainedSizes[doms[i]] += retainedSizes[i]; |
513 } | 681 } |
514 | 682 |
515 _retainedSizes = retainedSizes; | 683 _retainedSizes = retainedSizes; |
516 _size = size; | 684 _size = size; |
517 } | 685 } |
518 } | 686 } |
OLD | NEW |