Merge 201072 "DevTools: [timeline tree view] fix total time calc..."

> DevTools: [timeline tree view] fix total time calculation for recursive case.
> 
> BUG=523537
> NOTRY=true
> 
> Review URL: https://codereview.chromium.org/1312563002

TBR=alph@chromium.org

Review URL: https://codereview.chromium.org/1311783008

git-svn-id: svn://svn.chromium.org/blink/branches/chromium/2490@201158 bbb929c8-8fbe-4397-9dbb-9b2b20218538
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-js-callstacks-expected.txt b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-js-callstacks-expected.txt
index e41a3778..92af899 100644
--- a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-js-callstacks-expected.txt
+++ b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-js-callstacks-expected.txt
@@ -15,15 +15,21 @@
 JSFrame: 230.000 / 0.833 a
 Layout: 230.010 / 0.100 
 FunctionCall: 250.000 / 10.000 
-JSFrame: 251.000 / 8.482 x
-JSFrame: 251.000 / 8.482 y
-FunctionCall: 251.000 / 8.000 
+JSFrame: 251.000 / 1.513 x
+JSFrame: 251.000 / 1.513 y
+FunctionCall: 251.000 / 1.000 
 JSFrame: 251.000 / 0.200 z
 JSFrame: 251.000 / 0.200 w
 JSFrame: 251.200 / 0.200 w
+JSFrame: 253.000 / 0.015 recursive_a
+JSFrame: 253.000 / 0.014 recursive_b
+JSFrame: 253.000 / 0.012 recursive_a
+JSFrame: 253.000 / 0.008 recursive_b
+JSFrame: 253.100 / 0.200 recursive_a
+JSFrame: 253.100 / 0.100 recursive_b
 
 Top-Down Chart: 0.000  40.000
-  Function Call: 22.305  40.000
+  Function Call: 29.059  40.000
     a: 0.000  8.380
       b: 7.125  8.380
         c: 0.351  0.351
@@ -33,17 +39,26 @@
       l: 0.000  0.833
         a: 0.733  0.833
           Layout: 0.100  0.100
-    x: 0.000  8.482
-      y: 0.482  8.482
-        Function Call: 7.600  8.000
+    x: 0.000  1.513
+      y: 0.513  1.513
+        Function Call: 0.600  1.000
           z: 0.000  0.200
             w: 0.200  0.200
           w: 0.200  0.200
+    recursive_a: 0.101  0.215
+      recursive_b: 0.102  0.114
+        recursive_a: 0.004  0.012
+          recursive_b: 0.008  0.008
 Bottom-Up Chart: 40.000  40.000
-  Function Call: 29.905  48.000
-    y: 7.600  8.000
-      x: 7.600  8.000
-        Function Call: 7.600  8.000
+  Function Call: 29.659  40.000
+    y: 0.600  1.000
+      x: 0.600  1.000
+        Function Call: 0.600  1.000
+  a: 0.733  9.213
+    Function Call: 0.000  8.380
+    l: 0.733  0.833
+      f: 0.733  0.833
+        Function Call: 0.733  0.833
   b: 7.125  8.380
     a: 7.125  8.380
       Function Call: 7.125  8.380
@@ -56,18 +71,14 @@
       b: 0.905  0.905
         a: 0.905  0.905
           Function Call: 0.905  0.905
-  a: 0.733  0.833
-    l: 0.733  0.833
-      f: 0.733  0.833
-        Function Call: 0.733  0.833
   Layout: 0.100  0.100
     a: 0.100  0.100
       l: 0.100  0.100
         f: 0.100  0.100
           Function Call: 0.100  0.100
-  y: 0.482  8.482
-    x: 0.482  8.482
-      Function Call: 0.482  8.482
+  y: 0.513  1.513
+    x: 0.513  1.513
+      Function Call: 0.513  1.513
   w: 0.400  0.400
     z: 0.200  0.200
       Function Call: 0.200  0.200
@@ -78,4 +89,15 @@
       y: 0.200  0.200
         x: 0.200  0.200
           Function Call: 0.200  0.200
+  recursive_a: 0.105  0.215
+    Function Call: 0.101  0.215
+    recursive_b: 0.004  0.012
+      recursive_a: 0.004  0.012
+        Function Call: 0.004  0.012
+  recursive_b: 0.110  0.114
+    recursive_a: 0.110  0.114
+      Function Call: 0.102  0.114
+      recursive_b: 0.008  0.008
+        recursive_a: 0.008  0.008
+          Function Call: 0.008  0.008
 
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-js-callstacks.html b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-js-callstacks.html
index 7bbc09e7..501191e 100644
--- a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-js-callstacks.html
+++ b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-js-callstacks.html
@@ -323,7 +323,7 @@
         "pid": 17851,
         "tid": 23,
         "ts": 251000,
