Web Inspector: timeline hangs on a page with deep chain of nested events.
authoryurys@chromium.org <yurys@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 21 Feb 2012 16:14:19 +0000 (16:14 +0000)
committeryurys@chromium.org <yurys@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 21 Feb 2012 16:14:19 +0000 (16:14 +0000)
https://bugs.webkit.org/show_bug.cgi?id=79106

Use stack of states instead of recursive calls when traversing records tree to
avoid stack overflow.

Reviewed by Pavel Feldman.

* inspector/front-end/TimelineOverviewPane.js:
(WebInspector.TimelineOverviewPane.prototype._forAllRecords):
* inspector/front-end/TimelinePanel.js:
(WebInspector.TimelinePanel.prototype._filterRecords):

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

Source/WebCore/ChangeLog
Source/WebCore/inspector/front-end/TimelineOverviewPane.js
Source/WebCore/inspector/front-end/TimelinePanel.js

index 668ffde..ec3a378 100644 (file)
@@ -1,3 +1,18 @@
+2012-02-21  Yury Semikhatsky  <yurys@chromium.org>
+
+        Web Inspector: timeline hangs on a page with deep chain of nested events.
+        https://bugs.webkit.org/show_bug.cgi?id=79106
+
+        Use stack of states instead of recursive calls when traversing records tree to
+        avoid stack overflow.
+
+        Reviewed by Pavel Feldman.
+
+        * inspector/front-end/TimelineOverviewPane.js:
+        (WebInspector.TimelineOverviewPane.prototype._forAllRecords):
+        * inspector/front-end/TimelinePanel.js:
+        (WebInspector.TimelinePanel.prototype._filterRecords):
+
 2012-02-21  Pavel Feldman  <pfeldman@google.com>
 
         Web Inspector: [crash] upon style modification after navigation
index aa8c275..b37d8c0 100644 (file)
@@ -126,9 +126,18 @@ WebInspector.TimelineOverviewPane.prototype = {
     {
         if (!recordsArray)
             return;
-        for (var i = 0; i < recordsArray.length; ++i) {
-            callback(recordsArray[i]);
-            this._forAllRecords(recordsArray[i].children, callback);
+        var stack = [{array: recordsArray, index: 0}];
+        while (stack.length) {
+            var entry = stack[stack.length - 1];
+            var records = entry.array;
+            if (entry.index < records.length) {
+                 var record = records[entry.index];
+                 callback(record);
+                 if (record.children)
+                     stack.push({array: record.children, index: 0});
+                 ++entry.index;
+            } else
+                stack.pop();
         }
     },
 
index 3dab0fa..5d0b7f7 100644 (file)
@@ -672,34 +672,43 @@ WebInspector.TimelinePanel.prototype = {
         this._calculator.calculateWindow();
     },
 
-    /**
-     * @param {boolean=} parentIsCollapsed
-     */
-    _addToRecordsWindow: function(record, recordsWindow, parentIsCollapsed)
-    {
-        if (!this._showShortEvents && !record.isLong())
-            return;
-        var percentages = this._calculator.computeBarGraphPercentages(record);
-        if (percentages.start < 100 && percentages.endWithChildren >= 0 && !record.category.hidden) {
-            ++this._rootRecord._visibleRecordsCount;
-            ++record.parent._invisibleChildrenCount;
-            if (!parentIsCollapsed)
-                recordsWindow.push(record);
-        }
-
-        var index = recordsWindow.length;
-        record._invisibleChildrenCount = 0;
-        for (var i = 0; i < record.children.length; ++i)
-            this._addToRecordsWindow(record.children[i], recordsWindow, parentIsCollapsed || record.collapsed);
-        record._visibleChildrenCount = recordsWindow.length - index;
-    },
-
     _filterRecords: function()
     {
         var recordsInWindow = [];
         this._rootRecord._visibleRecordsCount = 0;
-        for (var i = 0; i < this._rootRecord.children.length; ++i)
-            this._addToRecordsWindow(this._rootRecord.children[i], recordsInWindow);
+
+        var stack = [{children: this._rootRecord.children, index: 0, parentIsCollapsed: false}];
+        while (stack.length) {
+            var entry = stack[stack.length - 1];
+            var records = entry.children;
+            if (records && entry.index < records.length) {
+                 var record = records[entry.index];
+                 ++entry.index;
+
+                 if (!this._showShortEvents && !record.isLong())
+                     continue;
+                 var percentages = this._calculator.computeBarGraphPercentages(record);
+                 if (percentages.start < 100 && percentages.endWithChildren >= 0 && !record.category.hidden) {
+                     ++this._rootRecord._visibleRecordsCount;
+                     ++record.parent._invisibleChildrenCount;
+                     if (!entry.parentIsCollapsed)
+                         recordsInWindow.push(record);
+                 }
+
+                 record._invisibleChildrenCount = 0;
+
+                 stack.push({children: record.children,
+                             index: 0,
+                             parentIsCollapsed: (entry.parentIsCollapsed || record.collapsed),
+                             parentRecord: record,
+                             windowLengthBeforeChildrenTraversal: recordsInWindow.length});
+            } else {
+                stack.pop();
+                if (entry.parentRecord)
+                    entry.parentRecord._visibleChildrenCount = recordsInWindow.length - entry.windowLengthBeforeChildrenTraversal;
+            }
+        }
+
         return recordsInWindow;
     },