<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[201196] branches/safari-602.1.32-branch</title>
</head>
<body>
<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; }
#msg dl a { font-weight: bold}
#msg dl a:link { color:#fc3; }
#msg dl a:active { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/201196">201196</a></dd>
<dt>Author</dt> <dd>bshafiei@apple.com</dd>
<dt>Date</dt> <dd>2016-05-19 15:58:32 -0700 (Thu, 19 May 2016)</dd>
</dl>
<h3>Log Message</h3>
<pre>Merge <a href="http://trac.webkit.org/projects/webkit/changeset/201183">r201183</a>. rdar://problem/26375866</pre>
<h3>Modified Paths</h3>
<ul>
<li><a href="#branchessafari602132branchLayoutTestsChangeLog">branches/safari-602.1.32-branch/LayoutTests/ChangeLog</a></li>
<li><a href="#branchessafari602132branchSourceWebInspectorUIChangeLog">branches/safari-602.1.32-branch/Source/WebInspectorUI/ChangeLog</a></li>
<li><a href="#branchessafari602132branchSourceWebInspectorUIUserInterfaceProxiesHeapSnapshotDiffProxyjs">branches/safari-602.1.32-branch/Source/WebInspectorUI/UserInterface/Proxies/HeapSnapshotDiffProxy.js</a></li>
<li><a href="#branchessafari602132branchSourceWebInspectorUIUserInterfaceProxiesHeapSnapshotNodeProxyjs">branches/safari-602.1.32-branch/Source/WebInspectorUI/UserInterface/Proxies/HeapSnapshotNodeProxy.js</a></li>
<li><a href="#branchessafari602132branchSourceWebInspectorUIUserInterfaceProxiesHeapSnapshotProxyjs">branches/safari-602.1.32-branch/Source/WebInspectorUI/UserInterface/Proxies/HeapSnapshotProxy.js</a></li>
<li><a href="#branchessafari602132branchSourceWebInspectorUIUserInterfaceProxiesHeapSnapshotWorkerProxyjs">branches/safari-602.1.32-branch/Source/WebInspectorUI/UserInterface/Proxies/HeapSnapshotWorkerProxy.js</a></li>
<li><a href="#branchessafari602132branchSourceWebInspectorUIUserInterfaceViewsHeapAllocationsTimelineViewjs">branches/safari-602.1.32-branch/Source/WebInspectorUI/UserInterface/Views/HeapAllocationsTimelineView.js</a></li>
<li><a href="#branchessafari602132branchSourceWebInspectorUIUserInterfaceViewsHeapSnapshotClassDataGridNodejs">branches/safari-602.1.32-branch/Source/WebInspectorUI/UserInterface/Views/HeapSnapshotClassDataGridNode.js</a></li>
<li><a href="#branchessafari602132branchSourceWebInspectorUIUserInterfaceViewsHeapSnapshotContentViewjs">branches/safari-602.1.32-branch/Source/WebInspectorUI/UserInterface/Views/HeapSnapshotContentView.js</a></li>
<li><a href="#branchessafari602132branchSourceWebInspectorUIUserInterfaceViewsHeapSnapshotDataGridTreejs">branches/safari-602.1.32-branch/Source/WebInspectorUI/UserInterface/Views/HeapSnapshotDataGridTree.js</a></li>
<li><a href="#branchessafari602132branchSourceWebInspectorUIUserInterfaceWorkersHeapSnapshotHeapSnapshotjs">branches/safari-602.1.32-branch/Source/WebInspectorUI/UserInterface/Workers/HeapSnapshot/HeapSnapshot.js</a></li>
<li><a href="#branchessafari602132branchSourceWebInspectorUIUserInterfaceWorkersHeapSnapshotHeapSnapshotWorkerjs">branches/safari-602.1.32-branch/Source/WebInspectorUI/UserInterface/Workers/HeapSnapshot/HeapSnapshotWorker.js</a></li>
</ul>
<h3>Added Paths</h3>
<ul>
<li><a href="#branchessafari602132branchLayoutTestsinspectorunittestsheapsnapshotcollectioneventexpectedtxt">branches/safari-602.1.32-branch/LayoutTests/inspector/unit-tests/heap-snapshot-collection-event-expected.txt</a></li>
<li><a href="#branchessafari602132branchLayoutTestsinspectorunittestsheapsnapshotcollectioneventhtml">branches/safari-602.1.32-branch/LayoutTests/inspector/unit-tests/heap-snapshot-collection-event.html</a></li>
</ul>
</div>
<div id="patch">
<h3>Diff</h3>
<a id="branchessafari602132branchLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: branches/safari-602.1.32-branch/LayoutTests/ChangeLog (201195 => 201196)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-602.1.32-branch/LayoutTests/ChangeLog        2016-05-19 22:58:13 UTC (rev 201195)
+++ branches/safari-602.1.32-branch/LayoutTests/ChangeLog        2016-05-19 22:58:32 UTC (rev 201196)
</span><span class="lines">@@ -1,5 +1,20 @@
</span><span class="cx"> 2016-05-19 Babak Shafiei <bshafiei@apple.com>
</span><span class="cx">
</span><ins>+ Merge r201183. rdar://problem/26375866
+
+ 2016-05-19 Joseph Pecoraro <pecoraro@apple.com>
+
+ Web Inspector: HeapSnapshot Instances view should remove dead objects
+ https://bugs.webkit.org/show_bug.cgi?id=157920
+ <rdar://problem/26375866>
+
+ Reviewed by Timothy Hatcher.
+
+ * inspector/unit-tests/heap-snapshot-collection-event-expected.txt: Added.
+ * inspector/unit-tests/heap-snapshot-collection-event.html: Added.
+
+2016-05-19 Babak Shafiei <bshafiei@apple.com>
+
</ins><span class="cx"> Merge r200651. rdar://problem/26188642
</span><span class="cx">
</span><span class="cx"> 2016-05-10 Joseph Pecoraro <pecoraro@apple.com>
</span></span></pre></div>
<a id="branchessafari602132branchLayoutTestsinspectorunittestsheapsnapshotcollectioneventexpectedtxt"></a>
<div class="addfile"><h4>Added: branches/safari-602.1.32-branch/LayoutTests/inspector/unit-tests/heap-snapshot-collection-event-expected.txt (0 => 201196)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-602.1.32-branch/LayoutTests/inspector/unit-tests/heap-snapshot-collection-event-expected.txt         (rev 0)
+++ branches/safari-602.1.32-branch/LayoutTests/inspector/unit-tests/heap-snapshot-collection-event-expected.txt        2016-05-19 22:58:32 UTC (rev 201196)
</span><span class="lines">@@ -0,0 +1,20 @@
</span><ins>+Testing HeapSnapshot CollectionEvent between snapshots.
+
+
+== Running test suite: HeapSnapshot.CollectionEvent
+-- Running test case: HeapSnapshot
+PASS: Should not have an error creating a snapshot.
+PASS: Should create HeapSnapshotProxy snapshot.
+
+-- Running test case: HeapSnapshotCollectionEvent
+PASS: Should not have an error creating a snapshot.
+PASS: Received HeapSnapshot.CollectionEvent.
+PASS: Collection should include at least 200 nodes (100 objects and 100 strings).
+PASS: Collection should affect the first snapshot.
+
+-- Running test case: HeapSnapshot.prototype.updateCategories
+PASS: 0 Objects were dead before.
+PASS: At least 100 Objects are dead after.
+PASS: 0 strings were dead before.
+PASS: At least 100 strings are dead after.
+
</ins></span></pre></div>
<a id="branchessafari602132branchLayoutTestsinspectorunittestsheapsnapshotcollectioneventhtml"></a>
<div class="addfile"><h4>Added: branches/safari-602.1.32-branch/LayoutTests/inspector/unit-tests/heap-snapshot-collection-event.html (0 => 201196)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-602.1.32-branch/LayoutTests/inspector/unit-tests/heap-snapshot-collection-event.html         (rev 0)
+++ branches/safari-602.1.32-branch/LayoutTests/inspector/unit-tests/heap-snapshot-collection-event.html        2016-05-19 22:58:32 UTC (rev 201196)
</span><span class="lines">@@ -0,0 +1,82 @@
</span><ins>+<!DOCTYPE html>
+<html>
+<head>
+<script src="../../http/tests/inspector/resources/inspector-test.js"></script>
+<script>
+function triggerCreateObjects() {
+ window.list = [];
+ for (let i = 0; i < 100; ++i)
+ window.list.push({key: "value" + i});
+}
+
+function triggerRemoveObjects() {
+ window.list = null;
+}
+
+function test()
+{
+ let suite = InspectorTest.createAsyncSuite("HeapSnapshot.CollectionEvent");
+
+ let snapshot = null;
+
+ suite.addTestCase({
+ name: "HeapSnapshot",
+ test: (resolve, reject) => {
+ InspectorTest.evaluateInPage("triggerCreateObjects()");
+ HeapAgent.snapshot((error, timestamp, snapshotStringData) => {
+ InspectorTest.expectThat(!error, "Should not have an error creating a snapshot.");
+ let workerProxy = WebInspector.HeapSnapshotWorkerProxy.singleton();
+ workerProxy.createSnapshot(snapshotStringData, ({objectId, snapshot: serializedSnapshot}) => {
+ snapshot = WebInspector.HeapSnapshotProxy.deserialize(objectId, serializedSnapshot);
+ InspectorTest.expectThat(snapshot, "Should create HeapSnapshotProxy snapshot.");
+ resolve();
+ });
+ });
+ }
+ });
+
+ suite.addTestCase({
+ name: "HeapSnapshotCollectionEvent",
+ test: (resolve, reject) => {
+ InspectorTest.evaluateInPage("triggerRemoveObjects()");
+
+ let workerProxy = WebInspector.HeapSnapshotWorkerProxy.singleton();
+ HeapAgent.snapshot((error, timestamp, snapshotStringData) => {
+ InspectorTest.expectThat(!error, "Should not have an error creating a snapshot.");
+ workerProxy.createSnapshot(snapshotStringData, ({objectId, snapshot: serializedSnapshot}) => {
+ // Ignore result. This should trigger the collection event.
+ });
+ });
+
+ workerProxy.addEventListener("HeapSnapshot.CollectionEvent", (event) => {
+ InspectorTest.pass("Received HeapSnapshot.CollectionEvent.");
+ InspectorTest.expectThat(Object.keys(event.data.collectedNodes).length >= 200, "Collection should include at least 200 nodes (100 objects and 100 strings).");
+ InspectorTest.expectThat(event.data.affectedSnapshots.includes(snapshot.identifier), "Collection should affect the first snapshot.");
+ resolve();
+ });
+ }
+ });
+
+ suite.addTestCase({
+ name: "HeapSnapshot.prototype.updateCategories",
+ test: (resolve, reject) => {
+ let categoriesBefore = snapshot.categories;
+ snapshot.updateCategories(() => {
+ let categoriesAfter = snapshot.categories;
+ InspectorTest.expectThat(categoriesBefore.get("Object").deadCount === 0, "0 Objects were dead before.");
+ InspectorTest.expectThat(categoriesAfter.get("Object").deadCount >= 100, "At least 100 Objects are dead after.");
+ InspectorTest.expectThat(categoriesBefore.get("string").deadCount === 0, "0 strings were dead before.");
+ InspectorTest.expectThat(categoriesAfter.get("string").deadCount >= 100, "At least 100 strings are dead after.");
+ resolve();
+ });
+ }
+ });
+
+ suite.runTestCasesAndFinish();
+}
+</script>
+</head>
+<body onload="runTest()">
+ <p>Testing HeapSnapshot CollectionEvent between snapshots.</p>
+</body>
+</html>
</ins></span></pre></div>
<a id="branchessafari602132branchSourceWebInspectorUIChangeLog"></a>
<div class="modfile"><h4>Modified: branches/safari-602.1.32-branch/Source/WebInspectorUI/ChangeLog (201195 => 201196)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-602.1.32-branch/Source/WebInspectorUI/ChangeLog        2016-05-19 22:58:13 UTC (rev 201195)
+++ branches/safari-602.1.32-branch/Source/WebInspectorUI/ChangeLog        2016-05-19 22:58:32 UTC (rev 201196)
</span><span class="lines">@@ -1,5 +1,97 @@
</span><span class="cx"> 2016-05-19 Babak Shafiei <bshafiei@apple.com>
</span><span class="cx">
</span><ins>+ Merge r201183. rdar://problem/26375866
+
+ 2016-05-19 Joseph Pecoraro <pecoraro@apple.com>
+
+ Web Inspector: HeapSnapshot Instances view should remove dead objects
+ https://bugs.webkit.org/show_bug.cgi?id=157920
+ <rdar://problem/26375866>
+
+ Reviewed by Timothy Hatcher.
+
+ * UserInterface/Workers/HeapSnapshot/HeapSnapshotWorker.js:
+ (HeapSnapshotWorker):
+ (HeapSnapshotWorker.prototype.clearSnapshots):
+ (HeapSnapshotWorker.prototype.createSnapshot):
+ Preserve a list of snapshots for this page's session. When
+ new snapshots come in we can determine which nodes have died
+ and update previous snapshots. Emit a CollectionEvent
+ containing the nodes that were deleted and affected snapshots.
+
+ * UserInterface/Workers/HeapSnapshot/HeapSnapshot.js:
+ (HeapSnapshot):
+ Stash the largest node identifier.
+ Create a byte-per-node list to mark it as dead or alive.
+ All snapshots start with all live nodes.
+
+ (HeapSnapshot.prototype.updateDeadNodesAndGatherCollectionData):
+ (HeapSnapshot.prototype._markDeadNodes):
+ When we get a new snapshot we can mark dead nodes in previous
+ snapshots. Determine the nodeIdentifiers of dead nodes, and
+ mark them as dead if they existed in previous snapshots.
+
+ (HeapSnapshot.buildCategories):
+ (HeapSnapshot.prototype.updateCategories):
+ (HeapSnapshotDiff.prototype.updateCategories):
+ Include a "deadCount" in category data. And provide a method
+ to return an updated category list.
+
+ (HeapSnapshot.prototype.serializeNode):
+ Include a "dead" property on nodes when they are first fetched.
+
+ * UserInterface/Proxies/HeapSnapshotDiffProxy.js:
+ (WebInspector.HeapSnapshotDiffProxy.prototype.updateForCollectionEvent):
+ (WebInspector.HeapSnapshotDiffProxy.prototype.updateCategories):
+ * UserInterface/Proxies/HeapSnapshotNodeProxy.js:
+ (WebInspector.HeapSnapshotNodeProxy):
+ (WebInspector.HeapSnapshotNodeProxy.deserialize):
+ * UserInterface/Proxies/HeapSnapshotProxy.js:
+ (WebInspector.HeapSnapshotProxy.prototype.updateForCollectionEvent):
+ (WebInspector.HeapSnapshotProxy.prototype.updateCategories):
+ Update snapshot proxies from a collection event by updating properties
+ and dispatching an event from the model object.
+
+ * UserInterface/Proxies/HeapSnapshotWorkerProxy.js:
+ (WebInspector.HeapSnapshotWorkerProxy):
+ (WebInspector.HeapSnapshotWorkerProxy.prototype.clearSnapshots):
+ (WebInspector.HeapSnapshotWorkerProxy.prototype._mainResourceDidChange):
+ Clear the session snapshot list when the main resource changes.
+ However we can't yet clear the HeapSnapshot objects on the worker
+ because we may still have UI that interact with them.
+
+ * UserInterface/Views/HeapAllocationsTimelineView.js:
+ (WebInspector.HeapAllocationsTimelineView):
+ (WebInspector.HeapAllocationsTimelineView.prototype.closed):
+ Register and unregister for HeapSnapshot collection events.
+
+ (WebInspector.HeapAllocationsTimelineView.prototype._heapSnapshotCollectionEvent.updateHeapSnapshotForEvent):
+ (WebInspector.HeapAllocationsTimelineView.prototype._heapSnapshotCollectionEvent):
+ Update all the snapshots we know about when a collection event happens.
+
+ * UserInterface/Views/HeapSnapshotClassDataGridNode.js:
+ (WebInspector.HeapSnapshotClassDataGridNode.prototype.removeCollectedNodes):
+ (WebInspector.HeapSnapshotClassDataGridNode.prototype.updateCount):
+ (WebInspector.HeapSnapshotClassDataGridNode.prototype._populate):
+ (WebInspector.HeapSnapshotClassDataGridNode.prototype._fetchBatch):
+ * UserInterface/Views/HeapSnapshotContentView.js:
+ (WebInspector.HeapSnapshotContentView.prototype._heapSnapshotDataGridTreeDidPopulate):
+ (WebInspector.HeapSnapshotContentView):
+ * UserInterface/Views/HeapSnapshotDataGridTree.js:
+ (WebInspector.HeapSnapshotDataGridTree):
+ (WebInspector.HeapSnapshotDataGridTree.prototype.removeChild):
+ (WebInspector.HeapSnapshotDataGridTree.prototype.removeCollectedNodes):
+ (WebInspector.HeapSnapshotDataGridTree.prototype._heapSnapshotCollectedNodes):
+ (WebInspector.HeapSnapshotInstancesDataGridTree.prototype.populateTopLevel):
+ (WebInspector.HeapSnapshotInstancesDataGridTree.prototype.removeCollectedNodes):
+ (WebInspector.HeapSnapshotInstancesDataGridTree):
+ Update the Instances DataGridTree UI when a collection event happens.
+ Remove any top level InstanceDataGridNodes that may be showing for collected nodes.
+ Update the category counts on the ClassDataGridNodes.
+ Update FetchMoreDataGridNodes to have updated counts (and replace removed nodes).
+
+2016-05-19 Babak Shafiei <bshafiei@apple.com>
+
</ins><span class="cx"> Merge r201177. rdar://problem/26373969
</span><span class="cx">
</span><span class="cx"> 2016-05-19 Timothy Hatcher <timothy@apple.com>
</span></span></pre></div>
<a id="branchessafari602132branchSourceWebInspectorUIUserInterfaceProxiesHeapSnapshotDiffProxyjs"></a>
<div class="modfile"><h4>Modified: branches/safari-602.1.32-branch/Source/WebInspectorUI/UserInterface/Proxies/HeapSnapshotDiffProxy.js (201195 => 201196)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-602.1.32-branch/Source/WebInspectorUI/UserInterface/Proxies/HeapSnapshotDiffProxy.js        2016-05-19 22:58:13 UTC (rev 201195)
+++ branches/safari-602.1.32-branch/Source/WebInspectorUI/UserInterface/Proxies/HeapSnapshotDiffProxy.js        2016-05-19 22:58:32 UTC (rev 201196)
</span><span class="lines">@@ -62,6 +62,16 @@
</span><span class="cx"> get totalObjectCount() { return this._totalObjectCount; }
</span><span class="cx"> get categories() { return this._categories; }
</span><span class="cx">
</span><ins>+ updateForCollectionEvent(event)
+ {
+ if (!event.data.affectedSnapshots.includes(this._snapshot2._identifier))
+ return;
+
+ this.updateCategories(() => {
+ this.dispatchEventToListeners(WebInspector.HeapSnapshotProxy.Event.CollectedNodes, event.data);
+ });
+ }
+
</ins><span class="cx"> allocationBucketCounts(bucketSizes, callback)
</span><span class="cx"> {
</span><span class="cx"> WebInspector.HeapSnapshotWorkerProxy.singleton().callMethod(this._proxyObjectId, "allocationBucketCounts", bucketSizes, callback);
</span><span class="lines">@@ -74,6 +84,14 @@
</span><span class="cx"> });
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+ updateCategories(callback)
+ {
+ WebInspector.HeapSnapshotWorkerProxy.singleton().callMethod(this._proxyObjectId, "updateCategories", (categories) => {
+ this._categories = Map.fromObject(categories);
+ callback();
+ });
+ }
+
</ins><span class="cx"> nodeWithIdentifier(nodeIdentifier, callback)
</span><span class="cx"> {
</span><span class="cx"> WebInspector.HeapSnapshotWorkerProxy.singleton().callMethod(this._proxyObjectId, "nodeWithIdentifier", nodeIdentifier, (serializedNode) => {
</span></span></pre></div>
<a id="branchessafari602132branchSourceWebInspectorUIUserInterfaceProxiesHeapSnapshotNodeProxyjs"></a>
<div class="modfile"><h4>Modified: branches/safari-602.1.32-branch/Source/WebInspectorUI/UserInterface/Proxies/HeapSnapshotNodeProxy.js (201195 => 201196)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-602.1.32-branch/Source/WebInspectorUI/UserInterface/Proxies/HeapSnapshotNodeProxy.js        2016-05-19 22:58:13 UTC (rev 201195)
+++ branches/safari-602.1.32-branch/Source/WebInspectorUI/UserInterface/Proxies/HeapSnapshotNodeProxy.js        2016-05-19 22:58:32 UTC (rev 201196)
</span><span class="lines">@@ -25,7 +25,7 @@
</span><span class="cx">
</span><span class="cx"> WebInspector.HeapSnapshotNodeProxy = class HeapSnapshotNodeProxy
</span><span class="cx"> {
</span><del>- constructor(snapshotObjectId, identifier, className, size, retainedSize, internal, gcRoot, dominatorNodeIdentifier, hasChildren)
</del><ins>+ constructor(snapshotObjectId, identifier, className, size, retainedSize, internal, gcRoot, dead, dominatorNodeIdentifier, hasChildren)
</ins><span class="cx"> {
</span><span class="cx"> this._proxyObjectId = snapshotObjectId;
</span><span class="cx">
</span><span class="lines">@@ -35,6 +35,7 @@
</span><span class="cx"> this.retainedSize = retainedSize;
</span><span class="cx"> this.internal = internal;
</span><span class="cx"> this.gcRoot = gcRoot;
</span><ins>+ this.dead = dead;
</ins><span class="cx"> this.dominatorNodeIdentifier = dominatorNodeIdentifier;
</span><span class="cx"> this.hasChildren = hasChildren;
</span><span class="cx"> }
</span><span class="lines">@@ -43,8 +44,8 @@
</span><span class="cx">
</span><span class="cx"> static deserialize(objectId, serializedNode)
</span><span class="cx"> {
</span><del>- let {id, className, size, retainedSize, internal, gcRoot, dominatorNodeIdentifier, hasChildren} = serializedNode;
- return new WebInspector.HeapSnapshotNodeProxy(objectId, id, className, size, retainedSize, internal, gcRoot, dominatorNodeIdentifier, hasChildren);
</del><ins>+ let {id, className, size, retainedSize, internal, gcRoot, dead, dominatorNodeIdentifier, hasChildren} = serializedNode;
+ return new WebInspector.HeapSnapshotNodeProxy(objectId, id, className, size, retainedSize, internal, gcRoot, dead, dominatorNodeIdentifier, hasChildren);
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> // Proxied
</span></span></pre></div>
<a id="branchessafari602132branchSourceWebInspectorUIUserInterfaceProxiesHeapSnapshotProxyjs"></a>
<div class="modfile"><h4>Modified: branches/safari-602.1.32-branch/Source/WebInspectorUI/UserInterface/Proxies/HeapSnapshotProxy.js (201195 => 201196)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-602.1.32-branch/Source/WebInspectorUI/UserInterface/Proxies/HeapSnapshotProxy.js        2016-05-19 22:58:13 UTC (rev 201195)
+++ branches/safari-602.1.32-branch/Source/WebInspectorUI/UserInterface/Proxies/HeapSnapshotProxy.js        2016-05-19 22:58:32 UTC (rev 201196)
</span><span class="lines">@@ -55,6 +55,16 @@
</span><span class="cx"> get totalObjectCount() { return this._totalObjectCount; }
</span><span class="cx"> get categories() { return this._categories; }
</span><span class="cx">
</span><ins>+ updateForCollectionEvent(event)
+ {
+ if (!event.data.affectedSnapshots.includes(this._identifier))
+ return;
+
+ this.updateCategories(() => {
+ this.dispatchEventToListeners(WebInspector.HeapSnapshotProxy.Event.CollectedNodes, event.data);
+ });
+ }
+
</ins><span class="cx"> allocationBucketCounts(bucketSizes, callback)
</span><span class="cx"> {
</span><span class="cx"> WebInspector.HeapSnapshotWorkerProxy.singleton().callMethod(this._proxyObjectId, "allocationBucketCounts", bucketSizes, callback);
</span><span class="lines">@@ -67,6 +77,14 @@
</span><span class="cx"> });
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+ updateCategories(callback)
+ {
+ WebInspector.HeapSnapshotWorkerProxy.singleton().callMethod(this._proxyObjectId, "updateCategories", (categories) => {
+ this._categories = Map.fromObject(categories);
+ callback();
+ });
+ }
+
</ins><span class="cx"> nodeWithIdentifier(nodeIdentifier, callback)
</span><span class="cx"> {
</span><span class="cx"> WebInspector.HeapSnapshotWorkerProxy.singleton().callMethod(this._proxyObjectId, "nodeWithIdentifier", nodeIdentifier, (serializedNode) => {
</span><span class="lines">@@ -74,3 +92,7 @@
</span><span class="cx"> });
</span><span class="cx"> }
</span><span class="cx"> };
</span><ins>+
+WebInspector.HeapSnapshotProxy.Event = {
+ CollectedNodes: "heap-snapshot-proxy-did-collect-nodes"
+};
</ins></span></pre></div>
<a id="branchessafari602132branchSourceWebInspectorUIUserInterfaceProxiesHeapSnapshotWorkerProxyjs"></a>
<div class="modfile"><h4>Modified: branches/safari-602.1.32-branch/Source/WebInspectorUI/UserInterface/Proxies/HeapSnapshotWorkerProxy.js (201195 => 201196)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-602.1.32-branch/Source/WebInspectorUI/UserInterface/Proxies/HeapSnapshotWorkerProxy.js        2016-05-19 22:58:13 UTC (rev 201195)
+++ branches/safari-602.1.32-branch/Source/WebInspectorUI/UserInterface/Proxies/HeapSnapshotWorkerProxy.js        2016-05-19 22:58:32 UTC (rev 201196)
</span><span class="lines">@@ -34,6 +34,8 @@
</span><span class="cx">
</span><span class="cx"> this._nextCallId = 1;
</span><span class="cx"> this._callbacks = new Map;
</span><ins>+
+ WebInspector.Frame.addEventListener(WebInspector.Frame.Event.MainResourceDidChange, this._mainResourceDidChange, this);
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> // Static
</span><span class="lines">@@ -47,6 +49,11 @@
</span><span class="cx">
</span><span class="cx"> // Actions
</span><span class="cx">
</span><ins>+ clearSnapshots(callback)
+ {
+ this.performAction("clearSnapshots", callback);
+ }
+
</ins><span class="cx"> createSnapshot(snapshotStringData, callback)
</span><span class="cx"> {
</span><span class="cx"> this.performAction("createSnapshot", ...arguments);
</span><span class="lines">@@ -88,6 +95,14 @@
</span><span class="cx">
</span><span class="cx"> // Private
</span><span class="cx">
</span><ins>+ _mainResourceDidChange(event)
+ {
+ if (!event.target.isMainFrame())
+ return;
+
+ this.clearSnapshots(function(){});
+ }
+
</ins><span class="cx"> _postMessage()
</span><span class="cx"> {
</span><span class="cx"> this._heapSnapshotWorker.postMessage(...arguments);
</span></span></pre></div>
<a id="branchessafari602132branchSourceWebInspectorUIUserInterfaceViewsHeapAllocationsTimelineViewjs"></a>
<div class="modfile"><h4>Modified: branches/safari-602.1.32-branch/Source/WebInspectorUI/UserInterface/Views/HeapAllocationsTimelineView.js (201195 => 201196)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-602.1.32-branch/Source/WebInspectorUI/UserInterface/Views/HeapAllocationsTimelineView.js        2016-05-19 22:58:13 UTC (rev 201195)
+++ branches/safari-602.1.32-branch/Source/WebInspectorUI/UserInterface/Views/HeapAllocationsTimelineView.js        2016-05-19 22:58:32 UTC (rev 201196)
</span><span class="lines">@@ -89,6 +89,8 @@
</span><span class="cx"> this._pendingRecords = [];
</span><span class="cx">
</span><span class="cx"> timeline.addEventListener(WebInspector.Timeline.Event.RecordAdded, this._heapAllocationsTimelineRecordAdded, this);
</span><ins>+
+ WebInspector.HeapSnapshotWorkerProxy.singleton().addEventListener("HeapSnapshot.CollectionEvent", this._heapSnapshotCollectionEvent, this);
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> // Public
</span><span class="lines">@@ -227,6 +229,8 @@
</span><span class="cx"> this._dataGrid.closed();
</span><span class="cx">
</span><span class="cx"> this._contentViewContainer.closeAllContentViews();
</span><ins>+
+ WebInspector.HeapSnapshotWorkerProxy.singleton().removeEventListener("HeapSnapshot.CollectionEvent", this._heapSnapshotCollectionEvent, this);
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> layout()
</span><span class="lines">@@ -269,6 +273,22 @@
</span><span class="cx"> this.needsLayout();
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+ _heapSnapshotCollectionEvent(event)
+ {
+ function updateHeapSnapshotForEvent(heapSnapshot) {
+ heapSnapshot.updateForCollectionEvent(event);
+ }
+
+ for (let node of this._dataGrid.children)
+ updateHeapSnapshotForEvent(node.record.heapSnapshot);
+ for (let record of this._pendingRecords)
+ updateHeapSnapshotForEvent(record.heapSnapshot);
+ if (this._heapSnapshotDiff)
+ updateHeapSnapshotForEvent(this._heapSnapshotDiff);
+
+ // FIXME: <https://webkit.org/b/157904> Web Inspector: Snapshot List should show the total size and the total live size
+ }
+
</ins><span class="cx"> _snapshotListPathComponentClicked(event)
</span><span class="cx"> {
</span><span class="cx"> this.showHeapSnapshotList();
</span></span></pre></div>
<a id="branchessafari602132branchSourceWebInspectorUIUserInterfaceViewsHeapSnapshotClassDataGridNodejs"></a>
<div class="modfile"><h4>Modified: branches/safari-602.1.32-branch/Source/WebInspectorUI/UserInterface/Views/HeapSnapshotClassDataGridNode.js (201195 => 201196)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-602.1.32-branch/Source/WebInspectorUI/UserInterface/Views/HeapSnapshotClassDataGridNode.js        2016-05-19 22:58:13 UTC (rev 201195)
+++ branches/safari-602.1.32-branch/Source/WebInspectorUI/UserInterface/Views/HeapSnapshotClassDataGridNode.js        2016-05-19 22:58:32 UTC (rev 201196)
</span><span class="lines">@@ -92,6 +92,43 @@
</span><span class="cx"> }
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+ removeCollectedNodes(collectedNodes)
+ {
+ let nodesToRemove = [];
+
+ this.forEachImmediateChild((dataGridNode) => {
+ if (dataGridNode instanceof WebInspector.HeapSnapshotInstanceDataGridNode) {
+ let heapSnapshotNode = dataGridNode.node;
+ if (heapSnapshotNode.id in collectedNodes)
+ nodesToRemove.push(dataGridNode);
+ }
+ });
+
+ if (nodesToRemove.length) {
+ for (let dataGridNode of nodesToRemove)
+ this.removeChild(dataGridNode);
+ }
+
+ if (this._instances) {
+ this._instances = this._instances.filter((instance) => !(instance.id in collectedNodes));
+ this._fetchBatch(nodesToRemove.length);
+ }
+ }
+
+ updateCount(count)
+ {
+ if (count === this._data.count)
+ return;
+
+ if (!count) {
+ this._tree.removeChild(this);
+ return;
+ }
+
+ this._data.count = count;
+ this.needsRefresh();
+ }
+
</ins><span class="cx"> // Private
</span><span class="cx">
</span><span class="cx"> _populate()
</span><span class="lines">@@ -99,7 +136,8 @@
</span><span class="cx"> this.removeEventListener("populate", this._populate, this);
</span><span class="cx">
</span><span class="cx"> this._tree.heapSnapshot.instancesWithClassName(this._data.className, (instances) => {
</span><del>- this._instances = instances;
</del><ins>+ // FIXME: <https://webkit.org/b/157905> Web Inspector: Provide a way to toggle between showing only live objects and live+dead objects
+ this._instances = instances.filter((instance) => !instance.dead);
</ins><span class="cx"> this._sortInstances();
</span><span class="cx">
</span><span class="cx"> // Batch.
</span><span class="lines">@@ -128,9 +166,11 @@
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> let count = newCount - oldCount;
</span><del>- for (let i = 0; i <= count; ++i) {
- let instance = this._instances[oldCount + i];
- this.appendChild(new WebInspector.HeapSnapshotInstanceDataGridNode(instance, this._tree));
</del><ins>+ if (count) {
+ for (let i = 0; i <= count; ++i) {
+ let instance = this._instances[oldCount + i];
+ this.appendChild(new WebInspector.HeapSnapshotInstanceDataGridNode(instance, this._tree));
+ }
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> if (this._batched)
</span></span></pre></div>
<a id="branchessafari602132branchSourceWebInspectorUIUserInterfaceViewsHeapSnapshotContentViewjs"></a>
<div class="modfile"><h4>Modified: branches/safari-602.1.32-branch/Source/WebInspectorUI/UserInterface/Views/HeapSnapshotContentView.js (201195 => 201196)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-602.1.32-branch/Source/WebInspectorUI/UserInterface/Views/HeapSnapshotContentView.js        2016-05-19 22:58:13 UTC (rev 201195)
+++ branches/safari-602.1.32-branch/Source/WebInspectorUI/UserInterface/Views/HeapSnapshotContentView.js        2016-05-19 22:58:32 UTC (rev 201196)
</span><span class="lines">@@ -86,6 +86,7 @@
</span><span class="cx">
</span><span class="cx"> _heapSnapshotDataGridTreeDidPopulate()
</span><span class="cx"> {
</span><ins>+ this._dataGrid.removeChildren();
</ins><span class="cx"> for (let child of this._heapSnapshotDataGridTree.children)
</span><span class="cx"> this._dataGrid.appendChild(child);
</span><span class="cx"> }
</span></span></pre></div>
<a id="branchessafari602132branchSourceWebInspectorUIUserInterfaceViewsHeapSnapshotDataGridTreejs"></a>
<div class="modfile"><h4>Modified: branches/safari-602.1.32-branch/Source/WebInspectorUI/UserInterface/Views/HeapSnapshotDataGridTree.js (201195 => 201196)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-602.1.32-branch/Source/WebInspectorUI/UserInterface/Views/HeapSnapshotDataGridTree.js        2016-05-19 22:58:13 UTC (rev 201195)
+++ branches/safari-602.1.32-branch/Source/WebInspectorUI/UserInterface/Views/HeapSnapshotDataGridTree.js        2016-05-19 22:58:32 UTC (rev 201196)
</span><span class="lines">@@ -32,6 +32,7 @@
</span><span class="cx"> console.assert(heapSnapshot instanceof WebInspector.HeapSnapshotProxy || heapSnapshot instanceof WebInspector.HeapSnapshotDiffProxy);
</span><span class="cx">
</span><span class="cx"> this._heapSnapshot = heapSnapshot;
</span><ins>+ this._heapSnapshot.addEventListener(WebInspector.HeapSnapshotProxy.Event.CollectedNodes, this._heapSnapshotCollectedNodes, this);
</ins><span class="cx">
</span><span class="cx"> this._children = [];
</span><span class="cx"> this._sortComparator = sortComparator;
</span><span class="lines">@@ -106,6 +107,11 @@
</span><span class="cx"> this._children.splice(index, 0, node);
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+ removeChild(node)
+ {
+ this._children.remove(node, true);
+ }
+
</ins><span class="cx"> removeChildren()
</span><span class="cx"> {
</span><span class="cx"> this._children = [];
</span><span class="lines">@@ -160,12 +166,24 @@
</span><span class="cx"> // Implemented by subclasses.
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+ removeCollectedNodes(collectedNodes)
+ {
+ // Implemented by subclasses.
+ }
+
</ins><span class="cx"> didPopulate()
</span><span class="cx"> {
</span><span class="cx"> this.sort();
</span><span class="cx">
</span><span class="cx"> this.dispatchEventToListeners(WebInspector.HeapSnapshotDataGridTree.Event.DidPopulate);
</span><span class="cx"> }
</span><ins>+
+ // Private
+
+ _heapSnapshotCollectedNodes(event)
+ {
+ this.removeCollectedNodes(event.data.collectedNodes);
+ }
</ins><span class="cx"> };
</span><span class="cx">
</span><span class="cx"> WebInspector.HeapSnapshotDataGridTree.Event = {
</span><span class="lines">@@ -182,14 +200,33 @@
</span><span class="cx"> populateTopLevel()
</span><span class="cx"> {
</span><span class="cx"> // Populate the first level with the different non-internal classes.
</span><del>- for (let [className, {size, retainedSize, count, internalCount}] of this.heapSnapshot.categories) {
</del><ins>+ for (let [className, {size, retainedSize, count, internalCount, deadCount}] of this.heapSnapshot.categories) {
</ins><span class="cx"> if (count === internalCount)
</span><span class="cx"> continue;
</span><del>- this.appendChild(new WebInspector.HeapSnapshotClassDataGridNode({className, size, retainedSize, count}, this));
</del><ins>+
+ // FIXME: <https://webkit.org/b/157905> Web Inspector: Provide a way to toggle between showing only live objects and live+dead objects
+ let liveCount = count - deadCount;
+ if (!liveCount)
+ continue;
+
+ this.appendChild(new WebInspector.HeapSnapshotClassDataGridNode({className, size, retainedSize, count: liveCount}, this));
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> this.didPopulate()
</span><span class="cx"> }
</span><ins>+
+ removeCollectedNodes(collectedNodes)
+ {
+ for (let classDataGridNode of this.children) {
+ let {count, deadCount} = this.heapSnapshot.categories.get(classDataGridNode.data.className);
+ let liveCount = count - deadCount;
+ classDataGridNode.updateCount(liveCount);
+ if (liveCount)
+ classDataGridNode.removeCollectedNodes(collectedNodes);
+ }
+
+ this.didPopulate();
+ }
</ins><span class="cx"> };
</span><span class="cx">
</span><span class="cx"> WebInspector.HeapSnapshotObjectGraphDataGridTree = class HeapSnapshotInstancesDataGridTree extends WebInspector.HeapSnapshotDataGridTree
</span></span></pre></div>
<a id="branchessafari602132branchSourceWebInspectorUIUserInterfaceWorkersHeapSnapshotHeapSnapshotjs"></a>
<div class="modfile"><h4>Modified: branches/safari-602.1.32-branch/Source/WebInspectorUI/UserInterface/Workers/HeapSnapshot/HeapSnapshot.js (201195 => 201196)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-602.1.32-branch/Source/WebInspectorUI/UserInterface/Workers/HeapSnapshot/HeapSnapshot.js        2016-05-19 22:58:13 UTC (rev 201195)
+++ branches/safari-602.1.32-branch/Source/WebInspectorUI/UserInterface/Workers/HeapSnapshot/HeapSnapshot.js        2016-05-19 22:58:32 UTC (rev 201196)
</span><span class="lines">@@ -52,7 +52,7 @@
</span><span class="cx">
</span><span class="cx"> // Terminology:
</span><span class="cx"> // - `nodeIndex` is an index into the `nodes` list.
</span><del>-// - `nodeOrdinal` is the order of the node in the `nodes` list. (nodeIndex / nodeFieldCount)
</del><ins>+// - `nodeOrdinal` is the order of the node in the `nodes` list. (nodeIndex / nodeFieldCount).
</ins><span class="cx"> // - `nodeIdentifier` is the node's id value. (nodes[nodeIndex + nodeIdOffset]).
</span><span class="cx"> // - `edgeIndex` is an index into the `edges` list.
</span><span class="cx"> //
</span><span class="lines">@@ -61,8 +61,9 @@
</span><span class="cx"> // Iterate edges by walking `edges` (edgeFieldCount) and checking if fromIdentifier is current.
</span><span class="cx"> // - _nodeOrdinalToFirstIncomingEdge - `nodeOrdinal` to `incomingEdgeIndex` in `incomingEdges`.
</span><span class="cx"> // Iterate edges by walking `incomingEdges` until `nodeOrdinal+1`'s first incoming edge index.
</span><del>-// - _nodeOrdinalToDominatorNodeOrdinal - `nodeOrdinal` to `nodeOrdinal` of dominator
-// - _nodeOrdinalToRetainedSizes - `nodeOrdinal` to retain size value
</del><ins>+// - _nodeOrdinalToDominatorNodeOrdinal - `nodeOrdinal` to `nodeOrdinal` of dominator.
+// - _nodeOrdinalToRetainedSizes - `nodeOrdinal` to retain size value.
+// - _nodeOrdinalIsDead - `nodeOrdinal` is dead or alive.
</ins><span class="cx"> //
</span><span class="cx"> // Temporary Lists:
</span><span class="cx"> // - nodeOrdinalToPostOrderIndex - `nodeOrdinal` to a `postOrderIndex`.
</span><span class="lines">@@ -96,10 +97,14 @@
</span><span class="cx">
</span><span class="cx"> this._totalSize = 0;
</span><span class="cx"> this._nodeIdentifierToOrdinal = new Map; // <node identifier> => nodeOrdinal
</span><ins>+ this._lastNodeIdentifier = 0;
</ins><span class="cx"> for (let nodeIndex = 0; nodeIndex < nodes.length; nodeIndex += nodeFieldCount) {
</span><span class="cx"> let nodeOrdinal = nodeIndex / nodeFieldCount;
</span><del>- this._nodeIdentifierToOrdinal.set(nodes[nodeIndex + nodeIdOffset], nodeOrdinal);
</del><ins>+ let nodeIdentifier = nodes[nodeIndex + nodeIdOffset];
+ this._nodeIdentifierToOrdinal.set(nodeIdentifier, nodeOrdinal);
</ins><span class="cx"> this._totalSize += nodes[nodeIndex + nodeSizeOffset];
</span><ins>+ if (nodeIdentifier > this._lastNodeIdentifier)
+ this._lastNodeIdentifier = nodeIdentifier;
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> // FIXME: Replace toIdentifier and fromIdentifier in edges with nodeIndex to reduce hash lookups?
</span><span class="lines">@@ -125,6 +130,8 @@
</span><span class="cx">
</span><span class="cx"> postOrderIndexToNodeOrdinal = null;
</span><span class="cx">
</span><ins>+ this._nodeOrdinalIsDead = new Uint8Array(this._nodeCount);
+
</ins><span class="cx"> this._categories = HeapSnapshot.buildCategories(this);
</span><span class="cx"> }
</span><span class="cx">
</span><span class="lines">@@ -137,6 +144,7 @@
</span><span class="cx"> let nodes = snapshot._nodes;
</span><span class="cx"> let nodeClassNamesTable = snapshot._nodeClassNamesTable;
</span><span class="cx"> let nodeOrdinalToRetainedSizes = snapshot._nodeOrdinalToRetainedSizes;
</span><ins>+ let nodeOrdinalIsDead = snapshot._nodeOrdinalIsDead;
</ins><span class="cx">
</span><span class="cx"> // Skip the <root> node.
</span><span class="cx"> let firstNodeIndex = nodeFieldCount;
</span><span class="lines">@@ -150,16 +158,19 @@
</span><span class="cx"> let size = nodes[nodeIndex + nodeSizeOffset];
</span><span class="cx"> let retainedSize = nodeOrdinalToRetainedSizes[nodeOrdinal];
</span><span class="cx"> let internal = nodes[nodeIndex + nodeInternalOffset] ? true : false;
</span><ins>+ let dead = nodeOrdinalIsDead[nodeOrdinal] ? true : false;
</ins><span class="cx">
</span><span class="cx"> let category = categories[className];
</span><span class="cx"> if (!category)
</span><del>- category = categories[className] = {className, size: 0, retainedSize: 0, count: 0, internalCount: 0};
</del><ins>+ category = categories[className] = {className, size: 0, retainedSize: 0, count: 0, internalCount: 0, deadCount: 0};
</ins><span class="cx">
</span><span class="cx"> category.size += size;
</span><span class="cx"> category.retainedSize += retainedSize;
</span><span class="cx"> category.count += 1;
</span><span class="cx"> if (internal)
</span><span class="cx"> category.internalCount += 1;
</span><ins>+ if (dead)
+ category.deadCount += 1;
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> return categories;
</span><span class="lines">@@ -228,6 +239,11 @@
</span><span class="cx"> return HeapSnapshot.instancesWithClassName(this, className);
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+ updateCategories()
+ {
+ return HeapSnapshot.buildCategories(this);
+ }
+
</ins><span class="cx"> nodeWithIdentifier(nodeIdentifier)
</span><span class="cx"> {
</span><span class="cx"> let nodeOrdinal = this._nodeIdentifierToOrdinal.get(nodeIdentifier);
</span><span class="lines">@@ -323,10 +339,60 @@
</span><span class="cx"> };
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+ updateDeadNodesAndGatherCollectionData(snapshots)
+ {
+ let previousSnapshotIndex = snapshots.indexOf(this) - 1;
+ let previousSnapshot = snapshots[previousSnapshotIndex];
+ console.assert(previousSnapshot instanceof HeapSnapshot);
+ if (!previousSnapshot)
+ return;
+
+ let lastNodeIdentifier = previousSnapshot._lastNodeIdentifier;
+
+ // All of the node identifiers that could have existed prior to this snapshot.
+ let known = new Map;
+ for (let nodeIndex = 0; nodeIndex < this._nodes.length; nodeIndex += nodeFieldCount) {
+ let nodeIdentifier = this._nodes[nodeIndex + nodeIdOffset];
+ if (nodeIdentifier > lastNodeIdentifier)
+ continue;
+ known.set(nodeIdentifier, nodeIndex);
+ }
+
+ // Determine which node identifiers have since been deleted.
+ let collectedNodesList = [];
+ for (let nodeIndex = 0; nodeIndex < previousSnapshot._nodes.length; nodeIndex += nodeFieldCount) {
+ let nodeIdentifier = previousSnapshot._nodes[nodeIndex + nodeIdOffset];
+ let wasDeleted = !known.has(nodeIdentifier);
+ if (wasDeleted)
+ collectedNodesList.push(nodeIdentifier);
+ }
+
+ // Update dead nodes in previous snapshots.
+ let affectedSnapshots = [];
+ for (let snapshot of snapshots) {
+ if (snapshot === this)
+ break;
+ if (snapshot._markDeadNodes(collectedNodesList))
+ affectedSnapshots.push(snapshot._identifier);
+ }
+
+ // Convert list to a map.
+ let collectedNodes = {};
+ for (let i = 0; i < collectedNodesList.length; ++i)
+ collectedNodes[collectedNodesList[i]] = true;
+
+ return {
+ collectedNodes,
+ affectedSnapshots,
+ };
+ }
+
</ins><span class="cx"> // Public
</span><span class="cx">
</span><span class="cx"> serialize()
</span><span class="cx"> {
</span><ins>+ // FIXME: <https://webkit.org/b/157904> Web Inspector: Snapshot List should show the total size and the total live size
+
</ins><span class="cx"> return {
</span><span class="cx"> identifier: this._identifier,
</span><span class="cx"> title: this._title,
</span><span class="lines">@@ -356,6 +422,7 @@
</span><span class="cx"> retainedSize: this._nodeOrdinalToRetainedSizes[nodeOrdinal],
</span><span class="cx"> internal: this._nodes[nodeIndex + nodeInternalOffset] ? true : false,
</span><span class="cx"> gcRoot: this._nodeOrdinalIsGCRoot[nodeOrdinal] ? true : false,
</span><ins>+ dead: this._nodeOrdinalIsDead[nodeOrdinal] ? true : false,
</ins><span class="cx"> dominatorNodeIdentifier,
</span><span class="cx"> hasChildren,
</span><span class="cx"> };
</span><span class="lines">@@ -619,6 +686,22 @@
</span><span class="cx"> }
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+ _markDeadNodes(collectedNodesList)
+ {
+ let affected = false;
+
+ for (let i = 0; i < collectedNodesList.length; ++i) {
+ let nodeIdentifier = collectedNodesList[i];
+ if (nodeIdentifier > this._lastNodeIdentifier)
+ continue;
+ let nodeOrdinal = this._nodeIdentifierToOrdinal.get(nodeIdentifier);
+ this._nodeOrdinalIsDead[nodeOrdinal] = 1;
+ affected = true;
+ }
+
+ return affected;
+ }
+
</ins><span class="cx"> _isNodeGlobalObject(nodeIndex)
</span><span class="cx"> {
</span><span class="cx"> let className = this._nodeClassNamesTable[this._nodes[nodeIndex + nodeClassNameOffset]];
</span><span class="lines">@@ -725,6 +808,11 @@
</span><span class="cx"> return HeapSnapshot.instancesWithClassName(this._snapshot2, className, (nodeIdentifier) => this._addedNodeIdentifiers.has(nodeIdentifier));
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+ updateCategories()
+ {
+ return HeapSnapshot.buildCategories(this._snapshot2, (nodeIdentifier) => this._addedNodeIdentifiers.has(nodeIdentifier));
+ }
+
</ins><span class="cx"> nodeWithIdentifier(nodeIdentifier) { return this._snapshot2.nodeWithIdentifier(nodeIdentifier); }
</span><span class="cx"> shortestGCRootPath(nodeIdentifier) { return this._snapshot2.shortestGCRootPath(nodeIdentifier); }
</span><span class="cx"> dominatedNodes(nodeIdentifier) { return this._snapshot2.dominatedNodes(nodeIdentifier); }
</span></span></pre></div>
<a id="branchessafari602132branchSourceWebInspectorUIUserInterfaceWorkersHeapSnapshotHeapSnapshotWorkerjs"></a>
<div class="modfile"><h4>Modified: branches/safari-602.1.32-branch/Source/WebInspectorUI/UserInterface/Workers/HeapSnapshot/HeapSnapshotWorker.js (201195 => 201196)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-602.1.32-branch/Source/WebInspectorUI/UserInterface/Workers/HeapSnapshot/HeapSnapshotWorker.js        2016-05-19 22:58:13 UTC (rev 201195)
+++ branches/safari-602.1.32-branch/Source/WebInspectorUI/UserInterface/Workers/HeapSnapshot/HeapSnapshotWorker.js        2016-05-19 22:58:32 UTC (rev 201196)
</span><span class="lines">@@ -33,17 +33,37 @@
</span><span class="cx"> {
</span><span class="cx"> this._nextObjectId = 1;
</span><span class="cx"> this._objects = new Map;
</span><ins>+ this._snapshots = [];
</ins><span class="cx">
</span><span class="cx"> self.addEventListener("message", this._handleMessage.bind(this));
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> // Actions
</span><span class="cx">
</span><ins>+ clearSnapshots()
+ {
+ // FIXME: <https://webkit.org/b/157907> Web Inspector: Snapshots should be cleared at some point
+ // this._objects.clear();
+
+ this._snapshots = [];
+ }
+
</ins><span class="cx"> createSnapshot(snapshotString, title)
</span><span class="cx"> {
</span><span class="cx"> let objectId = this._nextObjectId++;
</span><span class="cx"> let snapshot = new HeapSnapshot(objectId, snapshotString, title);
</span><ins>+ this._snapshots.push(snapshot);
</ins><span class="cx"> this._objects.set(objectId, snapshot);
</span><ins>+
+ if (this._snapshots.length > 1) {
+ setTimeout(() => {
+ let collectionData = snapshot.updateDeadNodesAndGatherCollectionData(this._snapshots);
+ if (!collectionData.affectedSnapshots.length)
+ return;
+ this.sendEvent("HeapSnapshot.CollectionEvent", collectionData);
+ }, 0);
+ }
+
</ins><span class="cx"> return {objectId, snapshot: snapshot.serialize()};
</span><span class="cx"> }
</span><span class="cx">
</span></span></pre>
</div>
</div>
</body>
</html>