| OLD | NEW | 
|    1 // Copyright 2016 The Chromium Authors. All rights reserved. |    1 // Copyright 2016 The Chromium Authors. All rights reserved. | 
|    2 // Use of this source code is governed by a BSD-style license that can be |    2 // Use of this source code is governed by a BSD-style license that can be | 
|    3 // found in the LICENSE file. |    3 // found in the LICENSE file. | 
|    4  |    4  | 
|    5 TimelineModel.TimelineProfileTree = {}; |    5 TimelineModel.TimelineProfileTree = class { | 
 |    6   /** | 
 |    7    * @param {!Array<!SDK.TracingModel.Event>} events | 
 |    8    * @param {!Array<!TimelineModel.TimelineModelFilter>} filters | 
 |    9    * @param {number} startTime | 
 |   10    * @param {number} endTime | 
 |   11    * @param {function(!SDK.TracingModel.Event):string=} eventGroupIdCallback | 
 |   12    */ | 
 |   13   constructor(events, filters, startTime, endTime, eventGroupIdCallback) { | 
 |   14     this._events = events; | 
 |   15     this._filter = e => TimelineModel.TimelineModel.isVisible(filters, e); | 
 |   16     this._startTime = startTime; | 
 |   17     this._endTime = endTime; | 
 |   18     this._eventGroupIdCallback = eventGroupIdCallback; | 
 |   19   } | 
 |   20  | 
 |   21   /** | 
 |   22    * @return {!TimelineModel.TimelineProfileTree.Node} | 
 |   23    */ | 
 |   24   bottomUpTreeRoot() { | 
 |   25     return new TimelineModel.TimelineProfileTree.BottomUpTreeRootNode(this); | 
 |   26   } | 
 |   27 }; | 
