2011-04-13 Mikhail Naganov <mnaganov@chromium.org>
authormnaganov@chromium.org <mnaganov@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 13 Apr 2011 11:35:00 +0000 (11:35 +0000)
committermnaganov@chromium.org <mnaganov@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 13 Apr 2011 11:35:00 +0000 (11:35 +0000)
        Reviewed by Pavel Feldman.

        Web Inspector: [Chromium] Prepare to move detailed heap snapshots storage and processing into workers.
        https://bugs.webkit.org/show_bug.cgi?id=58320

        Introduce a proxy object that emulates worker behavior and change UI code to cope with it.

        * inspector/profiler/detailed-heapshots-test.js:
        (initialize_DetailedHeapshotTest):

2011-04-13  Mikhail Naganov  <mnaganov@chromium.org>

        Reviewed by Pavel Feldman.

        Web Inspector: [Chromium] Prepare to move detailed heap snapshots storage and processing into workers.
        https://bugs.webkit.org/show_bug.cgi?id=58320

        Introduce a proxy object that emulates worker behavior and change UI code to cope with it.

        * WebCore.gypi:
        * WebCore.vcproj/WebCore.vcproj:
        * inspector/front-end/DetailedHeapshotGridNodes.js:
        (WebInspector.HeapSnapshotGridNode.prototype._populate.doPopulate.sorted):
        (WebInspector.HeapSnapshotGridNode.prototype._populate.doPopulate):
        (WebInspector.HeapSnapshotGridNode.prototype._populate):
        (WebInspector.HeapSnapshotGridNode.prototype.populateChildren.childrenRetrieved.notify):
        (WebInspector.HeapSnapshotGridNode.prototype.populateChildren.childrenRetrieved):
        (WebInspector.HeapSnapshotGridNode.prototype.populateChildren):
        (WebInspector.HeapSnapshotGridNode.prototype.sort.doSort.afterSort.afterPopulate):
        (WebInspector.HeapSnapshotGridNode.prototype.sort.doSort.afterSort):
        (WebInspector.HeapSnapshotGridNode.prototype.sort):
        (WebInspector.HeapSnapshotGenericObjectNode):
        (WebInspector.HeapSnapshotGenericObjectNode.prototype.get _shallowSizePercent):
        (WebInspector.HeapSnapshotGenericObjectNode.prototype._updateHasChildren):
        (WebInspector.HeapSnapshotObjectNode):
        (WebInspector.HeapSnapshotObjectNode.prototype._createChildNode):
        (WebInspector.HeapSnapshotObjectNode.prototype._createProvider):
        (WebInspector.HeapSnapshotInstanceNode):
        (WebInspector.HeapSnapshotInstanceNode.prototype._createChildNode):
        (WebInspector.HeapSnapshotInstanceNode.prototype._createProvider):
        (WebInspector.HeapSnapshotConstructorNode.prototype._createChildNode):
        (WebInspector.HeapSnapshotConstructorNode.prototype._createNodesProvider):
        (WebInspector.HeapSnapshotIteratorsTuple.prototype.sortAndRewind):
        (WebInspector.HeapSnapshotDiffNode.prototype._calculateDiff):
        (WebInspector.HeapSnapshotDiffNode.prototype._createChildNode):
        (WebInspector.HeapSnapshotDiffNode.prototype._createNodesProvider.createProvider):
        (WebInspector.HeapSnapshotDiffNode.prototype._createNodesProvider):
        (WebInspector.HeapSnapshotDiffNode.prototype._childHashForEntity):
        (WebInspector.HeapSnapshotDiffNode.prototype._childHashForNode):
        (WebInspector.HeapSnapshotDiffNode.prototype.populateChildren.firstProviderPopulated):
        (WebInspector.HeapSnapshotDiffNode.prototype.populateChildren.else.firstProviderPopulated):
        (WebInspector.HeapSnapshotDiffNode.prototype.populateChildren):
        (WebInspector.HeapSnapshotDominatorObjectNode):
        (WebInspector.HeapSnapshotDominatorObjectNode.prototype._createChildNode):
        (WebInspector.HeapSnapshotDominatorObjectNode.prototype._createProvider):
        * inspector/front-end/DetailedHeapshotView.js:
        (WebInspector.HeapSnapshotSortableDataGrid.prototype.sortingChanged):
        (WebInspector.HeapSnapshotSortableDataGrid.prototype._performSorting):
        (WebInspector.HeapSnapshotConstructorsDataGrid.prototype.setDataSource):
        (WebInspector.HeapSnapshotConstructorsDataGrid.prototype.populateChildren):
        (WebInspector.HeapSnapshotDiffDataGrid.prototype.setBaseDataSource.baseSnapshotNodeIdsReceived):
        (WebInspector.HeapSnapshotDiffDataGrid.prototype.setBaseDataSource.pushBaseSnapshotNodeIds):
        (WebInspector.HeapSnapshotDiffDataGrid.prototype.setBaseDataSource.snapshotNodeIdsReceived):
        (WebInspector.HeapSnapshotDiffDataGrid.prototype.setBaseDataSource):
        (WebInspector.HeapSnapshotDiffDataGrid.prototype.populateChildren.baseAggregatesReceived.aggregatesReceived):
        (WebInspector.HeapSnapshotDiffDataGrid.prototype.populateChildren):
        (WebInspector.HeapSnapshotRetainingPathsList):
        (WebInspector.HeapSnapshotRetainingPathsList.prototype._resetPaths):
        (WebInspector.HeapSnapshotRetainingPathsList.prototype.setDataSource):
        (WebInspector.HeapSnapshotRetainingPathsList.prototype.refresh):
        (WebInspector.HeapSnapshotRetainingPathsList.prototype.showNext.pathFound):
        (WebInspector.HeapSnapshotRetainingPathsList.prototype.showNext.startSearching):
        (WebInspector.HeapSnapshotRetainingPathsList.prototype.showNext):
        (WebInspector.DetailedHeapshotView.profileCallback):
        (WebInspector.DetailedHeapshotView):
        (WebInspector.DetailedHeapshotView.prototype.get profileWrapper):
        (WebInspector.DetailedHeapshotView.prototype.get baseProfileWrapper):
        (WebInspector.DetailedHeapshotView.prototype.show.profileCallback1):
        (WebInspector.DetailedHeapshotView.prototype.show.profileCallback2):
        (WebInspector.DetailedHeapshotView.prototype.show):
        (WebInspector.DetailedHeapshotView.prototype._changeBase.baseProfileLoaded):
        * inspector/front-end/HeapSnapshot.js:
        * inspector/front-end/HeapSnapshotProxy.js: Added.
        * inspector/front-end/PleaseWaitMessage.js:
        * inspector/front-end/ProfilesPanel.js:
        (WebInspector.ProfilesPanel.prototype._reset):
        (WebInspector.ProfilesPanel.prototype.loadHeapSnapshot):
        (WebInspector.ProfilesPanel.prototype._addHeapSnapshotChunk):
        (WebInspector.ProfilesPanel.prototype._finishHeapSnapshot.doParse):
        (WebInspector.ProfilesPanel.prototype._finishHeapSnapshot.else.parsed):
        (WebInspector.ProfilesPanel.prototype._finishHeapSnapshot):
        * inspector/front-end/WebKit.qrc:
        * inspector/front-end/inspector.html:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@83718 268f45cc-cd09-0410-ab3c-d52691b4dbfc