-        "dur": 8000
+        "dur": 1000
     },
     {
         "args": {
@@ -412,6 +412,131 @@
         "ts": 251400,
     },
     {
+        "args": {
+            "data": {
+                "stackTrace": [
+                    { "functionName": "recursive_b", "scriptId": 1 },
+                    { "functionName": "recursive_a", "scriptId": 1 },
+                    { "functionName": "recursive_b", "scriptId": 1 },
+                    { "functionName": "recursive_a", "scriptId": 1 }
+                ]
+            }
+        },
+        "cat": "disabled-by-default-devtools.timeline",
+        "name": "JSSample",
+        "ph": "I",
+        "pid": 17851,
+        "tid": 23,
+        "ts": 253000,
+    },
+    {
+        "args": {
+            "data": {
+                "stackTrace": [
+                    { "functionName": "recursive_a", "scriptId": 1 },
+                    { "functionName": "recursive_b", "scriptId": 1 },
+                    { "functionName": "recursive_a", "scriptId": 1 }
+                ]
+            }
+        },
+        "cat": "disabled-by-default-devtools.timeline",
+        "name": "JSSample",
+        "ph": "I",
+        "pid": 17851,
+        "tid": 23,
+        "ts": 253008,
+    },
+    {
+        "args": {
+            "data": {
+                "stackTrace": [
+                    { "functionName": "recursive_b", "scriptId": 1 },
+                    { "functionName": "recursive_a", "scriptId": 1 }
+                ]
+            }
+        },
+        "cat": "disabled-by-default-devtools.timeline",
+        "name": "JSSample",
+        "ph": "I",
+        "pid": 17851,
+        "tid": 23,
+        "ts": 253012,
+    },
+    {
+        "args": {
+            "data": {
+                "stackTrace": [
+                    { "functionName": "recursive_a", "scriptId": 1 }
+                ]
+            }
+        },
+        "cat": "disabled-by-default-devtools.timeline",
+        "name": "JSSample",
+        "ph": "I",
+        "pid": 17851,
+        "tid": 23,
+        "ts": 253014,
+    },
+    {
+        "args": {
+            "data": {
+                "stackTrace": [
+                ]
+            }
+        },
+        "cat": "disabled-by-default-devtools.timeline",
+        "name": "JSSample",
+        "ph": "I",
+        "pid": 17851,
+        "tid": 23,
+        "ts": 253015,
+    },
+    {
+        "args": {
+            "data": {
+                "stackTrace": [
+                    { "functionName": "recursive_b", "scriptId": 1 },
+                    { "functionName": "recursive_a", "scriptId": 1 }
+                ]
+            }
+        },
+        "cat": "disabled-by-default-devtools.timeline",
+        "name": "JSSample",
+        "ph": "I",
+        "pid": 17851,
+        "tid": 23,
+        "ts": 253100,
+    },
+    {
+        "args": {
+            "data": {
+                "stackTrace": [
+                    { "functionName": "recursive_a", "scriptId": 1 }
+                ]
+            }
+        },
+        "cat": "disabled-by-default-devtools.timeline",
+        "name": "JSSample",
+        "ph": "I",
+        "pid": 17851,
+        "tid": 23,
+        "ts": 253200,
+    },
+    {
+        "args": {
+            "data": {
+                "stackTrace": [
+                ]
+            }
+        },
+        "cat": "disabled-by-default-devtools.timeline",
+        "name": "JSSample",
+        "ph": "I",
+        "pid": 17851,
+        "tid": 23,
+        "ts": 253300,
+    },
+    {
         "args": {},
         "cat": "disabled-by-default-devtools.timeline",
         "name": "Program",
diff --git a/third_party/WebKit/Source/devtools/front_end/timeline/TimelineModel.js b/third_party/WebKit/Source/devtools/front_end/timeline/TimelineModel.js
index d198d9cb..e907777 100644
--- a/third_party/WebKit/Source/devtools/front_end/timeline/TimelineModel.js
+++ b/third_party/WebKit/Source/devtools/front_end/timeline/TimelineModel.js
@@ -1552,19 +1552,23 @@
     buRoot.name = WebInspector.UIString("Bottom-Up Chart");
     /** @type {!Map<string,!WebInspector.TimelineModel.ProfileTreeNode>} */
     buRoot.children = new Map();
-    processNode(topDownTree);
+    var nodesOnStack = /** @type {!Set<string>} */ (new Set());
+    topDownTree.children.forEach(processNode);
 
     /**
      * @param {!WebInspector.TimelineModel.ProfileTreeNode} tdNode
      */
     function processNode(tdNode)
     {
-        if (tdNode.selfTime > 0) {
-            var buParent = groupingCallback && groupingCallback(tdNode) || buRoot;
-            appendNode(tdNode, buParent);
-        }
+        var buParent = groupingCallback && groupingCallback(tdNode) || buRoot;
+        appendNode(tdNode, buParent);
+        var hadNode = nodesOnStack.has(tdNode.id);
+        if (!hadNode)
+            nodesOnStack.add(tdNode.id);
         if (tdNode.children)
             tdNode.children.forEach(processNode);
+        if (!hadNode)
+            nodesOnStack.delete(tdNode.id);
     }
 
     /**
@@ -1592,13 +1596,21 @@
                 buParent.children.set(id, buNode);
             } else {
                 buNode.selfTime += selfTime;
-                buNode.totalTime += totalTime;
+                if (!nodesOnStack.has(id))
+                    buNode.totalTime += totalTime;
             }
             tdNode = tdNode.parent;
             buParent = buNode;
         }
     }
 
+    // Purge zero self time nodes.
+    var rootChildren = buRoot.children;
+    for (var item of rootChildren.entries()) {
+        if (item[1].selfTime === 0)
+            rootChildren.delete(item[0]);
+    }
+
     return buRoot;
 }