|    6  |   28  | 
|    7 /** |   29 /** | 
|    8  * @unrestricted |   30  * @unrestricted | 
|    9  */ |   31  */ | 
|   10 TimelineModel.TimelineProfileTree.Node = class { |   32 TimelineModel.TimelineProfileTree.Node = class { | 
|   11   constructor() { |   33   /** | 
 |   34    * @param {string} id | 
 |   35    * @param {?SDK.TracingModel.Event} event | 
 |   36    */ | 
 |   37   constructor(id, event) { | 
|   12     /** @type {number} */ |   38     /** @type {number} */ | 
|   13     this.totalTime; |   39     this.totalTime = 0; | 
|   14     /** @type {number} */ |   40     /** @type {number} */ | 
|   15     this.selfTime; |   41     this.selfTime = 0; | 
|   16     /** @type {string} */ |   42     /** @type {string} */ | 
|   17     this.id; |   43     this.id = id; | 
|   18     /** @type {!SDK.TracingModel.Event} */ |   44     /** @type {?SDK.TracingModel.Event} */ | 
|   19     this.event; |   45     this.event = event; | 
|   20     /** @type {?Map<string|symbol,!TimelineModel.TimelineProfileTree.Node>} */ |  | 
|   21     this.children; |  | 
|   22     /** @type {?TimelineModel.TimelineProfileTree.Node} */ |   46     /** @type {?TimelineModel.TimelineProfileTree.Node} */ | 
|   23     this.parent; |   47     this.parent; | 
|   24  |   48  | 
|   25     /** @type {string} */ |   49     /** @type {string} */ | 
|   26     this._groupId = ''; |   50     this._groupId = ''; | 
|   27     this._isGroupNode = false; |   51     this._isGroupNode = false; | 
|   28   } |   52   } | 
|   29  |   53  | 
|   30   /** |   54   /** | 
|   31    * @return {boolean} |   55    * @return {boolean} | 
|   32    */ |   56    */ | 
|   33   isGroupNode() { |   57   isGroupNode() { | 
|   34     return this._isGroupNode; |   58     return this._isGroupNode; | 
|   35   } |   59   } | 
 |   60  | 
 |   61   /** | 
 |   62    * @return {boolean} | 
 |   63    */ | 
 |   64   hasChildren() { | 
 |   65     throw 'Not implemented'; | 
 |   66   } | 
 |   67  | 
 |   68   /** | 
 |   69    * @return {!Map<string, !TimelineModel.TimelineProfileTree.Node>} | 
 |   70    */ | 
 |   71   children() { | 
 |   72     throw 'Not implemented'; | 
 |   73   } | 
 |   74 }; | 
 |   75  | 
 |   76 TimelineModel.TimelineProfileTree.TopDownNode = class extends TimelineModel.Time
     lineProfileTree.Node { | 
 |   77   /** | 
 |   78    * @param {string} id | 
 |   79    * @param {?SDK.TracingModel.Event} event | 
 |   80    */ | 
 |   81   constructor(id, event) { | 
 |   82     super(id, event); | 
 |   83     /** @type {!Map<string, !TimelineModel.TimelineProfileTree.Node>} */ | 
 |   84     this._children = new Map(); | 
 |   85   } | 
 |   86  | 
 |   87   /** | 
 |   88    * @override | 
 |   89    * @return {boolean} | 
 |   90    */ | 
 |   91   hasChildren() { | 
 |   92     return !!this._children.size; | 
 |   93   } | 
 |   94  | 
 |   95   /** | 
 |   96    * @override | 
 |   97    * @return {!Map<string, !TimelineModel.TimelineProfileTree.Node>} | 
 |   98    */ | 
 |   99   children() { | 
 |  100     return this._children; | 
 |  101   } | 
|   36 }; |  102 }; | 
|   37  |  103  | 
|   38 /** |  104 /** | 
|   39  * @param {!Array<!SDK.TracingModel.Event>} events |  105  * @param {!Array<!SDK.TracingModel.Event>} events | 
|   40  * @param {!Array<!TimelineModel.TimelineModelFilter>} filters |  106  * @param {!Array<!TimelineModel.TimelineModelFilter>} filters | 
|   41  * @param {number} startTime |  107  * @param {number} startTime | 
|   42  * @param {number} endTime |  108  * @param {number} endTime | 
|   43  * @param {function(!SDK.TracingModel.Event):string=} eventGroupIdCallback |  109  * @param {function(!SDK.TracingModel.Event):string=} eventGroupIdCallback | 
|   44  * @return {!TimelineModel.TimelineProfileTree.Node} |  110  * @return {!TimelineModel.TimelineProfileTree.Node} | 
|   45  */ |  111  */ | 
|   46 TimelineModel.TimelineProfileTree.buildTopDown = function(events, filters, start
     Time, endTime, eventGroupIdCallback) { |  112 TimelineModel.TimelineProfileTree.buildTopDown = function(events, filters, start
     Time, endTime, eventGroupIdCallback) { | 
|   47   // Temporarily deposit a big enough value that exceeds the max recording time. |  113   // Temporarily deposit a big enough value that exceeds the max recording time. | 
|   48   var /** @const */ initialTime = 1e7; |  114   var /** @const */ initialTime = 1e7; | 
|   49   var root = new TimelineModel.TimelineProfileTree.Node(); |  115   var root = new TimelineModel.TimelineProfileTree.TopDownNode('', null); | 
|   50   root.totalTime = initialTime; |  116   root.totalTime = initialTime; | 
|   51   root.selfTime = initialTime; |  117   root.selfTime = initialTime; | 
|   52   root.children = /** @type {!Map<string, !TimelineModel.TimelineProfileTree.Nod
     e>} */ (new Map()); |  | 
|   53   var parent = root; |  118   var parent = root; | 
|   54  |  119  | 
|   55   /** |  120   /** | 
|   56    * @param {!SDK.TracingModel.Event} e |  121    * @param {!SDK.TracingModel.Event} e | 
|   57    */ |  122    */ | 
|   58   function onStartEvent(e) { |  123   function onStartEvent(e) { | 
|   59     if (!TimelineModel.TimelineModel.isVisible(filters, e)) |  124     if (!TimelineModel.TimelineModel.isVisible(filters, e)) | 
|   60       return; |  125       return; | 
|   61     var time = e.endTime ? Math.min(endTime, e.endTime) - Math.max(startTime, e.
     startTime) : 0; |  126     var time = e.endTime ? Math.min(endTime, e.endTime) - Math.max(startTime, e.
     startTime) : 0; | 
|   62     var groupId = eventGroupIdCallback ? eventGroupIdCallback(e) : Symbol('uniqu
     eGroupId'); |  127     var groupId = eventGroupIdCallback ? eventGroupIdCallback(e) : Symbol('uniqu
     eGroupId'); | 
|   63     var id = eventGroupIdCallback ? TimelineModel.TimelineProfileTree._eventId(e
     ) : Symbol('uniqueEventId'); |  128     var id = eventGroupIdCallback ? TimelineModel.TimelineProfileTree._eventId(e
     ) : Symbol('uniqueEventId'); | 
|   64     if (typeof groupId === 'string' && typeof id === 'string') |  129     if (typeof groupId === 'string' && typeof id === 'string') | 
|   65       id += '/' + groupId; |  130       id += '/' + groupId; | 
|   66     if (!parent.children) |  131     var node = parent.children().get(id); | 
|   67       parent.children = /** @type {!Map<string,!TimelineModel.TimelineProfileTre
     e.Node>} */ (new Map()); |  | 
|   68     var node = parent.children.get(id); |  | 
|   69     if (node) { |  132     if (node) { | 
|   70       node.selfTime += time; |  133       node.selfTime += time; | 
|   71       node.totalTime += time; |  134       node.totalTime += time; | 
|   72     } else { |  135     } else { | 
|   73       node = new TimelineModel.TimelineProfileTree.Node(); |  136       node = new TimelineModel.TimelineProfileTree.TopDownNode(id, e); | 
|   74       node.totalTime = time; |  137       node.totalTime = time; | 
|   75       node.selfTime = time; |  138       node.selfTime = time; | 
|   76       node.parent = parent; |  139       node.parent = parent; | 
|   77       node.id = id; |  | 
|   78       node.event = e; |  | 
|   79       node._groupId = groupId; |  140       node._groupId = groupId; | 
|   80       parent.children.set(id, node); |  141       parent.children().set(id, node); | 
|   81     } |  142     } | 
|   82     parent.selfTime -= time; |  143     parent.selfTime -= time; | 
|   83     if (parent.selfTime < 0) { |  144     if (parent.selfTime < 0) { | 
|   84       console.error('Error: Negative self of ' + parent.selfTime, e); |  145       console.error('Error: Negative self of ' + parent.selfTime, e); | 
|   85       parent.selfTime = 0; |  146       parent.selfTime = 0; | 
|   86     } |  147     } | 
|   87     if (e.endTime) |  148     if (e.endTime) | 
|   88       parent = node; |  149       parent = node; | 
|   89   } |  150   } | 
|   90  |  151  | 
|   91   /** |  152   /** | 
|   92    * @param {!SDK.TracingModel.Event} e |  153    * @param {!SDK.TracingModel.Event} e | 
|   93    */ |  154    */ | 
|   94   function onEndEvent(e) { |  155   function onEndEvent(e) { | 
|   95     if (!TimelineModel.TimelineModel.isVisible(filters, e)) |  156     if (!TimelineModel.TimelineModel.isVisible(filters, e)) | 
|   96       return; |  157       return; | 
|   97     parent = parent.parent; |  158     parent = parent.parent; | 
|   98   } |  159   } | 
|   99  |  160  | 
|  100   var instantEventCallback = |  161   var instantEventCallback = | 
|  101       eventGroupIdCallback ? undefined : onStartEvent;  // Ignore instant events
      when aggregating. |  162       eventGroupIdCallback ? undefined : onStartEvent;  // Ignore instant events
      when aggregating. | 
|  102   TimelineModel.TimelineModel.forEachEvent(events, onStartEvent, onEndEvent, ins
     tantEventCallback, startTime, endTime); |  163   TimelineModel.TimelineModel.forEachEvent(events, onStartEvent, onEndEvent, ins
     tantEventCallback, startTime, endTime); | 
|  103   root.totalTime -= root.selfTime; |  164   root.totalTime -= root.selfTime; | 
|  104   root.selfTime = 0; |  165   root.selfTime = 0; | 
|  105   return root; |  166   return root; | 
|  106 }; |  167 }; | 
|  107  |  168  | 
 |  169 TimelineModel.TimelineProfileTree.BottomUpTreeRootNode = class extends TimelineM
     odel.TimelineProfileTree.Node { | 
 |  170   /** | 
 |  171    * @param {!TimelineModel.TimelineProfileTree} tree | 
 |  172    */ | 
 |  173   constructor(tree) { | 
 |  174     super('', null); | 
 |  175     this._tree = tree; | 
 |  176     this.totalTime = this._tree._endTime - this._tree._startTime; | 
 |  177   } | 
 |  178  | 
 |  179   /** | 
 |  180    * @override | 
 |  181    * @return {boolean} | 
 |  182    */ | 
 |  183   hasChildren() { | 
 |  184     return true; | 
 |  185   } | 
 |  186  | 
 |  187   /** | 
 |  188    * @override | 
 |  189    * @return {!Map<string, !TimelineModel.TimelineProfileTree.Node>} | 
 |  190    */ | 
 |  191   children() { | 
 |  192     return this._grouppedTopNodes(); | 
 |  193   } | 
 |  194  | 
 |  195   /** | 
 |  196    * @return {!Map<string, !TimelineModel.TimelineProfileTree.Node>} | 
 |  197    */ | 
 |  198   _ungrouppedTopNodes() { | 
 |  199     var root = this; | 
 |  200     var startTime = this._tree._startTime; | 
 |  201     var endTime = this._tree._endTime; | 
 |  202     /** @type {!Map<string, !TimelineModel.TimelineProfileTree.Node>} */ | 
 |  203     var nodeById = new Map(); | 
 |  204     /** @type {!Array<number>} */ | 
 |  205     var selfTimeStack = [endTime - startTime]; | 
 |  206     /** @type {!Array<boolean>} */ | 
 |  207     var firstNodeStack = []; | 
 |  208     /** @type {!Map<string, number>} */ | 
 |  209     var totalTimeById = new Map(); | 
 |  210     TimelineModel.TimelineModel.forEachEvent( | 
 |  211         this._tree._events, onStartEvent, onEndEvent, undefined, startTime, endT
     ime, this._tree._filter); | 
 |  212  | 
 |  213     /** | 
 |  214      * @param {!SDK.TracingModel.Event} e | 
 |  215      */ | 
 |  216     function onStartEvent(e) { | 
 |  217       var duration = Math.min(e.endTime, endTime) - Math.max(e.startTime, startT
     ime); | 
 |  218       selfTimeStack[selfTimeStack.length - 1] -= duration; | 
 |  219       selfTimeStack.push(duration); | 
 |  220       var id = TimelineModel.TimelineProfileTree._eventId(e); | 
 |  221       var noNodeOnStack = !totalTimeById.has(id); | 
 |  222       if (noNodeOnStack) | 
 |  223         totalTimeById.set(id, duration); | 
 |  224       firstNodeStack.push(noNodeOnStack); | 
 |  225     } | 
 |  226  | 
 |  227     /** | 
 |  228      * @param {!SDK.TracingModel.Event} e | 
 |  229      */ | 
 |  230     function onEndEvent(e) { | 
 |  231       var id = TimelineModel.TimelineProfileTree._eventId(e); | 
 |  232       var node = nodeById.get(id); | 
 |  233       if (!node) { | 
 |  234         node = new TimelineModel.TimelineProfileTree.BottomUpTreeNode(root._tree
     , id, e, true, root); | 
 |  235         nodeById.set(id, node); | 
 |  236       } | 
 |  237       node.selfTime += selfTimeStack.pop(); | 
 |  238       if (firstNodeStack.pop()) { | 
 |  239         node.totalTime += totalTimeById.get(id); | 
 |  240         totalTimeById.delete(id); | 
 |  241       } | 
 |  242     } | 
 |  243  | 
 |  244     this.selfTime = selfTimeStack.pop(); | 
 |  245     for (var pair of nodeById) { | 
 |  246       if (pair[1].selfTime <= 0) | 
 |  247         nodeById.delete(/** @type {string} */ (pair[0])); | 
 |  248     } | 
 |  249     return nodeById; | 
 |  250   } | 
 |  251  | 
 |  252   /** | 
 |  253    * @return {!Map<string, !TimelineModel.TimelineProfileTree.Node>} | 
 |  254    */ | 
 |  255   _grouppedTopNodes() { | 
 |  256     var flatNodes = this._ungrouppedTopNodes(); | 
 |  257     var groupNodes = new Map(); | 
 |  258     for (var node of flatNodes.values()) { | 
 |  259       var groupId = this._tree._eventGroupIdCallback(/** @type {!SDK.TracingMode
     l.Event} */ (node.event)); | 
 |  260       if (typeof groupId !== 'string') | 
 |  261         return flatNodes; | 
 |  262       var groupNode = groupNodes.get(groupId); | 
 |  263       if (!groupNode) { | 
 |  264         groupNode = new TimelineModel.TimelineProfileTree.BottomUpTreeGroupNode( | 
 |  265             groupId, /** @type {!SDK.TracingModel.Event} */ (node.event)); | 
 |  266         groupNode.parent = this; | 
 |  267         groupNodes.set(groupId, groupNode); | 
 |  268       } | 
 |  269       groupNode.addChild(node); | 
 |  270       node.parent = groupNode; | 
 |  271     } | 
 |  272     return groupNodes; | 
 |  273   } | 
 |  274 }; | 
 |  275  | 
 |  276 TimelineModel.TimelineProfileTree.BottomUpTreeGroupNode = class extends Timeline
     Model.TimelineProfileTree.Node { | 
 |  277   /** | 
 |  278    * @param {string} id | 
 |  279    * @param {!SDK.TracingModel.Event} event | 
 |  280    */ | 
 |  281   constructor(id, event) { | 
 |  282     super(id, event); | 
 |  283     this._children = new Map(); | 
 |  284     this._isGroupNode = true; | 
 |  285   } | 
 |  286  | 
 |  287   /** | 
 |  288    * @param {!TimelineModel.TimelineProfileTree.BottomUpTreeNode} child | 
 |  289    */ | 
 |  290   addChild(child) { | 
 |  291     this._children.set(child.id, child); | 
 |  292     this.selfTime += child.selfTime; | 
 |  293     this.totalTime += child.selfTime; | 
 |  294   } | 
 |  295  | 
 |  296   /** | 
 |  297    * @override | 
 |  298    * @return {boolean} | 
 |  299    */ | 
 |  300   hasChildren() { | 
 |  301     return true; | 
 |  302   } | 
 |  303  | 
 |  304   /** | 
 |  305    * @override | 
 |  306    * @return {!Map<string, !TimelineModel.TimelineProfileTree.Node>} | 
 |  307    */ | 
 |  308   children() { | 
 |  309     return this._children; | 
 |  310   } | 
 |  311 }; | 
 |  312  | 
 |  313 TimelineModel.TimelineProfileTree.BottomUpTreeNode = class extends TimelineModel
     .TimelineProfileTree.Node { | 
 |  314   /** | 
 |  315    * @param {!TimelineModel.TimelineProfileTree} tree | 
 |  316    * @param {string} id | 
 |  317    * @param {!SDK.TracingModel.Event} event | 
 |  318    * @param {boolean} hasChildren | 
 |  319    * @param {!TimelineModel.TimelineProfileTree.Node} parent | 
 |  320    */ | 
 |  321   constructor(tree, id, event, hasChildren, parent) { | 
 |  322     super(id, event); | 
 |  323     this.parent = parent; | 
 |  324     this._tree = tree; | 
 |  325     this._depth = (parent._depth || 0) + 1; | 
 |  326     this._cachedChildren = null; | 
 |  327     this._hasChildren = hasChildren; | 
 |  328   } | 
 |  329  | 
 |  330   /** | 
 |  331    * @override | 
 |  332    * @return {boolean} | 
 |  333    */ | 
 |  334   hasChildren() { | 
 |  335     return this._hasChildren; | 
 |  336   } | 
 |  337  | 
 |  338   /** | 
 |  339    * @override | 
 |  340    * @return {!Map<string, !TimelineModel.TimelineProfileTree.Node>} | 
 |  341    */ | 
 |  342   children() { | 
 |  343     if (this._cachedChildren) | 
 |  344       return this._cachedChildren; | 
 |  345     /** @type {!Array<number>} */ | 
 |  346     var selfTimeStack = [0]; | 
 |  347     /** @type {!Array<string>} */ | 
 |  348     var eventIdStack = []; | 
 |  349     /** @type {!Array<!SDK.TracingModel.Event>} */ | 
 |  350     var eventStack = []; | 
 |  351     /** @type {!Map<string, !TimelineModel.TimelineProfileTree.Node>} */ | 
 |  352     var nodeById = new Map(); | 
 |  353     var startTime = this._tree._startTime; | 
 |  354     var endTime = this._tree._endTime; | 
 |  355     var lastTimeMarker = startTime; | 
 |  356     var self = this; | 
 |  357     TimelineModel.TimelineModel.forEachEvent( | 
 |  358         this._tree._events, onStartEvent, onEndEvent, undefined, startTime, endT
     ime, this._tree._filter); | 
 |  359  | 
 |  360     /** | 
 |  361      * @param {!SDK.TracingModel.Event} e | 
 |  362      */ | 
 |  363     function onStartEvent(e) { | 
 |  364       var duration = Math.min(e.endTime, endTime) - Math.max(e.startTime, startT
     ime); | 
 |  365       if (duration < 0) | 
 |  366         console.assert(false, 'Negative duration of an event'); | 
 |  367       selfTimeStack[selfTimeStack.length - 1] -= duration; | 
 |  368       selfTimeStack.push(duration); | 
 |  369       var id = TimelineModel.TimelineProfileTree._eventId(e); | 
 |  370       eventIdStack.push(id); | 
 |  371       eventStack.push(e); | 
 |  372     } | 
 |  373  | 
 |  374     /** | 
 |  375      * @param {!SDK.TracingModel.Event} e | 
 |  376      */ | 
 |  377     function onEndEvent(e) { | 
 |  378       var selfTime = selfTimeStack.pop(); | 
 |  379       var id = eventIdStack.pop(); | 
 |  380       eventStack.pop(); | 
 |  381       for (var node = self; node._depth > 1; node = node.parent) { | 
 |  382         if (node.id !== eventIdStack[eventIdStack.length + 1 - node._depth]) | 
 |  383           return; | 
 |  384       } | 
 |  385       if (node.id !== id || eventIdStack.length < self._depth) | 
 |  386         return; | 
 |  387       var childId = eventIdStack[eventIdStack.length - self._depth]; | 
 |  388       var node = nodeById.get(childId); | 
 |  389       if (!node) { | 
 |  390         var event = eventStack[eventStack.length - self._depth]; | 
 |  391         var hasChildren = eventStack.length > self._depth; | 
 |  392         node = new TimelineModel.TimelineProfileTree.BottomUpTreeNode(self._tree
     , childId, event, hasChildren, self); | 
 |  393         nodeById.set(childId, node); | 
 |  394       } | 
 |  395       var totalTime = Math.min(e.endTime, endTime) - Math.max(e.startTime, lastT
     imeMarker); | 
 |  396       node.selfTime += selfTime; | 
 |  397       node.totalTime += totalTime; | 
 |  398       lastTimeMarker = Math.min(e.endTime, endTime); | 
 |  399     } | 
 |  400  | 
 |  401     this._cachedChildren = nodeById; | 
 |  402     return nodeById; | 
 |  403   } | 
 |  404 }; | 
 |  405  | 
|  108 /** |  406 /** | 
|  109  * @param {!TimelineModel.TimelineProfileTree.Node} topDownTree |  | 
|  110  * @return {!TimelineModel.TimelineProfileTree.Node} |  | 
|  111  */ |  | 
|  112 TimelineModel.TimelineProfileTree.buildBottomUp = function(topDownTree) { |  | 
|  113   var buRoot = new TimelineModel.TimelineProfileTree.Node(); |  | 
|  114   var aggregator = new TimelineModel.TimelineAggregator(); |  | 
|  115   buRoot.selfTime = 0; |  | 
|  116   buRoot.totalTime = 0; |  | 
|  117   /** @type {!Map<string, !TimelineModel.TimelineProfileTree.Node>} */ |  | 
|  118   buRoot.children = new Map(); |  | 
|  119   var nodesOnStack = /** @type {!Set<string>} */ (new Set()); |  | 
|  120   if (topDownTree.children) |  | 
|  121     topDownTree.children.forEach(processNode); |  | 
|  122   buRoot.totalTime = topDownTree.totalTime; |  | 
|  123  |  | 
|  124   /** |  | 
|  125    * @param {!TimelineModel.TimelineProfileTree.Node} tdNode |  | 
|  126    */ |  | 
|  127   function processNode(tdNode) { |  | 
|  128     var buParent = |  | 
|  129         typeof tdNode._groupId === 'string' ? aggregator.groupNodeForId(tdNode._
     groupId, tdNode.event) : buRoot; |  | 
|  130     if (buParent !== buRoot && !buParent.parent) { |  | 
|  131       buRoot.children.set(buParent.id, buParent); |  | 
|  132       buParent.parent = buRoot; |  | 
|  133     } |  | 
|  134     appendNode(tdNode, buParent); |  | 
|  135     var hadNode = nodesOnStack.has(tdNode.id); |  | 
|  136     if (!hadNode) |  | 
|  137       nodesOnStack.add(tdNode.id); |  | 
|  138     if (tdNode.children) |  | 
|  139       tdNode.children.forEach(processNode); |  | 
|  140     if (!hadNode) |  | 
|  141       nodesOnStack.delete(tdNode.id); |  | 
|  142   } |  | 
|  143  |  | 
|  144   /** |  | 
|  145    * @param {!TimelineModel.TimelineProfileTree.Node} tdNode |  | 
|  146    * @param {!TimelineModel.TimelineProfileTree.Node} buParent |  | 
|  147    */ |  | 
|  148   function appendNode(tdNode, buParent) { |  | 
|  149     var selfTime = tdNode.selfTime; |  | 
|  150     var totalTime = tdNode.totalTime; |  | 
|  151     buParent.selfTime += selfTime; |  | 
|  152     buParent.totalTime += selfTime; |  | 
|  153     while (tdNode.parent) { |  | 
|  154       if (!buParent.children) |  | 
|  155         buParent.children = /** @type {!Map<string,!TimelineModel.TimelineProfil
     eTree.Node>} */ (new Map()); |  | 
|  156       var id = tdNode.id; |  | 
|  157       var buNode = buParent.children.get(id); |  | 
|  158       if (!buNode) { |  | 
|  159         buNode = new TimelineModel.TimelineProfileTree.Node(); |  | 
|  160         buNode.selfTime = selfTime; |  | 
|  161         buNode.totalTime = totalTime; |  | 
|  162         buNode.event = tdNode.event; |  | 
|  163         buNode.id = id; |  | 
|  164         buNode.parent = buParent; |  | 
|  165         buParent.children.set(id, buNode); |  | 
|  166       } else { |  | 
|  167         buNode.selfTime += selfTime; |  | 
|  168         if (!nodesOnStack.has(id)) |  | 
|  169           buNode.totalTime += totalTime; |  | 
|  170       } |  | 
|  171       tdNode = tdNode.parent; |  | 
|  172       buParent = buNode; |  | 
|  173     } |  | 
|  174   } |  | 
|  175  |  | 
|  176   // Purge zero self time nodes. |  | 
|  177   var rootChildren = buRoot.children; |  | 
|  178   for (var item of rootChildren.entries()) { |  | 
|  179     if (item[1].selfTime === 0) |  | 
|  180       rootChildren.delete(/** @type {string} */ (item[0])); |  | 
|  181   } |  | 
|  182  |  | 
|  183   return buRoot; |  | 
|  184 }; |  | 
|  185  |  | 
|  186 /** |  | 
|  187  * @param {!SDK.TracingModel.Event} event |  407  * @param {!SDK.TracingModel.Event} event | 
|  188  * @return {?string} |  408  * @return {?string} | 
|  189  */ |  409  */ | 
|  190 TimelineModel.TimelineProfileTree.eventURL = function(event) { |  410 TimelineModel.TimelineProfileTree.eventURL = function(event) { | 
|  191   var data = event.args['data'] || event.args['beginData']; |  411   var data = event.args['data'] || event.args['beginData']; | 
|  192   if (data && data['url']) |  412   if (data && data['url']) | 
|  193     return data['url']; |  413     return data['url']; | 
|  194   var frame = TimelineModel.TimelineProfileTree.eventStackFrame(event); |  414   var frame = TimelineModel.TimelineProfileTree.eventStackFrame(event); | 
|  195   while (frame) { |  415   while (frame) { | 
|  196     var url = frame['url']; |  416     var url = frame['url']; | 
| (...skipping 28 matching lines...) Expand all  Loading... | 
|  225       TimelineModel.TimelineJSProfileProcessor.nativeGroup(functionName) || func
     tionName : |  445       TimelineModel.TimelineJSProfileProcessor.nativeGroup(functionName) || func
     tionName : | 
|  226       functionName; |  446       functionName; | 
|  227   return `f:${name}@${location}`; |  447   return `f:${name}@${location}`; | 
|  228 }; |  448 }; | 
|  229  |  449  | 
|  230 /** |  450 /** | 
|  231  * @unrestricted |  451  * @unrestricted | 
|  232  */ |  452  */ | 
|  233 TimelineModel.TimelineAggregator = class { |  453 TimelineModel.TimelineAggregator = class { | 
|  234   constructor() { |  454   constructor() { | 
|  235     /** @type {!Map<string, !TimelineModel.TimelineProfileTree.Node>} */ |  455     /** @type {!Map<string, !TimelineModel.TimelineProfileTree.TopDownNode>} */ | 
|  236     this._groupNodes = new Map(); |  456     this._groupNodes = new Map(); | 
|  237   } |  457   } | 
|  238  |  458  | 
|  239   /** |  459   /** | 
|  240    * @param {!TimelineModel.TimelineProfileTree.Node} root |  460    * @param {!TimelineModel.TimelineProfileTree.Node} root | 
|  241    * @return {!TimelineModel.TimelineProfileTree.Node} |  461    * @return {!TimelineModel.TimelineProfileTree.Node} | 
|  242    */ |  462    */ | 
|  243   performGrouping(root) { |  463   performGrouping(root) { | 
|  244     for (var node of root.children.values()) { |  464     for (var node of root.children().values()) { | 
|  245       var groupNode = this.groupNodeForId(node._groupId, node.event); |  465       var groupNode = this.groupNodeForId(node._groupId, /** @type {!SDK.Tracing
     Model.Event} */ (node.event)); | 
|  246       groupNode.parent = root; |  466       groupNode.parent = root; | 
|  247       groupNode.selfTime += node.selfTime; |  467       groupNode.selfTime += node.selfTime; | 
|  248       groupNode.totalTime += node.totalTime; |  468       groupNode.totalTime += node.totalTime; | 
|  249       groupNode.children.set(node.id, node); |  469       groupNode.children().set(node.id, node); | 
|  250       node.parent = root; |  470       node.parent = root; | 
|  251     } |  471     } | 
|  252     root.children = this._groupNodes; |  472     root._children = this._groupNodes; | 
|  253     return root; |  473     return root; | 
|  254   } |  474   } | 
|  255  |  475  | 
|  256   /** |  476   /** | 
|  257    * @param {string} groupId |  477    * @param {string} groupId | 
|  258    * @param {!SDK.TracingModel.Event} event |  478    * @param {!SDK.TracingModel.Event} event | 
|  259    * @return {!TimelineModel.TimelineProfileTree.Node} |  479    * @return {!TimelineModel.TimelineProfileTree.Node} | 
|  260    */ |  480    */ | 
|  261   groupNodeForId(groupId, event) { |  481   groupNodeForId(groupId, event) { | 
|  262     var node = this._groupNodes.get(groupId); |  482     var node = this._groupNodes.get(groupId); | 
|  263     return node || this._buildGroupNode(groupId, event); |  483     return node || this._buildGroupNode(groupId, event); | 
|  264   } |  484   } | 
|  265  |  485  | 
|  266   /** |  486   /** | 
|  267    * @param {string} id |  487    * @param {string} id | 
|  268    * @param {!SDK.TracingModel.Event} event |  488    * @param {!SDK.TracingModel.Event} event | 
|  269    * @return {!TimelineModel.TimelineProfileTree.Node} |  489    * @return {!TimelineModel.TimelineProfileTree.Node} | 
|  270    */ |  490    */ | 
|  271   _buildGroupNode(id, event) { |  491   _buildGroupNode(id, event) { | 
|  272     var groupNode = new TimelineModel.TimelineProfileTree.Node(); |  492     var groupNode = new TimelineModel.TimelineProfileTree.TopDownNode(id, event)
     ; | 
|  273     groupNode.id = id; |  | 
|  274     groupNode.selfTime = 0; |  493     groupNode.selfTime = 0; | 
|  275     groupNode.totalTime = 0; |  494     groupNode.totalTime = 0; | 
|  276     groupNode.children = new Map(); |  | 
|  277     groupNode.event = event; |  | 
|  278     groupNode._isGroupNode = true; |  495     groupNode._isGroupNode = true; | 
|  279     this._groupNodes.set(id, groupNode); |  496     this._groupNodes.set(id, groupNode); | 
|  280     return groupNode; |  497     return groupNode; | 
|  281   } |  498   } | 
|  282 }; |  499 }; | 
|  283  |  | 
|  284 TimelineModel.TimelineAggregator._groupNodeFlag = Symbol('groupNode'); |  | 
| OLD | NEW |