13 files changed:
LayoutTests/ChangeLog
LayoutTests/inspector/profiler/detailed-heapshots-test.js
Source/WebCore/ChangeLog
Source/WebCore/WebCore.gypi
Source/WebCore/WebCore.vcproj/WebCore.vcproj
Source/WebCore/inspector/front-end/DetailedHeapshotGridNodes.js
Source/WebCore/inspector/front-end/DetailedHeapshotView.js
Source/WebCore/inspector/front-end/HeapSnapshot.js
Source/WebCore/inspector/front-end/HeapSnapshotProxy.js [new file with mode: 0644]
Source/WebCore/inspector/front-end/PleaseWaitMessage.js
Source/WebCore/inspector/front-end/ProfilesPanel.js
Source/WebCore/inspector/front-end/WebKit.qrc
Source/WebCore/inspector/front-end/inspector.html

index ee78105..b83e07d 100644 (file)
@@ -1,3 +1,15 @@
+2011-04-13  Mikhail Naganov  <mnaganov@chromium.org>
+
+        Reviewed by Pavel Feldman.
+
+        Web Inspector: [Chromium] Prepare to move detailed heap snapshots storage and processing into workers.
+        https://bugs.webkit.org/show_bug.cgi?id=58320
+
+        Introduce a proxy object that emulates worker behavior and change UI code to cope with it.
+
+        * inspector/profiler/detailed-heapshots-test.js:
+        (initialize_DetailedHeapshotTest):
+
 2011-04-13  Csaba Osztrogonác  <ossy@webkit.org>
 
         Update Qt specific expected results after r83710.
index 20c459b..d3e4439 100644 (file)
@@ -169,7 +169,6 @@ InspectorTest.clickColumn = function(column, callback)
 
     function sortingComplete()
     {
-        this._currentGrid().removeEventListener("sorting complete", sortingComplete, this);
         InspectorTest.assertEquals(column.identifier, this._currentGrid().sortColumnIdentifier, "unexpected sorting");
         column.sort = this._currentGrid().sortOrder;
         function callCallback()
@@ -178,7 +177,7 @@ InspectorTest.clickColumn = function(column, callback)
         }
         setTimeout(callCallback, 0);
     }
-    this._currentGrid().addEventListener("sorting complete", sortingComplete, this);
+    InspectorTest._prepareForRecursiveSort(sortingComplete.bind(this));
     this._currentGrid()._clickInHeaderCell(event);
 };
 
@@ -359,12 +358,7 @@ InspectorTest.switchToView = function(title, callback)
         setTimeout(callback, 0);
         return;
     }
-    function sortingComplete()
-    {
-        view.views[index].grid.removeEventListener("sorting complete", sortingComplete, this);
-        setTimeout(callback, 0);
-    }
-    view.views[index].grid.addEventListener("sorting complete", sortingComplete, this);
+    InspectorTest._prepareForRecursiveSort(callback, view.views[index].grid);
     view._changeView({target: {selectedIndex: index}});
 };
 
@@ -398,6 +392,38 @@ InspectorTest._currentGrid = function()
     return WebInspector.panels.profiles.visibleView.dataGrid;
 };
 
