11cb0ef41Sopenharmony_ci// Copyright 2009 the V8 project authors. All rights reserved.
21cb0ef41Sopenharmony_ci// Redistribution and use in source and binary forms, with or without
31cb0ef41Sopenharmony_ci// modification, are permitted provided that the following conditions are
41cb0ef41Sopenharmony_ci// met:
51cb0ef41Sopenharmony_ci//
61cb0ef41Sopenharmony_ci//     * Redistributions of source code must retain the above copyright
71cb0ef41Sopenharmony_ci//       notice, this list of conditions and the following disclaimer.
81cb0ef41Sopenharmony_ci//     * Redistributions in binary form must reproduce the above
91cb0ef41Sopenharmony_ci//       copyright notice, this list of conditions and the following
101cb0ef41Sopenharmony_ci//       disclaimer in the documentation and/or other materials provided
111cb0ef41Sopenharmony_ci//       with the distribution.
121cb0ef41Sopenharmony_ci//     * Neither the name of Google Inc. nor the names of its
131cb0ef41Sopenharmony_ci//       contributors may be used to endorse or promote products derived
141cb0ef41Sopenharmony_ci//       from this software without specific prior written permission.
151cb0ef41Sopenharmony_ci//
161cb0ef41Sopenharmony_ci// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
171cb0ef41Sopenharmony_ci// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
181cb0ef41Sopenharmony_ci// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
191cb0ef41Sopenharmony_ci// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
201cb0ef41Sopenharmony_ci// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
211cb0ef41Sopenharmony_ci// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
221cb0ef41Sopenharmony_ci// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
231cb0ef41Sopenharmony_ci// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
241cb0ef41Sopenharmony_ci// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
251cb0ef41Sopenharmony_ci// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
261cb0ef41Sopenharmony_ci// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
271cb0ef41Sopenharmony_ci
281cb0ef41Sopenharmony_ci
291cb0ef41Sopenharmony_ci/**
301cb0ef41Sopenharmony_ci * Creates a Profile View builder object.
311cb0ef41Sopenharmony_ci *
321cb0ef41Sopenharmony_ci * @param {number} samplingRate Number of ms between profiler ticks.
331cb0ef41Sopenharmony_ci * @constructor
341cb0ef41Sopenharmony_ci */
351cb0ef41Sopenharmony_cifunction ViewBuilder(samplingRate) {
361cb0ef41Sopenharmony_ci  this.samplingRate = samplingRate;
371cb0ef41Sopenharmony_ci};
381cb0ef41Sopenharmony_ci
391cb0ef41Sopenharmony_ci
401cb0ef41Sopenharmony_ci/**
411cb0ef41Sopenharmony_ci * Builds a profile view for the specified call tree.
421cb0ef41Sopenharmony_ci *
431cb0ef41Sopenharmony_ci * @param {CallTree} callTree A call tree.
441cb0ef41Sopenharmony_ci * @param {boolean} opt_bottomUpViewWeights Whether remapping
451cb0ef41Sopenharmony_ci *     of self weights for a bottom up view is needed.
461cb0ef41Sopenharmony_ci */
471cb0ef41Sopenharmony_ciViewBuilder.prototype.buildView = function(
481cb0ef41Sopenharmony_ci    callTree, opt_bottomUpViewWeights) {
491cb0ef41Sopenharmony_ci  var head;
501cb0ef41Sopenharmony_ci  var samplingRate = this.samplingRate;
511cb0ef41Sopenharmony_ci  var createViewNode = this.createViewNode;
521cb0ef41Sopenharmony_ci  callTree.traverse(function(node, viewParent) {
531cb0ef41Sopenharmony_ci    var totalWeight = node.totalWeight * samplingRate;
541cb0ef41Sopenharmony_ci    var selfWeight = node.selfWeight * samplingRate;
551cb0ef41Sopenharmony_ci    if (opt_bottomUpViewWeights === true) {
561cb0ef41Sopenharmony_ci      if (viewParent === head) {
571cb0ef41Sopenharmony_ci        selfWeight = totalWeight;
581cb0ef41Sopenharmony_ci      } else {
591cb0ef41Sopenharmony_ci        selfWeight = 0;
601cb0ef41Sopenharmony_ci      }
611cb0ef41Sopenharmony_ci    }
621cb0ef41Sopenharmony_ci    var viewNode = createViewNode(node.label, totalWeight, selfWeight, head);
631cb0ef41Sopenharmony_ci    if (viewParent) {
641cb0ef41Sopenharmony_ci      viewParent.addChild(viewNode);
651cb0ef41Sopenharmony_ci    } else {
661cb0ef41Sopenharmony_ci      head = viewNode;
671cb0ef41Sopenharmony_ci    }
681cb0ef41Sopenharmony_ci    return viewNode;
691cb0ef41Sopenharmony_ci  });
701cb0ef41Sopenharmony_ci  var view = this.createView(head);
711cb0ef41Sopenharmony_ci  return view;
721cb0ef41Sopenharmony_ci};
731cb0ef41Sopenharmony_ci
741cb0ef41Sopenharmony_ci
751cb0ef41Sopenharmony_ci/**
761cb0ef41Sopenharmony_ci * Factory method for a profile view.
771cb0ef41Sopenharmony_ci *
781cb0ef41Sopenharmony_ci * @param {ProfileView.Node} head View head node.
791cb0ef41Sopenharmony_ci * @return {ProfileView} Profile view.
801cb0ef41Sopenharmony_ci */
811cb0ef41Sopenharmony_ciViewBuilder.prototype.createView = function(head) {
821cb0ef41Sopenharmony_ci  return new ProfileView(head);
831cb0ef41Sopenharmony_ci};
841cb0ef41Sopenharmony_ci
851cb0ef41Sopenharmony_ci
861cb0ef41Sopenharmony_ci/**
871cb0ef41Sopenharmony_ci * Factory method for a profile view node.
881cb0ef41Sopenharmony_ci *
891cb0ef41Sopenharmony_ci * @param {string} internalFuncName A fully qualified function name.
901cb0ef41Sopenharmony_ci * @param {number} totalTime Amount of time that application spent in the
911cb0ef41Sopenharmony_ci *     corresponding function and its descendants (not that depending on
921cb0ef41Sopenharmony_ci *     profile they can be either callees or callers.)
931cb0ef41Sopenharmony_ci * @param {number} selfTime Amount of time that application spent in the
941cb0ef41Sopenharmony_ci *     corresponding function only.
951cb0ef41Sopenharmony_ci * @param {ProfileView.Node} head Profile view head.
961cb0ef41Sopenharmony_ci * @return {ProfileView.Node} Profile view node.
971cb0ef41Sopenharmony_ci */
981cb0ef41Sopenharmony_ciViewBuilder.prototype.createViewNode = function(
991cb0ef41Sopenharmony_ci    funcName, totalTime, selfTime, head) {
1001cb0ef41Sopenharmony_ci  return new ProfileView.Node(
1011cb0ef41Sopenharmony_ci      funcName, totalTime, selfTime, head);
1021cb0ef41Sopenharmony_ci};
1031cb0ef41Sopenharmony_ci
1041cb0ef41Sopenharmony_ci
1051cb0ef41Sopenharmony_ci/**
1061cb0ef41Sopenharmony_ci * Creates a Profile View object. It allows to perform sorting
1071cb0ef41Sopenharmony_ci * and filtering actions on the profile.
1081cb0ef41Sopenharmony_ci *
1091cb0ef41Sopenharmony_ci * @param {ProfileView.Node} head Head (root) node.
1101cb0ef41Sopenharmony_ci * @constructor
1111cb0ef41Sopenharmony_ci */
1121cb0ef41Sopenharmony_cifunction ProfileView(head) {
1131cb0ef41Sopenharmony_ci  this.head = head;
1141cb0ef41Sopenharmony_ci};
1151cb0ef41Sopenharmony_ci
1161cb0ef41Sopenharmony_ci
1171cb0ef41Sopenharmony_ci/**
1181cb0ef41Sopenharmony_ci * Sorts the profile view using the specified sort function.
1191cb0ef41Sopenharmony_ci *
1201cb0ef41Sopenharmony_ci * @param {function(ProfileView.Node,
1211cb0ef41Sopenharmony_ci *     ProfileView.Node):number} sortFunc A sorting
1221cb0ef41Sopenharmony_ci *     functions. Must comply with Array.sort sorting function requirements.
1231cb0ef41Sopenharmony_ci */
1241cb0ef41Sopenharmony_ciProfileView.prototype.sort = function(sortFunc) {
1251cb0ef41Sopenharmony_ci  this.traverse(function (node) {
1261cb0ef41Sopenharmony_ci    node.sortChildren(sortFunc);
1271cb0ef41Sopenharmony_ci  });
1281cb0ef41Sopenharmony_ci};
1291cb0ef41Sopenharmony_ci
1301cb0ef41Sopenharmony_ci
1311cb0ef41Sopenharmony_ci/**
1321cb0ef41Sopenharmony_ci * Traverses profile view nodes in preorder.
1331cb0ef41Sopenharmony_ci *
1341cb0ef41Sopenharmony_ci * @param {function(ProfileView.Node)} f Visitor function.
1351cb0ef41Sopenharmony_ci */
1361cb0ef41Sopenharmony_ciProfileView.prototype.traverse = function(f) {
1371cb0ef41Sopenharmony_ci  var nodesToTraverse = new ConsArray();
1381cb0ef41Sopenharmony_ci  nodesToTraverse.concat([this.head]);
1391cb0ef41Sopenharmony_ci  while (!nodesToTraverse.atEnd()) {
1401cb0ef41Sopenharmony_ci    var node = nodesToTraverse.next();
1411cb0ef41Sopenharmony_ci    f(node);
1421cb0ef41Sopenharmony_ci    nodesToTraverse.concat(node.children);
1431cb0ef41Sopenharmony_ci  }
1441cb0ef41Sopenharmony_ci};
1451cb0ef41Sopenharmony_ci
1461cb0ef41Sopenharmony_ci
1471cb0ef41Sopenharmony_ci/**
1481cb0ef41Sopenharmony_ci * Constructs a Profile View node object. Each node object corresponds to
1491cb0ef41Sopenharmony_ci * a function call.
1501cb0ef41Sopenharmony_ci *
1511cb0ef41Sopenharmony_ci * @param {string} internalFuncName A fully qualified function name.
1521cb0ef41Sopenharmony_ci * @param {number} totalTime Amount of time that application spent in the
1531cb0ef41Sopenharmony_ci *     corresponding function and its descendants (not that depending on
1541cb0ef41Sopenharmony_ci *     profile they can be either callees or callers.)
1551cb0ef41Sopenharmony_ci * @param {number} selfTime Amount of time that application spent in the
1561cb0ef41Sopenharmony_ci *     corresponding function only.
1571cb0ef41Sopenharmony_ci * @param {ProfileView.Node} head Profile view head.
1581cb0ef41Sopenharmony_ci * @constructor
1591cb0ef41Sopenharmony_ci */
1601cb0ef41Sopenharmony_ciProfileView.Node = function(
1611cb0ef41Sopenharmony_ci    internalFuncName, totalTime, selfTime, head) {
1621cb0ef41Sopenharmony_ci  this.internalFuncName = internalFuncName;
1631cb0ef41Sopenharmony_ci  this.totalTime = totalTime;
1641cb0ef41Sopenharmony_ci  this.selfTime = selfTime;
1651cb0ef41Sopenharmony_ci  this.head = head;
1661cb0ef41Sopenharmony_ci  this.parent = null;
1671cb0ef41Sopenharmony_ci  this.children = [];
1681cb0ef41Sopenharmony_ci};
1691cb0ef41Sopenharmony_ci
1701cb0ef41Sopenharmony_ci
1711cb0ef41Sopenharmony_ci/**
1721cb0ef41Sopenharmony_ci * Returns a share of the function's total time in its parent's total time.
1731cb0ef41Sopenharmony_ci */
1741cb0ef41Sopenharmony_ciProfileView.Node.prototype.__defineGetter__(
1751cb0ef41Sopenharmony_ci    'parentTotalPercent',
1761cb0ef41Sopenharmony_ci    function() { return this.totalTime /
1771cb0ef41Sopenharmony_ci      (this.parent ? this.parent.totalTime : this.totalTime) * 100.0; });
1781cb0ef41Sopenharmony_ci
1791cb0ef41Sopenharmony_ci
1801cb0ef41Sopenharmony_ci/**
1811cb0ef41Sopenharmony_ci * Adds a child to the node.
1821cb0ef41Sopenharmony_ci *
1831cb0ef41Sopenharmony_ci * @param {ProfileView.Node} node Child node.
1841cb0ef41Sopenharmony_ci */
1851cb0ef41Sopenharmony_ciProfileView.Node.prototype.addChild = function(node) {
1861cb0ef41Sopenharmony_ci  node.parent = this;
1871cb0ef41Sopenharmony_ci  this.children.push(node);
1881cb0ef41Sopenharmony_ci};
1891cb0ef41Sopenharmony_ci
1901cb0ef41Sopenharmony_ci
1911cb0ef41Sopenharmony_ci/**
1921cb0ef41Sopenharmony_ci * Sorts all the node's children recursively.
1931cb0ef41Sopenharmony_ci *
1941cb0ef41Sopenharmony_ci * @param {function(ProfileView.Node,
1951cb0ef41Sopenharmony_ci *     ProfileView.Node):number} sortFunc A sorting
1961cb0ef41Sopenharmony_ci *     functions. Must comply with Array.sort sorting function requirements.
1971cb0ef41Sopenharmony_ci */
1981cb0ef41Sopenharmony_ciProfileView.Node.prototype.sortChildren = function(
1991cb0ef41Sopenharmony_ci    sortFunc) {
2001cb0ef41Sopenharmony_ci  this.children.sort(sortFunc);
2011cb0ef41Sopenharmony_ci};
202