Changeset 117749 in webkit


Ignore:
Timestamp:
May 21, 2012 1:53:37 AM (12 years ago)
Author:
loislo@chromium.org
Message:

Web Inspector: upstream build dominators tree procedure from v8.
https://bugs.webkit.org/show_bug.cgi?id=86640

The idea is to reduce transfer size and move all the post-processing steps to the front-end.
The JS implementation is ~1.5 times slower.

Reviewed by Yury Semikhatsky.

Covered by existing tests and performance tests.

PerformanceTests:

  • inspector/heap-snapshot.html:

Source/WebCore:

  • inspector/front-end/HeapSnapshot.js:

(WebInspector.HeapSnapshot.prototype._init):
(WebInspector.HeapSnapshot.prototype._buildAggregates):
(WebInspector.HeapSnapshot.prototype._buildPostOrderIndex):
(WebInspector.HeapSnapshot.prototype._buildDominatorTree):
(WebInspector.HeapSnapshot.prototype._markPageOwnedNodes):
(WebInspector.HeapSnapshot.prototype._markQueriableHeapObjects):
(WebInspector.HeapSnapshot.prototype._calculateFlags):

LayoutTests:

  • inspector/profiler/heap-snapshot-expected.txt:
  • inspector/profiler/heap-snapshot-test.js:

(initialize_HeapSnapshotTest.InspectorTest.createHeapSnapshotMockRaw):

  • inspector/profiler/heap-snapshot.html:
Location:
trunk
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r117748 r117749  
     12012-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
    1182012-05-21  Mike Lawther  <mikelawther@chromium.org>
    219
  • trunk/LayoutTests/inspector/profiler/heap-snapshot-expected.txt

    r116771 r117749  
    1414Running: heapSnapshotSimpleTest
    1515
     16Running: heapSnapshotPostOrderIndexTest
     17
     18Running: heapSnapshotDominatorsTreeTest
     19
    1620Running: heapSnapshotRetainersTest
    1721
  • trunk/LayoutTests/inspector/profiler/heap-snapshot-test.js

    r117581 r117749  
    7070            edge_count: 7},
    7171        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)
    7878        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'
    8393        strings: ["", "A", "B", "C", "D", "E", "a", "b", "ac", "bc", "bd", "ce"]
    8494    };
  • trunk/LayoutTests/inspector/profiler/heap-snapshot.html

    r116771 r117749  
    9393            InspectorTest.assertEquals(6, snapshot.nodeCount, "node count");
    9494            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");
    95116            next();
    96117        },
  • trunk/PerformanceTests/ChangeLog

    r117614 r117749  
     12012-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
    1152012-05-18  Kentaro Hara  <haraken@chromium.org>
    216
  • trunk/PerformanceTests/inspector/heap-snapshot.html

    r117236 r117749  
    2929            InspectorTest.measureFunction(WebInspector.HeapSnapshot.prototype, "_markDetachedDOMTreeNodes");
    3030            InspectorTest.measureFunction(WebInspector.HeapSnapshot.prototype, "_markQueriableHeapObjects");
     31            InspectorTest.measureFunction(WebInspector.HeapSnapshot.prototype, "_markPageOwnedNodes");
    3132            InspectorTest.measureFunction(WebInspector.HeapSnapshot.prototype, "_splitNodesAndContainmentEdges");
     33            InspectorTest.measureFunction(WebInspector.HeapSnapshot.prototype, "_buildPostOrderIndex");
     34            InspectorTest.measureFunction(WebInspector.HeapSnapshot.prototype, "_buildDominatorTree");
    3235
    3336            timer.finish(backendTimerCookie);
  • trunk/Source/WebCore/ChangeLog

    r117748 r117749  
     12012-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
    1222012-05-21  Mike Lawther  <mikelawther@chromium.org>
    223
  • trunk/Source/WebCore/inspector/front-end/HeapSnapshot.js

    r117545 r117749  
    709709            canBeQueried: 1,
    710710            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
    711715        };
    712716
     
    720724        this._calculateFlags();
    721725        this._calculateObjectToWindowDistance();
     726        var result = this._buildPostOrderIndex();
     727        this._dominatorsTree = this._buildDominatorTree(result.postOrderIndex2NodeIndex, result.nodeOrdinal2PostOrderIndex);
    722728    },
    723729
     
    788794        delete this._flags;
    789795        delete this._distancesToWindow;
     796        delete this._dominatorsTree;
    790797    },
    791798
     
    960967        var nodesLength = nodes.length;
    961968        var nodeNativeType = this._nodeNativeType;
    962         var nodeFieldsCount = this._nodeFieldCount;
     969        var nodeFieldCount = this._nodeFieldCount;
    963970        var selfSizeOffset = this._nodeSelfSizeOffset;
    964971        var nodeTypeOffset = this._nodeTypeOffset;
     
    966973        var distancesToWindow = this._distancesToWindow;
    967974
    968         for (var nodeIndex = this._rootNodeIndex; nodeIndex < nodesLength; nodeIndex += nodeFieldsCount) {
    969             var nodeOrdinal = nodeIndex / nodeFieldsCount;
     975        for (var nodeIndex = this._rootNodeIndex; nodeIndex < nodesLength; nodeIndex += nodeFieldCount) {
     976            var nodeOrdinal = nodeIndex / nodeFieldCount;
    970977            node.nodeIndex = nodeIndex;
    971978            var selfSize = nodes[nodeIndex + selfSizeOffset];
     
    10641071    },
    10651072
     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
    10661260    _buildDominatedNodes: function()
    10671261    {
     
    11571351                for (var edgesIter = node.edges; edgesIter.hasNext(); edgesIter.next())
    11581352                    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;
    11591409            }
    11601410        }
     
    11811431        var flags = this._flags;
    11821432        var list = [];
     1433
    11831434        for (var iter = this.rootNode.edges; iter.hasNext(); iter.next()) {
    11841435            if (iter.edge.node.isWindow)
     
    12131464        this._markDetachedDOMTreeNodes();
    12141465        this._markQueriableHeapObjects();
     1466        this._markPageOwnedNodes();
    12151467    },
    12161468
Note: See TracChangeset for help on using the changeset viewer.