Changeset 117749 in webkit
- Timestamp:
- May 21, 2012 1:53:37 AM (12 years ago)
- Location:
- trunk
- Files:
-
- 8 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r117748 r117749 1 2012-05-18 Ilya Tikhonovsky <loislo@chromium.org> 2 3 Web Inspector: upstream build dominators tree procedure from v8. 4 https://bugs.webkit.org/show_bug.cgi?id=86640 5 6 The idea is to reduce transfer size and move all the post-processing steps to the front-end. 7 The JS implementation is ~1.5 times slower. 8 9 Reviewed by Yury Semikhatsky. 10 11 Covered by existing tests and performance tests. 12 13 * inspector/profiler/heap-snapshot-expected.txt: 14 * inspector/profiler/heap-snapshot-test.js: 15 (initialize_HeapSnapshotTest.InspectorTest.createHeapSnapshotMockRaw): 16 * inspector/profiler/heap-snapshot.html: 17 1 18 2012-05-21 Mike Lawther <mikelawther@chromium.org> 2 19 -
trunk/LayoutTests/inspector/profiler/heap-snapshot-expected.txt
r116771 r117749 14 14 Running: heapSnapshotSimpleTest 15 15 16 Running: heapSnapshotPostOrderIndexTest 17 18 Running: heapSnapshotDominatorsTreeTest 19 16 20 Running: heapSnapshotRetainersTest 17 21 -
trunk/LayoutTests/inspector/profiler/heap-snapshot-test.js
r117581 r117749 70 70 edge_count: 7}, 71 71 nodes: [ 72 0, 0, 1, 0, 20, 0, 0, 73 1, 1, 2, 2, 2, 0, 6, 74 1, 2, 3, 3, 8, 0, 12, 75 1, 3, 4, 4, 10, 0, 18, 76 1, 4, 5, 5, 5, 14, 21, 77 1, 5, 6, 6, 6, 21, 21], 72 0, 0, 1, 0, 20, 0, 0, // root (0) 73 1, 1, 2, 2, 2, 0, 6, // A (7) 74 1, 2, 3, 3, 8, 0, 12, // B (14) 75 1, 3, 4, 4, 10, 0, 18, // C (21) 76 1, 4, 5, 5, 5, 14, 21, // D (28) 77 1, 5, 6, 6, 6, 21, 21],// E (35) 78 78 edges: [ 79 1, 6, 7, 1, 7, 14, 80 0, 1, 14, 1, 8, 21, 81 1, 9, 21, 1, 10, 28, 82 1, 11, 35], 79 // root node edges 80 1, 6, 7, // property 'a' to node 'A' 81 1, 7, 14, // property 'b' to node 'B' 82 83 // A node edges 84 0, 1, 14, // element 1 to node 'B' 85 1, 8, 21, // property 'ac' to node 'C' 86 87 // B node edges 88 1, 9, 21, // property 'bc' to node 'C' 89 1, 10, 28, // property 'bd' to node 'D' 90 91 // C node edges 92 1, 11, 35], // property 'ce' to node 'E' 83 93 strings: ["", "A", "B", "C", "D", "E", "a", "b", "ac", "bc", "bd", "ce"] 84 94 }; -
trunk/LayoutTests/inspector/profiler/heap-snapshot.html
r116771 r117749 93 93 InspectorTest.assertEquals(6, snapshot.nodeCount, "node count"); 94 94 InspectorTest.assertEquals(20, snapshot.totalSize, "total size"); 95 next(); 96 }, 97 98 function heapSnapshotPostOrderIndexTest(next) 99 { 100 var snapshot = new WebInspector.HeapSnapshot(InspectorTest.createHeapSnapshotMock()); 101 var postOrderIndex = snapshot._buildPostOrderIndex().postOrderIndex2NodeIndex; 102 var expected = [28,35,21,14,7,0]; 103 for (var i = 0; i < expected.length; ++i) 104 InspectorTest.assertEquals(expected[i], postOrderIndex[i], "Post ordered indexes"); 105 next(); 106 }, 107 108 function heapSnapshotDominatorsTreeTest(next) 109 { 110 var snapshot = new WebInspector.HeapSnapshot(InspectorTest.createHeapSnapshotMock()); 111 var result = snapshot._buildPostOrderIndex(); 112 var dominatorsTree = snapshot._buildDominatorTree(result.postOrderIndex2NodeIndex, result.nodeOrdinal2PostOrderIndex); 113 var expected = [0, 0, 0, 0, 14, 21]; 114 for (var i = 0; i < expected.length; ++i) 115 InspectorTest.assertEquals(expected[i], dominatorsTree[i], "Dominators Tree"); 95 116 next(); 96 117 }, -
trunk/PerformanceTests/ChangeLog
r117614 r117749 1 2012-05-18 Ilya Tikhonovsky <loislo@chromium.org> 2 3 Web Inspector: upstream build dominators tree procedure from v8. 4 https://bugs.webkit.org/show_bug.cgi?id=86640 5 6 The idea is to reduce transfer size and move all the post-processing steps to the front-end. 7 The JS implementation is ~1.5 times slower. 8 9 Reviewed by Yury Semikhatsky. 10 11 Covered by existing tests and performance tests. 12 13 * inspector/heap-snapshot.html: 14 1 15 2012-05-18 Kentaro Hara <haraken@chromium.org> 2 16 -
trunk/PerformanceTests/inspector/heap-snapshot.html
r117236 r117749 29 29 InspectorTest.measureFunction(WebInspector.HeapSnapshot.prototype, "_markDetachedDOMTreeNodes"); 30 30 InspectorTest.measureFunction(WebInspector.HeapSnapshot.prototype, "_markQueriableHeapObjects"); 31 InspectorTest.measureFunction(WebInspector.HeapSnapshot.prototype, "_markPageOwnedNodes"); 31 32 InspectorTest.measureFunction(WebInspector.HeapSnapshot.prototype, "_splitNodesAndContainmentEdges"); 33 InspectorTest.measureFunction(WebInspector.HeapSnapshot.prototype, "_buildPostOrderIndex"); 34 InspectorTest.measureFunction(WebInspector.HeapSnapshot.prototype, "_buildDominatorTree"); 32 35 33 36 timer.finish(backendTimerCookie); -
trunk/Source/WebCore/ChangeLog
r117748 r117749 1 2012-05-18 Ilya Tikhonovsky <loislo@chromium.org> 2 3 Web Inspector: upstream build dominators tree procedure from v8. 4 https://bugs.webkit.org/show_bug.cgi?id=86640 5 6 The idea is to reduce transfer size and move all the post-processing steps to the front-end. 7 The JS implementation is ~1.5 times slower. 8 9 Reviewed by Yury Semikhatsky. 10 11 Covered by existing tests and performance tests. 12 13 * inspector/front-end/HeapSnapshot.js: 14 (WebInspector.HeapSnapshot.prototype._init): 15 (WebInspector.HeapSnapshot.prototype._buildAggregates): 16 (WebInspector.HeapSnapshot.prototype._buildPostOrderIndex): 17 (WebInspector.HeapSnapshot.prototype._buildDominatorTree): 18 (WebInspector.HeapSnapshot.prototype._markPageOwnedNodes): 19 (WebInspector.HeapSnapshot.prototype._markQueriableHeapObjects): 20 (WebInspector.HeapSnapshot.prototype._calculateFlags): 21 1 22 2012-05-21 Mike Lawther <mikelawther@chromium.org> 2 23 -
trunk/Source/WebCore/inspector/front-end/HeapSnapshot.js
r117545 r117749 709 709 canBeQueried: 1, 710 710 detachedDOMTreeNode: 2, 711 pageObject: 4, // The idea is to track separately the objects owned by the page and the objects owned by debugger. 712 713 visitedMarkerMask: 0x0ffff, // bits: 0,1111,1111,1111,1111 714 visitedMarker: 0x10000 // bits: 1,0000,0000,0000,0000 711 715 }; 712 716 … … 720 724 this._calculateFlags(); 721 725 this._calculateObjectToWindowDistance(); 726 var result = this._buildPostOrderIndex(); 727 this._dominatorsTree = this._buildDominatorTree(result.postOrderIndex2NodeIndex, result.nodeOrdinal2PostOrderIndex); 722 728 }, 723 729 … … 788 794 delete this._flags; 789 795 delete this._distancesToWindow; 796 delete this._dominatorsTree; 790 797 }, 791 798 … … 960 967 var nodesLength = nodes.length; 961 968 var nodeNativeType = this._nodeNativeType; 962 var nodeField sCount = this._nodeFieldCount;969 var nodeFieldCount = this._nodeFieldCount; 963 970 var selfSizeOffset = this._nodeSelfSizeOffset; 964 971 var nodeTypeOffset = this._nodeTypeOffset; … … 966 973 var distancesToWindow = this._distancesToWindow; 967 974 968 for (var nodeIndex = this._rootNodeIndex; nodeIndex < nodesLength; nodeIndex += nodeField sCount) {969 var nodeOrdinal = nodeIndex / nodeField sCount;975 for (var nodeIndex = this._rootNodeIndex; nodeIndex < nodesLength; nodeIndex += nodeFieldCount) { 976 var nodeOrdinal = nodeIndex / nodeFieldCount; 970 977 node.nodeIndex = nodeIndex; 971 978 var selfSize = nodes[nodeIndex + selfSizeOffset]; … … 1064 1071 }, 1065 1072 1073 _buildPostOrderIndex: function() 1074 { 1075 var nodeFieldCount = this._nodeFieldCount; 1076 var nodes = this._nodes; 1077 var nodeCount = this.nodeCount; 1078 var rootNodeIndex = this._rootNodeIndex; 1079 1080 var edgeFieldsCount = this._edgeFieldsCount; 1081 var edgeToNodeOffset = this._edgeToNodeOffset; 1082 var edgeTypeOffset = this._edgeTypeOffset; 1083 var edgeShortcutType = this._edgeShortcutType; 1084 var firstEdgeIndexOffset = this._firstEdgeIndexOffset; 1085 var containmentEdges = this._containmentEdges; 1086 var containmentEdgesLength = this._containmentEdges.length; 1087 1088 var flags = this._flags; 1089 var flag = this._nodeFlags.pageObject; 1090 1091 var nodesToVisit = new Uint32Array(nodeCount); 1092 var postOrderIndex2NodeIndex = new Uint32Array(nodeCount); 1093 var nodeOrdinal2PostOrderIndex = new Uint32Array(nodeCount); 1094 var painted = new Uint8Array(nodeCount); 1095 var nodesToVisitLength = 0; 1096 var postOrderIndex = 0; 1097 var grey = 1; 1098 var black = 2; 1099 1100 nodesToVisit[nodesToVisitLength++] = this._rootNodeIndex; 1101 painted[this._rootNodeIndex / nodeFieldCount] = grey; 1102 1103 while (nodesToVisitLength) { 1104 var nodeIndex = nodesToVisit[nodesToVisitLength - 1]; 1105 var nodeOrdinal = nodeIndex / nodeFieldCount; 1106 if (painted[nodeOrdinal] === grey) { 1107 painted[nodeOrdinal] = black; 1108 var nodeFlag = flags[nodeOrdinal] & flag; 1109 var beginEdgeIndex = nodes[nodeIndex + firstEdgeIndexOffset]; 1110 var endEdgeIndex = nodeOrdinal < nodeCount - 1 1111 ? nodes[nodeIndex + firstEdgeIndexOffset + nodeFieldCount] 1112 : containmentEdgesLength; 1113 for (var edgeIndex = beginEdgeIndex; edgeIndex < endEdgeIndex; edgeIndex += edgeFieldsCount) { 1114 if (nodeIndex !== rootNodeIndex && containmentEdges[edgeIndex + edgeTypeOffset] === edgeShortcutType) 1115 continue; 1116 var childNodeIndex = containmentEdges[edgeIndex + edgeToNodeOffset]; 1117 var childNodeOrdinal = childNodeIndex / nodeFieldCount; 1118 var childNodeFlag = flags[childNodeOrdinal] & flag; 1119 // We are skipping the edges from non-page-owned nodes to page-owned nodes. 1120 // Otherwise the dominators for the objects that also were retained by debugger would be affected. 1121 if (nodeIndex !== rootNodeIndex && childNodeFlag && !nodeFlag) 1122 continue; 1123 if (!painted[childNodeOrdinal]) { 1124 painted[childNodeOrdinal] = grey; 1125 nodesToVisit[nodesToVisitLength++] = childNodeIndex; 1126 } 1127 } 1128 } else { 1129 nodeOrdinal2PostOrderIndex[nodeOrdinal] = postOrderIndex; 1130 postOrderIndex2NodeIndex[postOrderIndex++] = nodeIndex; 1131 --nodesToVisitLength; 1132 } 1133 } 1134 return {postOrderIndex2NodeIndex: postOrderIndex2NodeIndex, nodeOrdinal2PostOrderIndex: nodeOrdinal2PostOrderIndex}; 1135 }, 1136 1137 // The algorithm is based on the article: 1138 // K. Cooper, T. Harvey and K. Kennedy "A Simple, Fast Dominance Algorithm" 1139 // Softw. Pract. Exper. 4 (2001), pp. 1-10. 1140 /** 1141 * @param {Array.<number>} postOrderIndex2NodeIndex 1142 * @param {Array.<number>} nodeOrdinal2PostOrderIndex 1143 */ 1144 _buildDominatorTree: function(postOrderIndex2NodeIndex, nodeOrdinal2PostOrderIndex) 1145 { 1146 var nodeFieldCount = this._nodeFieldCount; 1147 var nodes = this._nodes; 1148 var firstRetainerIndex = this._firstRetainerIndex; 1149 var retainingNodes = this._retainingNodes; 1150 var retainingEdges = this._retainingEdges; 1151 var edgeFieldsCount = this._edgeFieldsCount; 1152 var edgeToNodeOffset = this._edgeToNodeOffset; 1153 var edgeTypeOffset = this._edgeTypeOffset; 1154 var edgeShortcutType = this._edgeShortcutType; 1155 var firstEdgeIndexOffset = this._firstEdgeIndexOffset; 1156 var containmentEdges = this._containmentEdges; 1157 var containmentEdgesLength = this._containmentEdges.length; 1158 var rootNodeIndex = this._rootNodeIndex; 1159 1160 var flags = this._flags; 1161 var flag = this._nodeFlags.pageObject; 1162 1163 var nodesCount = postOrderIndex2NodeIndex.length; 1164 var rootPostOrderedIndex = nodesCount - 1; 1165 var noEntry = nodesCount; 1166 var dominators = new Uint32Array(nodesCount); 1167 for (var i = 0; i < rootPostOrderedIndex; ++i) 1168 dominators[i] = noEntry; 1169 dominators[rootPostOrderedIndex] = rootPostOrderedIndex; 1170 1171 // The affected array is used to mark entries which dominators 1172 // have to be racalculated because of changes in their retainers. 1173 var affected = new Uint8Array(nodesCount); 1174 1175 { // Mark the root direct children as affected. 1176 var nodeIndex = this._rootNodeIndex; 1177 var beginEdgeToNodeFieldIndex = nodes[nodeIndex + firstEdgeIndexOffset] + edgeToNodeOffset; 1178 var endEdgeToNodeFieldIndex = nodes[nodeIndex + nodeFieldCount + firstEdgeIndexOffset]; 1179 for (var toNodeFieldIndex = beginEdgeToNodeFieldIndex; 1180 toNodeFieldIndex < endEdgeToNodeFieldIndex; 1181 toNodeFieldIndex += edgeFieldsCount) { 1182 var childNodeOrdinal = containmentEdges[toNodeFieldIndex] / nodeFieldCount; 1183 affected[nodeOrdinal2PostOrderIndex[childNodeOrdinal]] = 1; 1184 } 1185 } 1186 1187 var changed = true; 1188 while (changed) { 1189 changed = false; 1190 for (var postOrderIndex = rootPostOrderedIndex - 1; postOrderIndex >= 0; --postOrderIndex) { 1191 if (affected[postOrderIndex] === 0) 1192 continue; 1193 affected[postOrderIndex] = 0; 1194 // If dominator of the entry has already been set to root, 1195 // then it can't propagate any further. 1196 if (dominators[postOrderIndex] === rootPostOrderedIndex) 1197 continue; 1198 var nodeOrdinal = postOrderIndex2NodeIndex[postOrderIndex] / nodeFieldCount; 1199 var nodeFlag = !!(flags[nodeOrdinal] & flag); 1200 var newDominatorIndex = noEntry; 1201 var beginRetainerIndex = firstRetainerIndex[nodeOrdinal]; 1202 var endRetainerIndex = firstRetainerIndex[nodeOrdinal + 1]; 1203 for (var retainerIndex = beginRetainerIndex; retainerIndex < endRetainerIndex; ++retainerIndex) { 1204 var retainerEdgeIndex = retainingEdges[retainerIndex]; 1205 var retainerEdgeType = containmentEdges[retainerEdgeIndex + edgeTypeOffset]; 1206 var retainerNodeIndex = retainingNodes[retainerIndex]; 1207 if (retainerNodeIndex !== rootNodeIndex && retainerEdgeType === edgeShortcutType) 1208 continue; 1209 var retainerNodeOrdinal = retainerNodeIndex / nodeFieldCount; 1210 var retainerNodeFlag = !!(flags[retainerNodeOrdinal] & flag); 1211 // We are skipping the edges from non-page-owned nodes to page-owned nodes. 1212 // Otherwise the dominators for the objects that also were retained by debugger would be affected. 1213 if (retainerNodeIndex !== rootNodeIndex && nodeFlag && !retainerNodeFlag) 1214 continue; 1215 var retanerPostOrderIndex = nodeOrdinal2PostOrderIndex[retainerNodeOrdinal]; 1216 if (dominators[retanerPostOrderIndex] !== noEntry) { 1217 if (newDominatorIndex === noEntry) 1218 newDominatorIndex = retanerPostOrderIndex; 1219 else { 1220 while (retanerPostOrderIndex !== newDominatorIndex) { 1221 while (retanerPostOrderIndex < newDominatorIndex) 1222 retanerPostOrderIndex = dominators[retanerPostOrderIndex]; 1223 while (newDominatorIndex < retanerPostOrderIndex) 1224 newDominatorIndex = dominators[newDominatorIndex]; 1225 } 1226 } 1227 // If idom has already reached the root, it doesn't make sense 1228 // to check other retainers. 1229 if (newDominatorIndex === rootPostOrderedIndex) 1230 break; 1231 } 1232 } 1233 if (newDominatorIndex !== noEntry && dominators[postOrderIndex] !== newDominatorIndex) { 1234 dominators[postOrderIndex] = newDominatorIndex; 1235 changed = true; 1236 nodeIndex = postOrderIndex2NodeIndex[postOrderIndex]; 1237 nodeOrdinal = nodeIndex / nodeFieldCount; 1238 beginEdgeToNodeFieldIndex = nodes[nodeIndex + firstEdgeIndexOffset] + edgeToNodeOffset; 1239 endEdgeToNodeFieldIndex = nodeOrdinal < nodesCount - 1 1240 ? nodes[nodeIndex + firstEdgeIndexOffset + nodeFieldCount] 1241 : containmentEdgesLength; 1242 for (var toNodeFieldIndex = beginEdgeToNodeFieldIndex; 1243 toNodeFieldIndex < endEdgeToNodeFieldIndex; 1244 toNodeFieldIndex += edgeFieldsCount) { 1245 var childNodeOrdinal = containmentEdges[toNodeFieldIndex] / nodeFieldCount; 1246 affected[nodeOrdinal2PostOrderIndex[childNodeOrdinal]] = 1; 1247 } 1248 } 1249 } 1250 } 1251 1252 var dominatorsTree = new Uint32Array(nodesCount); 1253 for (var postOrderIndex = 0, l = dominators.length; postOrderIndex < l; ++postOrderIndex) { 1254 var nodeOrdinal = postOrderIndex2NodeIndex[postOrderIndex] / nodeFieldCount; 1255 dominatorsTree[nodeOrdinal] = postOrderIndex2NodeIndex[dominators[postOrderIndex]]; 1256 } 1257 return dominatorsTree; 1258 }, 1259 1066 1260 _buildDominatedNodes: function() 1067 1261 { … … 1157 1351 for (var edgesIter = node.edges; edgesIter.hasNext(); edgesIter.next()) 1158 1352 this._flags[edgesIter.edge.node.nodeIndex / this._nodeFieldCount] |= flag; 1353 } 1354 } 1355 }, 1356 1357 _markPageOwnedNodes: function() 1358 { 1359 var edgeShortcutType = this._edgeShortcutType; 1360 var edgeToNodeOffset = this._edgeToNodeOffset; 1361 var edgeTypeOffset = this._edgeTypeOffset; 1362 var edgeFieldsCount = this._edgeFieldsCount; 1363 var firstEdgeIndexOffset = this._firstEdgeIndexOffset; 1364 var containmentEdges = this._containmentEdges; 1365 var containmentEdgesLength = containmentEdges.length; 1366 var nodes = this._nodes; 1367 var nodeFieldCount = this._nodeFieldCount; 1368 var nodesCount = this.nodeCount; 1369 1370 var flags = this._flags; 1371 var flag = this._nodeFlags.pageObject; 1372 var visitedMarker = this._nodeFlags.visitedMarker; 1373 var visitedMarkerMask = this._nodeFlags.visitedMarkerMask; 1374 var markerAndFlag = visitedMarker | flag; 1375 1376 var nodesToVisit = new Uint32Array(nodesCount); 1377 var nodesToVisitLength = 0; 1378 1379 for (var edgeIndex = nodes[this._rootNodeIndex + firstEdgeIndexOffset], endEdgeIndex = nodes[this._rootNodeIndex + nodeFieldCount + firstEdgeIndexOffset]; 1380 edgeIndex < endEdgeIndex; 1381 edgeIndex += edgeFieldsCount) { 1382 if (containmentEdges[edgeIndex + edgeTypeOffset] === edgeShortcutType) { 1383 var nodeIndex = containmentEdges[edgeIndex + edgeToNodeOffset]; 1384 nodesToVisit[nodesToVisitLength++] = nodeIndex; 1385 flags[nodeIndex / nodeFieldCount] |= visitedMarker; 1386 } 1387 } 1388 1389 while (nodesToVisitLength) { 1390 var nodeIndex = nodesToVisit[--nodesToVisitLength]; 1391 var nodeOrdinal = nodeIndex / nodeFieldCount; 1392 flags[nodeOrdinal] |= flag; 1393 flags[nodeOrdinal] &= visitedMarkerMask; 1394 var beginEdgeToNodeFieldIndex = nodes[nodeIndex + firstEdgeIndexOffset] + edgeToNodeOffset; 1395 var endEdgeToNodeFieldIndex = 0; 1396 if (nodeOrdinal < nodesCount - 1) 1397 endEdgeToNodeFieldIndex = nodes[nodeIndex + firstEdgeIndexOffset + nodeFieldCount] + edgeToNodeOffset; 1398 else 1399 endEdgeToNodeFieldIndex = containmentEdgesLength; 1400 for (var edgeToNodeIndex = beginEdgeToNodeFieldIndex; 1401 edgeToNodeIndex < endEdgeToNodeFieldIndex; 1402 edgeToNodeIndex += edgeFieldsCount) { 1403 var childNodeIndex = containmentEdges[edgeToNodeIndex]; 1404 var childNodeOrdinal = childNodeIndex / nodeFieldCount; 1405 if (flags[childNodeOrdinal] & markerAndFlag) 1406 continue; 1407 nodesToVisit[nodesToVisitLength++] = childNodeIndex; 1408 flags[childNodeOrdinal] |= visitedMarker; 1159 1409 } 1160 1410 } … … 1181 1431 var flags = this._flags; 1182 1432 var list = []; 1433 1183 1434 for (var iter = this.rootNode.edges; iter.hasNext(); iter.next()) { 1184 1435 if (iter.edge.node.isWindow) … … 1213 1464 this._markDetachedDOMTreeNodes(); 1214 1465 this._markQueriableHeapObjects(); 1466 this._markPageOwnedNodes(); 1215 1467 }, 1216 1468
Note: See TracChangeset
for help on using the changeset viewer.