+InspectorTest._prepareForRecursiveSort = function(callback, grid)
+{
+    if (InspectorTest._recursiveSortCallback)
+        console.error("Didn't finished with previous sorting");
+    InspectorTest._recursiveSortCallback = callback;
+    InspectorTest._recursiveSortDepth = 0;
+    grid = grid || InspectorTest._currentGrid();
+    grid.addEventListener("start sorting", InspectorTest._recursiveSortEnter, InspectorTest);
+    grid.addEventListener("sorting complete", InspectorTest._recursiveSortLeave, InspectorTest);
+    InspectorTest._recursiveSortGrid = grid;
+};
+
+InspectorTest._recursiveSortEnter = function()
+{
+    ++InspectorTest._recursiveSortDepth;
+    if (isNaN(InspectorTest._recursiveSortDepth))
+        console.error("Wasn't prepared to track sorting");
+};
+
+InspectorTest._recursiveSortLeave = function()
+{
+    if (!--InspectorTest._recursiveSortDepth) {
+        var callback = InspectorTest._recursiveSortCallback;
+        delete InspectorTest._recursiveSortCallback;
+        InspectorTest._recursiveSortGrid.removeEventListener("start sorting", InspectorTest._recursiveSortEnter, InspectorTest);
+        InspectorTest._recursiveSortGrid.removeEventListener("sorting complete", InspectorTest._recursiveSortLeave, InspectorTest);
+        setTimeout(callback, 0);
+    }
+    if (!(InspectorTest._recursiveSortDepth >= 0))
+        console.error("Bad sort nesting");
+};
+
 InspectorTest._snapshotViewShown = function()
 {
     if (InspectorTest._takeAndOpenSnapshotCallback) {
index db7084b..959caf8 100644 (file)
@@ -1,3 +1,87 @@
+2011-04-13  Mikhail Naganov  <mnaganov@chromium.org>
+
+        Reviewed by Pavel Feldman.
+
+        Web Inspector: [Chromium] Prepare to move detailed heap snapshots storage and processing into workers.
+        https://bugs.webkit.org/show_bug.cgi?id=58320
+
+        Introduce a proxy object that emulates worker behavior and change UI code to cope with it.
+
+        * WebCore.gypi:
+        * WebCore.vcproj/WebCore.vcproj:
+        * inspector/front-end/DetailedHeapshotGridNodes.js:
+        (WebInspector.HeapSnapshotGridNode.prototype._populate.doPopulate.sorted):
+        (WebInspector.HeapSnapshotGridNode.prototype._populate.doPopulate):
+        (WebInspector.HeapSnapshotGridNode.prototype._populate):
+        (WebInspector.HeapSnapshotGridNode.prototype.populateChildren.childrenRetrieved.notify):
+        (WebInspector.HeapSnapshotGridNode.prototype.populateChildren.childrenRetrieved):
+        (WebInspector.HeapSnapshotGridNode.prototype.populateChildren):
+        (WebInspector.HeapSnapshotGridNode.prototype.sort.doSort.afterSort.afterPopulate):
+        (WebInspector.HeapSnapshotGridNode.prototype.sort.doSort.afterSort):
+        (WebInspector.HeapSnapshotGridNode.prototype.sort):
+        (WebInspector.HeapSnapshotGenericObjectNode):
+        (WebInspector.HeapSnapshotGenericObjectNode.prototype.get _shallowSizePercent):
+        (WebInspector.HeapSnapshotGenericObjectNode.prototype._updateHasChildren):
+        (WebInspector.HeapSnapshotObjectNode):
+        (WebInspector.HeapSnapshotObjectNode.prototype._createChildNode):
+        (WebInspector.HeapSnapshotObjectNode.prototype._createProvider):
+        (WebInspector.HeapSnapshotInstanceNode):
+        (WebInspector.HeapSnapshotInstanceNode.prototype._createChildNode):
+        (WebInspector.HeapSnapshotInstanceNode.prototype._createProvider):
+        (WebInspector.HeapSnapshotConstructorNode.prototype._createChildNode):
+        (WebInspector.HeapSnapshotConstructorNode.prototype._createNodesProvider):
+        (WebInspector.HeapSnapshotIteratorsTuple.prototype.sortAndRewind):
+        (WebInspector.HeapSnapshotDiffNode.prototype._calculateDiff):
+        (WebInspector.HeapSnapshotDiffNode.prototype._createChildNode):
+        (WebInspector.HeapSnapshotDiffNode.prototype._createNodesProvider.createProvider):
+        (WebInspector.HeapSnapshotDiffNode.prototype._createNodesProvider):
+        (WebInspector.HeapSnapshotDiffNode.prototype._childHashForEntity):
+        (WebInspector.HeapSnapshotDiffNode.prototype._childHashForNode):
+        (WebInspector.HeapSnapshotDiffNode.prototype.populateChildren.firstProviderPopulated):
+        (WebInspector.HeapSnapshotDiffNode.prototype.populateChildren.else.firstProviderPopulated):
+        (WebInspector.HeapSnapshotDiffNode.prototype.populateChildren):
+        (WebInspector.HeapSnapshotDominatorObjectNode):
+        (WebInspector.HeapSnapshotDominatorObjectNode.prototype._createChildNode):
+        (WebInspector.HeapSnapshotDominatorObjectNode.prototype._createProvider):
+        * inspector/front-end/DetailedHeapshotView.js:
+        (WebInspector.HeapSnapshotSortableDataGrid.prototype.sortingChanged):
+        (WebInspector.HeapSnapshotSortableDataGrid.prototype._performSorting):
+        (WebInspector.HeapSnapshotConstructorsDataGrid.prototype.setDataSource):
+        (WebInspector.HeapSnapshotConstructorsDataGrid.prototype.populateChildren):
+        (WebInspector.HeapSnapshotDiffDataGrid.prototype.setBaseDataSource.baseSnapshotNodeIdsReceived):
+        (WebInspector.HeapSnapshotDiffDataGrid.prototype.setBaseDataSource.pushBaseSnapshotNodeIds):
+        (WebInspector.HeapSnapshotDiffDataGrid.prototype.setBaseDataSource.snapshotNodeIdsReceived):
+        (WebInspector.HeapSnapshotDiffDataGrid.prototype.setBaseDataSource):
+        (WebInspector.HeapSnapshotDiffDataGrid.prototype.populateChildren.baseAggregatesReceived.aggregatesReceived):
+        (WebInspector.HeapSnapshotDiffDataGrid.prototype.populateChildren):
+        (WebInspector.HeapSnapshotRetainingPathsList):
+        (WebInspector.HeapSnapshotRetainingPathsList.prototype._resetPaths):
+        (WebInspector.HeapSnapshotRetainingPathsList.prototype.setDataSource):
+        (WebInspector.HeapSnapshotRetainingPathsList.prototype.refresh):
+        (WebInspector.HeapSnapshotRetainingPathsList.prototype.showNext.pathFound):
+        (WebInspector.HeapSnapshotRetainingPathsList.prototype.showNext.startSearching):
+        (WebInspector.HeapSnapshotRetainingPathsList.prototype.showNext):
+        (WebInspector.DetailedHeapshotView.profileCallback):
+        (WebInspector.DetailedHeapshotView):
+        (WebInspector.DetailedHeapshotView.prototype.get profileWrapper):
+        (WebInspector.DetailedHeapshotView.prototype.get baseProfileWrapper):
+        (WebInspector.DetailedHeapshotView.prototype.show.profileCallback1):
+        (WebInspector.DetailedHeapshotView.prototype.show.profileCallback2):
+        (WebInspector.DetailedHeapshotView.prototype.show):
+        (WebInspector.DetailedHeapshotView.prototype._changeBase.baseProfileLoaded):
+        * inspector/front-end/HeapSnapshot.js:
+        * inspector/front-end/HeapSnapshotProxy.js: Added.
+        * inspector/front-end/PleaseWaitMessage.js:
+        * inspector/front-end/ProfilesPanel.js:
+        (WebInspector.ProfilesPanel.prototype._reset):
+        (WebInspector.ProfilesPanel.prototype.loadHeapSnapshot):
+        (WebInspector.ProfilesPanel.prototype._addHeapSnapshotChunk):
+        (WebInspector.ProfilesPanel.prototype._finishHeapSnapshot.doParse):
+        (WebInspector.ProfilesPanel.prototype._finishHeapSnapshot.else.parsed):
+        (WebInspector.ProfilesPanel.prototype._finishHeapSnapshot):
+        * inspector/front-end/WebKit.qrc:
+        * inspector/front-end/inspector.html:
+
 2011-04-13  Alexander Pavlov  <apavlov@chromium.org>
 
         Reviewed by Pavel Feldman.
index 32459f8..167acf9 100644 (file)
             'inspector/front-end/GoToLineDialog.js',
             'inspector/front-end/HAREntry.js',
             'inspector/front-end/HeapSnapshot.js',
+            'inspector/front-end/HeapSnapshotProxy.js',
             'inspector/front-end/HeapSnapshotView.js',
             'inspector/front-end/HelpScreen.js',
             'inspector/front-end/ImageView.js',
index 6fcb79b..74c468c 100755 (executable)
                                        >
                                </File>
                                <File
+                                       RelativePath="..\inspector\front-end\HeapSnapshotProxy.js"
+                                       >
+                               </File>
+                               <File
                                        RelativePath="..\inspector\front-end\HeapSnapshotView.js"
                                        >
                                </File>
index 469cb94..47e36b9 100644 (file)
@@ -52,13 +52,15 @@ WebInspector.HeapSnapshotGridNode.prototype = {
         function doPopulate()
         {
             this.removeEventListener("populate", this._populate, this);
-            this._provider.sort(this.comparator());
-            this._provider.first();
-            this.populateChildren();
+            function sorted(ignored)
+            {
+                this.populateChildren();
+            }
+            this._provider.sortAndRewind(this.comparator(), sorted.bind(this));
         }
     },
 
-    populateChildren: function(provider, howMany, atIndex, suppressNotifyAboutCompletion)
+    populateChildren: function(provider, howMany, atIndex, afterPopulate, suppressNotifyAboutCompletion)
     {
         if (!howMany && provider) {
             howMany = provider.instanceCount;
@@ -77,21 +79,35 @@ WebInspector.HeapSnapshotGridNode.prototype = {
                 break;
             }
         }
-        for ( ; howMany > 0 && provider.hasNext(); provider.next(), ++provider.instanceCount, --howMany) {
-            var item = provider.item;
-            if (haveSavedChildren) {
-                var hash = this._childHashForEntity(item);
-                if (hash in this._savedChildren) {
-                    this.insertChild(this._savedChildren[hash], atIndex++);
-                    continue;
+        
+        function childrenRetrieved(items, hasNext, length)
+        {
+            for (var i = 0, l = items.length; i < l; ++i) {
+                var item = items[i];
+                if (haveSavedChildren) {
+                    var hash = this._childHashForEntity(item);
+                    if (hash in this._savedChildren) {
+                        this.insertChild(this._savedChildren[hash], atIndex++);
+                        continue;
+                    }
+                }
+                this.insertChild(this._createChildNode(item, provider), atIndex++);
+            }
+            provider.instanceCount += items.length;
+
+            if (hasNext)
+                this.insertChild(new WebInspector.ShowMoreDataGridNode(this.populateChildren.bind(this, provider), this._defaultPopulateCount, length), atIndex++);
+            if (afterPopulate)
+                afterPopulate();
+            if (!suppressNotifyAboutCompletion) {
+                function notify()
+                {
+                    this.dispatchEventToListeners("populate complete");
                 }
+                setTimeout(notify.bind(this), 0);
             }
-            this.insertChild(this._createChildNode(provider), atIndex++);
         }
-        if (provider.hasNext())
-            this.insertChild(new WebInspector.ShowMoreDataGridNode(this.populateChildren.bind(this, provider), this._defaultPopulateCount, provider.length), atIndex++);
-        if (!suppressNotifyAboutCompletion)
-            this.dispatchEventToListeners("populate complete");
+        provider.getNextItems(howMany, childrenRetrieved.bind(this));
     },
 
     _saveChildren: function()
@@ -106,33 +122,38 @@ WebInspector.HeapSnapshotGridNode.prototype = {
 
     sort: function()
     {
-        var comparator = this.comparator();
-        WebInspector.PleaseWaitMessage.prototype.startAction(this.dataGrid.element, doSort.bind(this));
-
         function doSort()
         {
-            if (this._provider.sort(comparator)) {
+            function afterSort(sorted)
+            {
+                if (!sorted)
+                    return;
                 this._saveChildren();
                 this.removeChildren();
-                this._provider.first();
-                this.populateChildren(this._provider);
-                for (var i = 0, l = this.children.length; i < l; ++i) {
-                    var child = this.children[i];
-                    if (child.expanded)
-                        child.sort();
+     
+                function afterPopulate()
+                {
+                    for (var i = 0, l = this.children.length; i < l; ++i) {
+                        var child = this.children[i];
+                        if (child.expanded)
+                            child.sort();
+                    }
+                    this.dataGrid.dispatchEventToListeners("sorting complete");
                 }
+                this.populateChildren(this._provider, null, null, afterPopulate.bind(this));
             }
-            if (this.dataGrid === this)
-                this.dispatchEventToListeners("sorting complete");
+            this._provider.sortAndRewind(this.comparator(), afterSort.bind(this));
         }
+        this.dataGrid.dispatchEventToListeners("start sorting");
+        WebInspector.PleaseWaitMessage.prototype.startAction(this.dataGrid.element, doSort.bind(this));
     }
 };
 
 WebInspector.HeapSnapshotGridNode.prototype.__proto__ = WebInspector.DataGridNode.prototype;
 
-WebInspector.HeapSnapshotGenericObjectNode = function(tree, node, hasChildren)
+WebInspector.HeapSnapshotGenericObjectNode = function(tree, node)
 {
-    WebInspector.HeapSnapshotGridNode.call(this, tree, hasChildren);
+    WebInspector.HeapSnapshotGridNode.call(this, tree, false);
     this._name = node.name;
     this._type = node.type;
     this._shallowSize = node.selfSize;
@@ -222,6 +243,15 @@ WebInspector.HeapSnapshotGenericObjectNode.prototype = {
     get _shallowSizePercent()
     {
         return this._shallowSize / this.dataGrid.snapshot.totalSize * 100.0;
+    },
+
+    _updateHasChildren: function()
+    {
+        function isEmptyCallback(isEmpty)
+        {
+            this.hasChildren = !isEmpty;
+        }
+        this._provider.isEmpty(isEmptyCallback.bind(this));
     }
 }
 
@@ -229,24 +259,23 @@ WebInspector.HeapSnapshotGenericObjectNode.prototype.__proto__ = WebInspector.He
 
 WebInspector.HeapSnapshotObjectNode = function(tree, edge)
 {
-    var provider = this._createProvider(tree.snapshot, edge.nodeIndex);
-    WebInspector.HeapSnapshotGenericObjectNode.call(this, tree, edge.node, !provider.isEmpty);
+    WebInspector.HeapSnapshotGenericObjectNode.call(this, tree, edge.node);
     this._referenceName = edge.name;
     this._referenceType = edge.type;
-    this._provider = provider;
+    this._provider = this._createProvider(tree.snapshot, edge.nodeIndex);
+    this._updateHasChildren();
 }
 
 WebInspector.HeapSnapshotObjectNode.prototype = {
-    _createChildNode: function(provider)
+    _createChildNode: function(item)
     {
-        return new WebInspector.HeapSnapshotObjectNode(this.dataGrid, provider.item);
+        return new WebInspector.HeapSnapshotObjectNode(this.dataGrid, item);
     },
 
     _createProvider: function(snapshot, nodeIndex)
     {
         var showHiddenData = WebInspector.DetailedHeapshotView.prototype.showHiddenData;
-        return new WebInspector.HeapSnapshotEdgesProvider(
-            snapshot,
+        return snapshot.createEdgesProvider(
             nodeIndex,
             function(edge) {
                 return !edge.isInvisible
@@ -318,23 +347,22 @@ WebInspector.HeapSnapshotObjectNode.prototype.__proto__ = WebInspector.HeapSnaps
 
 WebInspector.HeapSnapshotInstanceNode = function(tree, baseSnapshot, snapshot, node)
 {
-    var provider = this._createProvider(baseSnapshot || snapshot, node.nodeIndex);  
-    WebInspector.HeapSnapshotGenericObjectNode.call(this, tree, node, !provider.isEmpty);
+    WebInspector.HeapSnapshotGenericObjectNode.call(this, tree, node);
     this._isDeletedNode = !!baseSnapshot;
-    this._provider = provider;    
+    this._provider = this._createProvider(baseSnapshot || snapshot, node.nodeIndex);
+    this._updateHasChildren();
 };
 
 WebInspector.HeapSnapshotInstanceNode.prototype = {
-    _createChildNode: function(provider)
+    _createChildNode: function(item)
     {
-        return new WebInspector.HeapSnapshotObjectNode(this.dataGrid, provider.item);
+        return new WebInspector.HeapSnapshotObjectNode(this.dataGrid, item);
     },
 
     _createProvider: function(snapshot, nodeIndex)
     {
         var showHiddenData = WebInspector.DetailedHeapshotView.prototype.showHiddenData;
-        return new WebInspector.HeapSnapshotEdgesProvider(
-            snapshot,
+        return snapshot.createEdgesProvider(
             nodeIndex,
             function(edge) {
                 return !edge.isInvisible
@@ -402,15 +430,14 @@ WebInspector.HeapSnapshotConstructorNode = function(tree, className, aggregate)
 }
 
 WebInspector.HeapSnapshotConstructorNode.prototype = {
-    _createChildNode: function(provider)
+    _createChildNode: function(item)
     {
-        return new WebInspector.HeapSnapshotInstanceNode(this.dataGrid, null, this.dataGrid.snapshot, provider.item);
+        return new WebInspector.HeapSnapshotInstanceNode(this.dataGrid, null, this.dataGrid.snapshot, item);
     },
 
     _createNodesProvider: function(snapshot, nodeType, nodeClassName)
     {
-        return new WebInspector.HeapSnapshotNodesProvider(
-            snapshot,
+        return snapshot.createNodesProvider(
             function (node) {
                  return node.type === nodeType
                     && (nodeClassName === null || node.className === nodeClassName);
@@ -475,16 +502,13 @@ WebInspector.HeapSnapshotIteratorsTuple = function(it1, it2)
 }
 
 WebInspector.HeapSnapshotIteratorsTuple.prototype = {
-    first: function()
+    sortAndRewind: function(comparator, callback)
     {
-        this._it1.first();
-        this._it2.first();
-    },
-
-    sort: function(comparator)
-    {
-        this._it1.sort(comparator);
-        this._it2.sort(comparator);
+        function afterSort(ignored)
+        {
+            this._it2.sortAndRewind(comparator, callback);
+        }
+        this._it1.sortAndRewind(comparator, afterSort.bind(this));
     }
 };
 
@@ -509,8 +533,8 @@ WebInspector.HeapSnapshotDiffNode.prototype = {
         this._removedCount = 0;
         this._addedSize = 0;
         this._removedSize = 0;
-        var nodeA = new WebInspector.HeapSnapshotNode(baseSnapshot);
-        var nodeB = new WebInspector.HeapSnapshotNode(snapshot);
+        var nodeA = new WebInspector.HeapSnapshotNode(baseSnapshot._snapshot);
+        var nodeB = new WebInspector.HeapSnapshotNode(snapshot._snapshot);
         nodeA.nodeIndex = baseIndexes[i];
         nodeB.nodeIndex = currentIndexes[j];
         while (i < l && j < m) {
@@ -535,18 +559,18 @@ WebInspector.HeapSnapshotDiffNode.prototype = {
         while (j < m) {
             this._addedCount++;
             this._addedSize += nodeB.selfSize;
-            nodeB.nodeIndex = currentIndexes[++j];                
+            nodeB.nodeIndex = currentIndexes[++j];
         }
         this._countDelta = this._addedCount - this._removedCount;
         this._sizeDelta = this._addedSize - this._removedSize;
     },
 
-    _createChildNode: function(provider)
+    _createChildNode: function(item, provider)
     {
         if (provider === this._provider._it1)
-            return new WebInspector.HeapSnapshotInstanceNode(this.dataGrid, null, provider.snapshot, provider.item);
+            return new WebInspector.HeapSnapshotInstanceNode(this.dataGrid, null, provider.snapshot, item);
         else
-            return new WebInspector.HeapSnapshotInstanceNode(this.dataGrid, provider.snapshot, null, provider.item);
+            return new WebInspector.HeapSnapshotInstanceNode(this.dataGrid, provider.snapshot, null, item);
     },
 
     _createNodesProvider: function(baseSnapshot, snapshot, nodeType, nodeClassName)
@@ -556,16 +580,28 @@ WebInspector.HeapSnapshotDiffNode.prototype = {
 
         function createProvider(snapshot, otherSnapshot)
         {
-            return new WebInspector.HeapSnapshotNodesProvider(
-                snapshot,
+            var otherSnapshotId = otherSnapshot.uid;
+            var provider = snapshot.createNodesProvider(
                 function (node) {
                      return node.type === nodeType
                          && (nodeClassName === null || node.className === nodeClassName)
-                         && !otherSnapshot.hasId(node.id);
+                         && !this.snapshotHasNodeWithId(otherSnapshotId, node.id);
                 });
+            provider.snapshot = snapshot;
+            return provider;
         }
     },
 
+    _childHashForEntity: function(node)
+    {
+        return node.id;
+    },
+
+    _childHashForNode: function(childNode)
+    {
+        return childNode.snapshotNodeId;
+    },
+
     comparator: function()
     {
         var sortAscending = this.dataGrid.sortOrder === "ascending";
@@ -582,16 +618,22 @@ WebInspector.HeapSnapshotDiffNode.prototype = {
         return WebInspector.HeapSnapshotFilteredOrderedIterator.prototype.createComparator(sortFields);
     },
 
-    populateChildren: function(provider, howMany, atIndex)
+    populateChildren: function(provider, howMany, atIndex, afterPopulate)
     {
         if (!provider && !howMany) {
-            WebInspector.HeapSnapshotGridNode.prototype.populateChildren.call(this, this._provider._it1, this._defaultPopulateCount, null, true);
-            WebInspector.HeapSnapshotGridNode.prototype.populateChildren.call(this, this._provider._it2, this._defaultPopulateCount);
+            var firstProviderPopulated = function()
+            {
+                WebInspector.HeapSnapshotGridNode.prototype.populateChildren.call(this, this._provider._it2, this._defaultPopulateCount, atIndex, afterPopulate);
+            };
+            WebInspector.HeapSnapshotGridNode.prototype.populateChildren.call(this, this._provider._it1, this._defaultPopulateCount, atIndex, firstProviderPopulated.bind(this), true);
         } else if (!howMany) {
-            WebInspector.HeapSnapshotGridNode.prototype.populateChildren.call(this, this._provider._it1, null, null, true);
-            WebInspector.HeapSnapshotGridNode.prototype.populateChildren.call(this, this._provider._it2);
+            var firstProviderPopulated = function()
+            {
+                WebInspector.HeapSnapshotGridNode.prototype.populateChildren.call(this, this._provider._it2, null, atIndex, afterPopulate);
+            };
+            WebInspector.HeapSnapshotGridNode.prototype.populateChildren.call(this, this._provider._it1, null, atIndex, firstProviderPopulated.bind(this), true);
         } else
-            WebInspector.HeapSnapshotGridNode.prototype.populateChildren.call(this, provider, howMany, atIndex);
+            WebInspector.HeapSnapshotGridNode.prototype.populateChildren.call(this, provider, howMany, atIndex, afterPopulate);
     },
 
     _signForDelta: function(delta)
@@ -628,22 +670,21 @@ WebInspector.HeapSnapshotDiffNode.prototype.__proto__ = WebInspector.HeapSnapsho
 
 WebInspector.HeapSnapshotDominatorObjectNode = function(tree, node)
 {
-    var provider = this._createProvider(tree.snapshot, node.nodeIndex);
-    WebInspector.HeapSnapshotGenericObjectNode.call(this, tree, node, !provider.isEmpty);
-    this._provider = provider;
+    WebInspector.HeapSnapshotGenericObjectNode.call(this, tree, node);
+    this._provider = this._createProvider(tree.snapshot, node.nodeIndex);
+    this._updateHasChildren();
 };
 
 WebInspector.HeapSnapshotDominatorObjectNode.prototype = {
-    _createChildNode: function(provider)
+    _createChildNode: function(item)
     {
-        return new WebInspector.HeapSnapshotDominatorObjectNode(this.dataGrid, provider.item);
+        return new WebInspector.HeapSnapshotDominatorObjectNode(this.dataGrid, item);
     },
 
     _createProvider: function(snapshot, nodeIndex)
     {
         var showHiddenData = WebInspector.DetailedHeapshotView.prototype.showHiddenData;
-        return new WebInspector.HeapSnapshotNodesProvider(
-            snapshot,
+        return snapshot.createNodesProvider(
             function (node) {
                  var dominatorIndex = node.dominatorIndex;
                  return dominatorIndex === nodeIndex
index a21bf75..fa6189d 100644 (file)
@@ -66,6 +66,10 @@ WebInspector.HeapSnapshotSortableDataGrid.prototype = {
     {
         var sortAscending = this.sortOrder === "ascending";
         var sortColumnIdentifier = this.sortColumnIdentifier;
+        if (this._lastSortColumnIdentifier === sortColumnIdentifier && this._lastSortAscending === sortAscending)
+            return;
+        this._lastSortColumnIdentifier = sortColumnIdentifier;
+        this._lastSortAscending = sortAscending;
         var sortFields = this._sortFields(sortColumnIdentifier, sortAscending);
 
         function SortByTwoFields(nodeA, nodeB)
@@ -86,11 +90,11 @@ WebInspector.HeapSnapshotSortableDataGrid.prototype = {
         }
 
         this._performSorting(SortByTwoFields);
-        this.dispatchEventToListeners("sorting complete");
     },
 
     _performSorting: function(sortFunction)
     {
+        this.dispatchEventToListeners("start sorting");
         var children = this.children;
         this.removeChildren();
         children.sort(sortFunction);
@@ -100,6 +104,7 @@ WebInspector.HeapSnapshotSortableDataGrid.prototype = {
             if (child.expanded)
                 child.sort();
         }
+        this.dispatchEventToListeners("sorting complete");
     }
 };
 
@@ -134,14 +139,17 @@ WebInspector.HeapSnapshotConstructorsDataGrid.prototype = {
         this.snapshotView = snapshotView;
         this.snapshot = snapshot;
         this.populateChildren();
-        this.sortingChanged();
     },
 
     populateChildren: function()
     {
-        var aggregates = this.snapshot.aggregates();
-        for (var constructor in aggregates)
-            this.appendChild(new WebInspector.HeapSnapshotConstructorNode(this, constructor, aggregates[constructor]));
+        function aggregatesReceived(aggregates)
+        {
+            for (var constructor in aggregates)
+                this.appendChild(new WebInspector.HeapSnapshotConstructorNode(this, constructor, aggregates[constructor]));
+            this.sortingChanged();
+        }
+        this.snapshot.aggregates(false, aggregatesReceived.bind(this));
     }
 };
 
@@ -188,28 +196,55 @@ WebInspector.HeapSnapshotDiffDataGrid.prototype = {
     {
         this.baseSnapshot = baseSnapshot;
         this.removeChildren();
-        if (this.baseSnapshot !== this.snapshot) {
+        if (this.baseSnapshot === this.snapshot)
+            return;
+
+        function baseSnapshotNodeIdsReceived(nodeIds)
+        {
+            this.snapshot.pushSnapshotNodeIds(this.baseSnapshot.uid, nodeIds);
             this.populateChildren();
-            this.sortingChanged();
         }
+        function pushBaseSnapshotNodeIds()
+        {
+            if (!this.snapshot.hasSnapshotNodeIds(this.baseSnapshot.uid))
+                this.baseSnapshot.nodeIds(baseSnapshotNodeIdsReceived.bind(this));
+            else
+                this.populateChildren();        
+        }
+        function snapshotNodeIdsReceived(nodeIds)
+        {
+            this.baseSnapshot.pushSnapshotNodeIds(this.snapshot.uid, nodeIds);
+            pushBaseSnapshotNodeIds.call(this);
+        }
+        if (!this.baseSnapshot.hasSnapshotNodeIds(this.snapshot.uid))
+            this.snapshot.nodeIds(snapshotNodeIdsReceived.bind(this));
+        else
+            pushBaseSnapshotNodeIds.call(this);
     },
 
     populateChildren: function()
     {
-        var baseClasses = this.baseSnapshot.aggregates(true);
-        var classes = this.snapshot.aggregates(true);
-        for (var clss in baseClasses) {
-            var node = new WebInspector.HeapSnapshotDiffNode(this, clss, baseClasses[clss], classes[clss]);
-            if (!node.zeroDiff)
-                this.appendChild(node);
-        }
-        for (clss in classes) {
-            if (!(clss in baseClasses)) {
-                var node = new WebInspector.HeapSnapshotDiffNode(this, clss, null, classes[clss]);
-                if (!node.zeroDiff)
-                    this.appendChild(node);
+        function baseAggregatesReceived(baseClasses)
+        {
+            function aggregatesReceived(classes)
+            {
+                for (var clss in baseClasses) {
+                    var node = new WebInspector.HeapSnapshotDiffNode(this, clss, baseClasses[clss], classes[clss]);
+                    if (!node.zeroDiff)
+                        this.appendChild(node);
+                }
+                for (clss in classes) {
+                    if (!(clss in baseClasses)) {
+                        var node = new WebInspector.HeapSnapshotDiffNode(this, clss, null, classes[clss]);
+                        if (!node.zeroDiff)
+                            this.appendChild(node);
+                    }
+                }
+                this.sortingChanged();
             }
+            this.snapshot.aggregates(true, aggregatesReceived.bind(this));
         }
+        this.baseSnapshot.aggregates(true, baseAggregatesReceived.bind(this));
     }
 };
 
@@ -249,6 +284,7 @@ WebInspector.HeapSnapshotRetainingPathsList = function()
         len: { title: WebInspector.UIString("Length"), width: "90px", sortable: true, sort: "ascending" }
     };
     WebInspector.HeapSnapshotSortableDataGrid.call(this, columns);
+    this._defaultPopulateCount = 100;
 }
 
 WebInspector.HeapSnapshotRetainingPathsList.prototype = {
@@ -260,6 +296,14 @@ WebInspector.HeapSnapshotRetainingPathsList.prototype = {
         }[sortColumn];
     },
 
+    _resetPaths: function()
+    {
+        this._setRootChildrenForFinder();
+        this.removeChildren();
+        this._counter = 0;
+        this.showNext(this._defaultPopulateCount);
+    },
+
     setDataSource: function(snapshotView, snapshot, nodeIndex, prefix)
     {
         this.snapshotView = snapshotView;
@@ -267,53 +311,49 @@ WebInspector.HeapSnapshotRetainingPathsList.prototype = {
 
         if (this.pathFinder)
             this.searchCancelled();
-
-        this.pathFinder = new WebInspector.HeapSnapshotPathFinder(snapshot, nodeIndex);
-        this._setRootChildrenForFinder();
-
-        this.removeChildren();
-
-        this._counter = 0;
-        this.showNext(100);
+        this.pathFinder = snapshot.createPathFinder(nodeIndex);
+        this._resetPaths();
     },
 
     refresh: function()
     {
-        this.removeChildren();
-        this._counter = 0;
         delete this._cancel;
-        this._setRootChildrenForFinder();
-        this.showNext(100);
+        this._resetPaths();
     },
 
     showNext: function(pathsCount)
     {
         WebInspector.PleaseWaitMessage.prototype.show(this.element, this.searchCancelled.bind(this, pathsCount));
-        window.setTimeout(startSearching.bind(this), 500);
+
+        function pathFound(result)
+        {
+            if (result === null) {
+                WebInspector.PleaseWaitMessage.prototype.hide();
+                if (!this.children.length)
+                    this.appendChild(new WebInspector.DataGridNode({path:WebInspector.UIString("Can't find any paths."), len:""}, false));
+                return;
+            } else if (result !== false) {
+                if (this._prefix)
+                    result.path = this._prefix + result.path;
+                this.appendChild(new WebInspector.DataGridNode(result, false));
+                ++this._counter;
+            }
+            setTimeout(startSearching.bind(this), 0);
+        }
 
         function startSearching()
         {
-            if (this._cancel !== this.pathFinder) {
-                if (this._counter < pathsCount) {
-                    var result = this.pathFinder.findNext();
-                    if (result === null) {
-                        WebInspector.PleaseWaitMessage.prototype.hide();
-                        if (!this.children.length)
-                            this.appendChild(new WebInspector.DataGridNode({path:WebInspector.UIString("Can't find any paths."), len:""}, false));
-                        return;
-                    } else if (result !== false) {
-                        if (this._prefix)
-                            result.path = this._prefix + result.path;
-                        this.appendChild(new WebInspector.DataGridNode(result, false));
-                        ++this._counter;
-                    }
-                    window.setTimeout(startSearching.bind(this), 0);
-                    return;
-                } else
-                    this.searchCancelled.call(this, pathsCount);
+            if (this._cancel === this.pathFinder)
+                return;
+            delete this._cancel;
+            if (this._counter < pathsCount)
+                this.pathFinder.findNext(pathFound.bind(this));
+            else {
+                this.searchCancelled.call(this, pathsCount);
+                delete this._cancel;
             }
-            this._cancel = false;
         }
+        setTimeout(startSearching.bind(this), 0);
     },
 
     searchCancelled: function(pathsCount)
@@ -453,12 +493,12 @@ WebInspector.DetailedHeapshotView = function(parent, profile)
 
     this._loadProfile(this._profileUid, profileCallback.bind(this));
 
-    function profileCallback(profile)
+    function profileCallback()
     {
         var list = this._profiles();
         var profileIndex;
         for (var i = 0; i < list.length; ++i)
-            if (list[i].uid === profile.uid) {
+            if (list[i].uid === this._profileUid) {
                 profileIndex = i;
                 break;
             }
@@ -493,7 +533,7 @@ WebInspector.DetailedHeapshotView.prototype = {
     get profileWrapper()
     {
         if (!this._profileWrapper)
-            this._profileWrapper = new WebInspector.HeapSnapshot(this.profile);
+            this._profileWrapper = this.profile.proxy;
         return this._profileWrapper;
     },
 
@@ -504,34 +544,27 @@ WebInspector.DetailedHeapshotView.prototype = {
 
     get baseProfileWrapper()
     {
-        if (!this._baseProfileWrapper) {
-            if (this.baseProfile !== this.profile)
-                this._baseProfileWrapper = new WebInspector.HeapSnapshot(this.baseProfile);
-            else
-                this._baseProfileWrapper = this.profileWrapper;
-        }
+        if (!this._baseProfileWrapper)
+            this._baseProfileWrapper = this.baseProfile.proxy;
         return this._baseProfileWrapper;
     },
 
     show: function(parentElement)
     {
         WebInspector.View.prototype.show.call(this, parentElement);
-        if (!this.profile._loaded)
+        if (!this.profileWrapper.loaded)
             this._loadProfile(this._profileUid, profileCallback1.bind(this));
         else
-            profileCallback1.call(this, this.profile);
+            profileCallback1.call(this);
 
-        function profileCallback1(profile) {
-            this.profileWrapper.restore(profile);
-            if (this.baseProfile && !this.baseProfile._loaded)
+        function profileCallback1() {
+            if (this.baseProfile && !this.baseProfileWrapper.loaded)
                 this._loadProfile(this._baseProfileUid, profileCallback2.bind(this));
             else
-                profileCallback2.call(this, this.baseProfile);
+                profileCallback2.call(this);
         }
 
-        function profileCallback2(profile) {
-            if (profile)
-                this.baseProfileWrapper.restore(profile);
+        function profileCallback2() {
             this.currentView.show();
             this.dataGrid.updateWidths();
         }
@@ -700,7 +733,7 @@ WebInspector.DetailedHeapshotView.prototype = {
         this._baseProfileUid = this._profiles()[this.baseSelectElement.selectedIndex].uid;
         this._loadProfile(this._baseProfileUid, baseProfileLoaded.bind(this));
 
-        function baseProfileLoaded(profile)
+        function baseProfileLoaded()
         {
             delete this._baseProfileWrapper;
             this.baseProfile._lastShown = Date.now();
index c9d1e30..2b1afee 100644 (file)
@@ -552,12 +552,6 @@ WebInspector.HeapSnapshot.prototype = {
         return this._nodeCount;
     },
 
-    restore: function(profile)
-    {
-        this._nodes = profile.nodes;
-        this._strings = profile.strings;
-    },
-
     get rootNode()
     {
         return new WebInspector.HeapSnapshotNode(this, this._rootNodeIndex);
diff --git a/Source/WebCore/inspector/front-end/HeapSnapshotProxy.js b/Source/WebCore/inspector/front-end/HeapSnapshotProxy.js
new file mode 100644 (file)
index 0000000..19a61d4
--- /dev/null
@@ -0,0 +1,263 @@
+/*
+ * Copyright (C) 2011 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyrightdd
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.HeapSnapshotProxy = function()
+{   
+    this._snapshot = null;
+    this._nodeIds = [];
+}
+
+WebInspector.HeapSnapshotProxy.prototype = {
+    _invokeGetter: function(getterName, callback)
+    {
+        function returnResult()
+        {
+            callback(this._snapshot[getterName]);
+        }
+        setTimeout(returnResult.bind(this), 0);
+    },
+
+    aggregates: function(withNodeIndexes, callback)
+    {
+        function returnResult()
+        {
+            callback(this._snapshot.aggregates(withNodeIndexes));
+        }
+        setTimeout(returnResult.bind(this), 0);
+    },
+
+    _extractEdgeData: function(edge)
+    {
+        return {name: edge.name, node: this._extractNodeData(edge.node), nodeIndex: edge.nodeIndex, type: edge.type};
+    },
+
+    _extractNodeData: function(node)
+    {
+        return {id: node.id, name: node.name, nodeIndex: node.nodeIndex, retainedSize: node.retainedSize, selfSize: node.selfSize, type: node.type};
+    },
+
+    createEdgesProvider: function(nodeIndex, filter)
+    {
+        function createProvider()
+        {
+            if (filter)
+                filter = filter.bind(this);
+            return new WebInspector.HeapSnapshotEdgesProvider(this._snapshot, nodeIndex, filter);
+        }
+        return new WebInspector.HeapSnapshotProviderProxy(createProvider.bind(this), this._extractEdgeData.bind(this));
+    },
+
+    createNodesProvider: function(filter)
+    {
+        function createProvider()
+        {
+            if (filter)
+                filter = filter.bind(this);
+            return new WebInspector.HeapSnapshotNodesProvider(this._snapshot, filter);
+        }
+        return new WebInspector.HeapSnapshotProviderProxy(createProvider.bind(this), this._extractNodeData.bind(this));
+    },
+
+    createPathFinder: function(targetNodeIndex)
+    {
+        return new WebInspector.HeapSnapshotPathFinderProxy(new WebInspector.HeapSnapshotPathFinder(this._snapshot, targetNodeIndex));
+    },
+
+    dispose: function()
+    {
+        this._snapshot.dispose();
+        delete this._nodeIds;
+    },
+
+    hasSnapshotNodeIds: function(snapshotId)
+    {
+        return snapshotId in this._nodeIds;
+    },
+
+    finishLoading: function(callback)
+    {
+        if (this._snapshot || !this._isLoading)
+            return false;
+        function parse() {
+            var rawSnapshot = JSON.parse(this._json);
+            var loadCallbacks = this._onLoadCallbacks;
+            loadCallbacks.splice(0, 0, callback);
+            delete this._onLoadCallback;
+            delete this._json;
+            delete this._isLoading;
+            this._snapshot = new WebInspector.HeapSnapshot(rawSnapshot);
+            this._nodeCount = this._snapshot.nodeCount;
+            this._rootNodeIndex = this._snapshot._rootNodeIndex;
+            this._totalSize = this._snapshot.totalSize;
+            for (var i = 0; i < loadCallbacks.length; ++i)
+                loadCallbacks[i]();
+        }
+        setTimeout(parse.bind(this), 0);
+        return true;
+    },
+
+    get loaded()
+    {
+        return !!this._snapshot;
+    },
+
+    get nodeCount()
+    {
+        return this._nodeCount;
+    },
+
+    nodeIds: function(callback)
+    {
+        this._invokeGetter("nodeIds", callback);
+    },
+
+    pushJSONChunk: function(chunk)
+    {
+        if (this.loaded || !this._isLoading)
+            return;
+        this._json += chunk;
+    },
+
+    pushSnapshotNodeIds: function(snapshotId, nodeIds)
+    {
+        this._nodeIds[snapshotId] = nodeIds;
+    },
+
+    get rootNodeIndex()
+    {
+        return this._rootNodeIndex;
+    },
+
+    snapshotHasNodeWithId: function(snapshotId, nodeId)
+    {
+        var nodeIds = this._nodeIds[snapshotId];
+        if (nodeIds)
+            return nodeIds.binaryIndexOf(nodeId, this._snapshot._numbersComparator) >= 0;
+        else
+            return false;
+    },
+
+    startLoading: function(callback)
+    {
+        if (this._snapshot) {
+            function asyncInvoke()
+            {
+                callback();
+            }
+            setTimeout(callback, 0);
+            return false;
+        } else if (this._isLoading) {
+            this._onLoadCallbacks.push(callback);
+            return false;
+        } else {
+            this._isLoading = true;
+            this._onLoadCallbacks = [callback];
+            this._json = "";
+            return true;
+        }
+    },
+
+    get totalSize()
+    {
+        return this._totalSize;
+    },
+
+    get uid()
+    {
+        return this._snapshot.uid;
+    }
+};
+
+WebInspector.HeapSnapshotProviderProxy = function(createProvider, extractData)
+{
+    this._provider = createProvider();
+    this._extractData = extractData;
+}
+
+WebInspector.HeapSnapshotProviderProxy.prototype = {
+    getNextItems: function(count, callback)
+    {
+        function returnResult()
+        {
+            var result = new Array(count);
+            for (var i = 0 ; i < count && this._provider.hasNext(); ++i, this._provider.next())
+                result[i] = this._extractData(this._provider.item);
+            result.length = i;
+            callback(result, this._provider.hasNext(), this._provider.length);
+        }
+        setTimeout(returnResult.bind(this), 0);
+    },
+
+    isEmpty: function(callback)
+    {
+        function returnResult()
+        {
+            callback(this._provider.isEmpty);
+        }
+        setTimeout(returnResult.bind(this), 0);
+    },
+
+    sortAndRewind: function(comparator, callback)
+    {
+        function returnResult()
+        {
+            var result = this._provider.sort(comparator);
+            if (result)
+                this._provider.first();
+            callback(result);
+        }
+        setTimeout(returnResult.bind(this), 0);
+    }
+};
+
+WebInspector.HeapSnapshotPathFinderProxy = function(pathFinder)
+{
+    this._pathFinder = pathFinder;
+}
+
+WebInspector.HeapSnapshotPathFinderProxy.prototype = {
+    findNext: function(callback)
+    {
+        function returnResult()
+        {
+            callback(this._pathFinder.findNext());
+        }
+        setTimeout(returnResult.bind(this), 0);
+    },
+
+    updateRoots: function(filter)
+    {
+        function asyncInvoke()
+        {
+            this._pathFinder.updateRoots(filter);
+        }
+        setTimeout(asyncInvoke.bind(this), 0);
+    }
+};
index e1980a0..c5ddd49 100644 (file)
@@ -86,7 +86,7 @@ WebInspector.PleaseWaitMessage.prototype = {
         var instance = WebInspector.PleaseWaitMessage.prototype.instance;
         var message = instance.element;
         if (message.parentNode === element) {
-            actionCallback();
+            setTimeout(actionCallback, 0);
             return;
         }
      
index 1ee67a0..d9a1178 100644 (file)
@@ -211,11 +211,6 @@ WebInspector.ProfilesPanel.prototype = {
             if (view && ("dispose" in view))
                 view.dispose();
             delete this._profiles[i]._profileView;
-            var profile = this._profiles[i];
-            if (profile.nodes) {
-                delete profile.nodes;
-                delete profile.strings;
-            }
         }
         delete this.visibleView;
 
@@ -450,58 +445,84 @@ WebInspector.ProfilesPanel.prototype = {
         if (!profile)
             return;
 
-        if (profile._loaded)
-            callback(profile);
-        else if (profile._is_loading)
-            profile._callbacks.push(callback);
-        else {
-            profile._is_loading = true;
-            profile._callbacks = [callback];
-            profile._json = "";
-            profile.sideBarElement.subtitle = WebInspector.UIString("Loading…");
-            ProfilerAgent.getProfile(profile.typeId, profile.uid);
+        if (!Preferences.detailedHeapProfiles) {
+            if (profile._loaded)
+                callback(profile);
+            else if (profile._is_loading)
+                profile._callbacks.push(callback);
+            else {
+                profile._is_loading = true;
+                profile._callbacks = [callback];
+                profile._json = "";
+                profile.sideBarElement.subtitle = WebInspector.UIString("Loading\u2026");
+                ProfilerAgent.getProfile(profile.typeId, profile.uid);
+            }
+        } else {
+            if (!profile.proxy)
+                profile.proxy = new WebInspector.HeapSnapshotProxy();
+            var proxy = profile.proxy;
+            if (proxy.startLoading(callback)) {
+                profile.sideBarElement.subtitle = WebInspector.UIString("Loading\u2026");
+                ProfilerAgent.getProfile(profile.typeId, profile.uid);
+            }
         }
     },
 
     _addHeapSnapshotChunk: function(uid, chunk)
     {
         var profile = this._profilesIdMap[this._makeKey(uid, WebInspector.HeapSnapshotProfileType.TypeId)];
-        if (!profile || profile._loaded || !profile._is_loading)
+        if (!profile)
             return;
-
-        profile._json += chunk;
+        if (!Preferences.detailedHeapProfiles) {
+            if (profile._loaded || !profile._is_loading)
+                return;
+            profile._json += chunk;
+        } else {
+            if (!profile.proxy)
+                return;
+            profile.proxy.pushJSONChunk(chunk);
+        }
     },
 
     _finishHeapSnapshot: function(uid)
     {
         var profile = this._profilesIdMap[this._makeKey(uid, WebInspector.HeapSnapshotProfileType.TypeId)];
-        if (!profile || profile._loaded || !profile._is_loading)
+        if (!profile)
             return;
-
-        profile.sideBarElement.subtitle = WebInspector.UIString("Parsing…");
-        window.setTimeout(doParse, 0);
-
-        function doParse()
-        {
-            var loadedSnapshot = JSON.parse(profile._json);
-            delete profile._json;
-            delete profile._is_loading;
-            var callbacks = profile._callbacks;
-            delete profile._callbacks;
-            profile._loaded = true;
-            profile.sideBarElement.subtitle = "";
-
-            if (!Preferences.detailedHeapProfiles && WebInspector.DetailedHeapshotView.prototype.isDetailedSnapshot(loadedSnapshot)) {
-                WebInspector.panels.profiles._enableDetailedHeapProfiles(false);
+        if (!Preferences.detailedHeapProfiles) {
+            if (profile._loaded || !profile._is_loading)
                 return;
-            }
+            profile.sideBarElement.subtitle = WebInspector.UIString("Parsing\u2026");
+            function doParse()
+            {
+                var loadedSnapshot = JSON.parse(profile._json);
+                var callbacks = profile._callbacks;
+                delete profile._callbacks;
+                delete profile._json;
+                delete profile._is_loading;
+                profile._loaded = true;
+                profile.sideBarElement.subtitle = "";
+
+                if (WebInspector.DetailedHeapshotView.prototype.isDetailedSnapshot(loadedSnapshot)) {
+                    WebInspector.panels.profiles._enableDetailedHeapProfiles(false);
+                    return;
+                }
 
-            if (!Preferences.detailedHeapProfiles)
                 WebInspector.HeapSnapshotView.prototype.processLoadedSnapshot(profile, loadedSnapshot);
-            else
-                WebInspector.DetailedHeapshotView.prototype.processLoadedSnapshot(profile, loadedSnapshot);
-            for (var i = 0; i < callbacks.length; ++i)
-                callbacks[i](profile);
+                for (var i = 0; i < callbacks.length; ++i)
+                    callbacks[i](profile);
+            }
+            setTimeout(doParse, 0);
+        } else {
+            if (!profile.proxy)
+                return;
+            var proxy = profile.proxy;
+            function parsed()
+            {
+                profile.sideBarElement.subtitle = Number.bytesToString(proxy.totalSize);
+            }
+            if (proxy.finishLoading(parsed))
+                profile.sideBarElement.subtitle = WebInspector.UIString("Parsing\u2026");
         }
     },
 
index 020ac4a..f3e8d0f 100644 (file)
@@ -50,6 +50,7 @@
     <file>GoToLineDialog.js</file>
     <file>HAREntry.js</file>
     <file>HeapSnapshot.js</file>
+    <file>HeapSnapshotProxy.js</file>
     <file>HeapSnapshotView.js</file>
     <file>HelpScreen.js</file>
     <file>ImageView.js</file>
index 27b84ed..e8cb10f 100644 (file)
@@ -140,6 +140,7 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     <script type="text/javascript" src="TopDownProfileDataGridTree.js"></script>
     <script type="text/javascript" src="ProfileView.js"></script>
     <script type="text/javascript" src="HeapSnapshot.js"></script>
+    <script type="text/javascript" src="HeapSnapshotProxy.js"></script>
     <script type="text/javascript" src="HeapSnapshotView.js"></script>
     <script type="text/javascript" src="DetailedHeapshotGridNodes.js"></script>
     <script type="text/javascript" src="DetailedHeapshotView.js"></script>