+2012-02-08 Ilya Tikhonovsky <loislo@chromium.org>
+
+ Web Inspector: heap snapshot: implement Distance column in Object's retaining tree.
+ https://bugs.webkit.org/show_bug.cgi?id=78113
+
+ Retaining path list was replaced with Retaining tree some time ago.
+ But it was not so useful when we want to track the retaining path from an object to a DOM Window node.
+
+ Drive by fix: sort doesn't work in retaining tree panel.
+ Drive by fix: save/load child nodes doesn't work for the retaining tree panel.
+
+ Reviewed by Yury Semikhatsky.
+
+ * inspector/front-end/DetailedHeapshotGridNodes.js:
+ (WebInspector.HeapSnapshotObjectNode):
+ (WebInspector.HeapSnapshotObjectNode.prototype._childHashForEntity): save/load children fix
+ (WebInspector.HeapSnapshotObjectNode.prototype._childHashForNode): save/load children fix
+ (WebInspector.HeapSnapshotObjectNode.prototype.comparator):
+ (WebInspector.HeapSnapshotObjectNode.prototype._enhanceData):
+ * inspector/front-end/DetailedHeapshotView.js:
+ (WebInspector.HeapSnapshotContainmentDataGrid):
+ (WebInspector.HeapSnapshotRetainmentDataGrid):
+ (WebInspector.HeapSnapshotRetainmentDataGrid.prototype._sortFields):
+ * inspector/front-end/HeapSnapshot.js:
+ (WebInspector.HeapSnapshotRetainerEdge.prototype.set retainerIndex):
+ (WebInspector.HeapSnapshotRetainerEdge.prototype.set edgeIndex):
+ (WebInspector.HeapSnapshotRetainerEdge.prototype.get _node):
+ (WebInspector.HeapSnapshotRetainerEdge.prototype.get _edge):
+ (WebInspector.HeapSnapshotNode.prototype.get distanceToWindow):
+ (WebInspector.HeapSnapshot.prototype._init):
+ (WebInspector.HeapSnapshot.prototype._buildRetainers):
+ (WebInspector.HeapSnapshot.prototype._calculateObjectToWindowDistance):
+ (WebInspector.HeapSnapshot.prototype._bfs):
+ (WebInspector.HeapSnapshotEdgesProvider.prototype._serialize):
+ (WebInspector.HeapSnapshotEdgesProvider.prototype.sort.compareEdgeFieldName):
+ (WebInspector.HeapSnapshotEdgesProvider.prototype.sort.compareNodeField):
+ (WebInspector.HeapSnapshotEdgesProvider.prototype.sort.compareEdgeAndNode):
+ (WebInspector.HeapSnapshotEdgesProvider.prototype.sort.compareNodeAndEdge):
+ (WebInspector.HeapSnapshotEdgesProvider.prototype.sort.compareNodeAndNode):
+ (WebInspector.HeapSnapshotEdgesProvider.prototype.sort):
+ (WebInspector.HeapSnapshotNodesProvider.prototype._serialize):
+ * inspector/front-end/heapProfiler.css:
+ (.detailed-heapshot-view .data-grid td.distanceToWindow-column):
+
2012-02-08 Anders Carlsson <andersca@apple.com>
Fix assertion in svg/dom/SVGStyledElement-pendingResource-crash.html
this._referenceName = edge.name;
this._referenceType = edge.type;
this._propertyAccessor = edge.propertyAccessor;
+ this._distanceToWindow = edge.distanceToWindow;
this.showRetainingEdges = tree.showRetainingEdges;
this._isFromBaseSnapshot = isFromBaseSnapshot;
this._provider = this._createProvider(!isFromBaseSnapshot ? tree.snapshot : tree.baseSnapshot, edge.nodeIndex, tree);
_childHashForEntity: function(edge)
{
- return edge.type + "#" + edge.name;
+ var prefix = this.showRetainingEdges ? edge.node.id + "#" : "";
+ return prefix + edge.type + "#" + edge.name;
},
_childHashForNode: function(childNode)
{
- return childNode._referenceType + "#" + childNode._referenceName;
+ var prefix = this.showRetainingEdges ? childNode.snapshotNodeId + "#" : "";
+ return prefix + childNode._referenceType + "#" + childNode._referenceName;
},
comparator: function()
object: ["!edgeName", sortAscending, "retainedSize", false],
count: ["!edgeName", true, "retainedSize", false],
shallowSize: ["selfSize", sortAscending, "!edgeName", true],
- retainedSize: ["retainedSize", sortAscending, "!edgeName", true]
+ retainedSize: ["retainedSize", sortAscending, "!edgeName", true],
+ distanceToWindow: ["distanceToWindow", sortAscending, "_name", true]
}[sortColumnIdentifier] || ["!edgeName", true, "retainedSize", false];
return WebInspector.HeapSnapshotFilteredOrderedIterator.prototype.createComparator(sortFields);
},
}
data["object"].nameClass = nameClass;
data["object"].name = name;
+ data["distanceToWindow"] = this._distanceToWindow;
return data;
},
WebInspector.HeapSnapshotSortableDataGrid.prototype.__proto__ = WebInspector.DataGrid.prototype;
-WebInspector.HeapSnapshotContainmentDataGrid = function()
+WebInspector.HeapSnapshotContainmentDataGrid = function(columns)
{
- var columns = {
+ columns = columns || {
object: { title: WebInspector.UIString("Object"), disclosure: true, sortable: true },
shallowSize: { title: WebInspector.UIString("Shallow Size"), width: "120px", sortable: true },
retainedSize: { title: WebInspector.UIString("Retained Size"), width: "120px", sortable: true, sort: "descending" }
WebInspector.HeapSnapshotRetainmentDataGrid = function()
{
this.showRetainingEdges = true;
- WebInspector.HeapSnapshotContainmentDataGrid.call(this);
+ var columns = {
+ object: { title: WebInspector.UIString("Object"), disclosure: true, sortable: true },
+ shallowSize: { title: WebInspector.UIString("Shallow Size"), width: "120px", sortable: true },
+ retainedSize: { title: WebInspector.UIString("Retained Size"), width: "120px", sortable: true },
+ distanceToWindow: { title: WebInspector.UIString("Distance"), width: "80px", sortable: true, sort: "ascending" }
+ };
+ WebInspector.HeapSnapshotContainmentDataGrid.call(this, columns);
}
WebInspector.HeapSnapshotRetainmentDataGrid.prototype = {
+ _sortFields: function(sortColumn, sortAscending)
+ {
+ return {
+ object: ["_name", sortAscending, "_count", false],
+ count: ["_count", sortAscending, "_name", true],
+ shallowSize: ["_shallowSize", sortAscending, "_name", true],
+ retainedSize: ["_retainedSize", sortAscending, "_name", true],
+ distanceToWindow: ["_distanceToWindow", sortAscending, "_name", true]
+ }[sortColumn];
+ },
+
reset: function()
{
this.removeChildren();
{
if (newIndex !== this._retainerIndex) {
this._retainerIndex = newIndex;
- this._setupEdge();
+ this.edgeIndex = newIndex;
}
},
- _setupEdge: function()
+ set edgeIndex(edgeIndex)
{
- var globalEdgeIndex = this._retainers.item(this._retainerIndex);
- this._nodeIndex = this._snapshot._findNearestNodeIndex(globalEdgeIndex);
- this._node = new WebInspector.HeapSnapshotNode(this._snapshot, this._nodeIndex);
- var edgeIndex = globalEdgeIndex - this._nodeIndex - this._snapshot._firstEdgeOffset;
- this._edge = new WebInspector.HeapSnapshotEdge(this._snapshot, this._node.rawEdges, edgeIndex);
+ this._globalEdgeIndex = this._retainers.item(edgeIndex);
+ this._nodeIndex = this._snapshot._findNearestNodeIndex(this._globalEdgeIndex);
+ delete this._edgeInstance;
+ delete this._nodeInstance;
+ },
+
+ get _node()
+ {
+ if (!this._nodeInstance)
+ this._nodeInstance = new WebInspector.HeapSnapshotNode(this._snapshot, this._nodeIndex);
+ return this._nodeInstance;
+ },
+
+ get _edge()
+ {
+ if (!this._edgeInstance) {
+ var edgeIndex = this._globalEdgeIndex - this._nodeIndex - this._snapshot._firstEdgeOffset;
+ this._edgeInstance = new WebInspector.HeapSnapshotEdge(this._snapshot, this._node.rawEdges, edgeIndex);
+ }
+ return this._edgeInstance;
},
toString: function()
return !!(flags & this._snapshot._nodeFlags.canBeQueried);
},
+ get distanceToWindow()
+ {
+ return this._snapshot._distancesToWindow[this.nodeIndex];
+ },
+
get className()
{
switch (this.type) {
detachedDOMTreeNode: 2,
};
+ this._distancesToWindow = [];
this._markInvisibleEdges();
},
dataCallback(indexCallback(retIndex), node.nodeIndex + this._firstEdgeOffset + edge.edgeIndex);
}
}).bind(this));
+ this._calculateObjectToWindowDistance();
+ },
+
+ _calculateObjectToWindowDistance: function()
+ {
+ this._distancesToWindow = new Array(this.nodeCount);
+
+ // bfs for DOMWindow roots
+ var list = [];
+ for (var iter = this.rootNode.edges; iter.hasNext(); iter.next()) {
+ if (iter.edge.node.isDOMWindow) {
+ list.push(iter.edge.node);
+ this._distancesToWindow[iter.edge.node.nodeIndex] = 0;
+ }
+ }
+ this._bfs(list);
+
+ // bfs for root
+ list = [];
+ list.push(this.rootNode);
+ this._distancesToWindow[this.rootNode.nodeIndex] = 0;
+ this._bfs(list);
+ },
+
+ _bfs: function(list)
+ {
+ var index = 0;
+ while (index < list.length) {
+ var node = list[index++]; // shift generates too much garbage.
+ if (index > 100000) {
+ list = list.slice(index);
+ index = 0;
+ }
+ var distance = this._distancesToWindow[node.nodeIndex] + 1;
+ for (var iter = node.edges; iter.hasNext(); iter.next()) {
+ var edge = iter.edge;
+ var childNode = edge.node;
+ if (typeof this._distancesToWindow[childNode.nodeIndex] !== "undefined")
+ continue;
+ this._distancesToWindow[childNode.nodeIndex] = distance;
+ list.push(childNode);
+ }
+ }
},
_buildAggregates: function(filter)
WebInspector.HeapSnapshotEdgesProvider.prototype = {
_serialize: function(edge)
{
- return {name: edge.name, propertyAccessor: edge.toString(), node: WebInspector.HeapSnapshotNodesProvider.prototype._serialize(edge.node), nodeIndex: edge.nodeIndex, type: edge.type};
+ return {
+ name: edge.name,
+ propertyAccessor: edge.toString(),
+ node: WebInspector.HeapSnapshotNodesProvider.prototype._serialize(edge.node),
+ nodeIndex: edge.nodeIndex,
+ type: edge.type,
+ distanceToWindow: edge.node.distanceToWindow
+ };
},
sort: function(comparator, leftBound, rightBound, count)
var nodeA = new WebInspector.HeapSnapshotNode(this.snapshot);
var nodeB = new WebInspector.HeapSnapshotNode(this.snapshot);
- function sortByEdgeFieldName(ascending, indexA, indexB)
+ function compareEdgeFieldName(ascending, indexA, indexB)
{
edgeA.edgeIndex = indexA;
edgeB.edgeIndex = indexB;
return ascending ? result : -result;
}
- function sortByNodeField(fieldName, ascending, indexA, indexB)
+ function compareNodeField(fieldName, ascending, indexA, indexB)
{
edgeA.edgeIndex = indexA;
- edgeB.edgeIndex = indexB;
nodeA.nodeIndex = edgeA.nodeIndex;
- nodeB.nodeIndex = edgeB.nodeIndex;
var valueA = nodeA[fieldName];
+
+ edgeB.edgeIndex = indexB;
+ nodeB.nodeIndex = edgeB.nodeIndex;
var valueB = nodeB[fieldName];
+
var result = valueA < valueB ? -1 : (valueA > valueB ? 1 : 0);
return ascending ? result : -result;
}
- function sortByEdgeAndNode(indexA, indexB) {
- var result = sortByEdgeFieldName(ascending1, indexA, indexB);
+ function compareEdgeAndNode(indexA, indexB) {
+ var result = compareEdgeFieldName(ascending1, indexA, indexB);
if (result === 0)
- result = sortByNodeField(fieldName2, ascending2, indexA, indexB);
+ result = compareNodeField(fieldName2, ascending2, indexA, indexB);
return result;
}
- function sortByNodeAndEdge(indexA, indexB) {
- var result = sortByNodeField(fieldName1, ascending1, indexA, indexB);
+ function compareNodeAndEdge(indexA, indexB) {
+ var result = compareNodeField(fieldName1, ascending1, indexA, indexB);
if (result === 0)
- result = sortByEdgeFieldName(ascending2, indexA, indexB);
+ result = compareEdgeFieldName(ascending2, indexA, indexB);
return result;
}
- function sortByNodeAndNode(indexA, indexB) {
- var result = sortByNodeField(fieldName1, ascending1, indexA, indexB);
+ function compareNodeAndNode(indexA, indexB) {
+ var result = compareNodeField(fieldName1, ascending1, indexA, indexB);
if (result === 0)
- result = sortByNodeField(fieldName2, ascending2, indexA, indexB);
+ result = compareNodeField(fieldName2, ascending2, indexA, indexB);
return result;
}
if (fieldName1 === "!edgeName")
- this._iterationOrder.sortRange(sortByEdgeAndNode, leftBound, rightBound, count);
+ this._iterationOrder.sortRange(compareEdgeAndNode, leftBound, rightBound, count);
else if (fieldName2 === "!edgeName")
- this._iterationOrder.sortRange(sortByNodeAndEdge, leftBound, rightBound, count);
+ this._iterationOrder.sortRange(compareNodeAndEdge, leftBound, rightBound, count);
else
- this._iterationOrder.sortRange(sortByNodeAndNode, leftBound, rightBound, count);
+ this._iterationOrder.sortRange(compareNodeAndNode, leftBound, rightBound, count);
}
};
WebInspector.HeapSnapshotNodesProvider.prototype = {
_serialize: function(node)
{
- return {id: node.id, name: node.name, nodeIndex: node.nodeIndex, retainedSize: node.retainedSize, selfSize: node.selfSize, type: node.type, flags: node.flags};
+ return {
+ id: node.id,
+ name: node.name,
+ nodeIndex: node.nodeIndex,
+ retainedSize: node.retainedSize,
+ selfSize: node.selfSize,
+ type: node.type,
+ flags: node.flags
+ };
},
sort: function(comparator, leftBound, rightBound, count)