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_ciimport { ConsArray } from "./consarray.mjs";
291cb0ef41Sopenharmony_ci
301cb0ef41Sopenharmony_ci/**
311cb0ef41Sopenharmony_ci * Creates a Profile View builder object.
321cb0ef41Sopenharmony_ci *
331cb0ef41Sopenharmony_ci * @param {number} samplingRate Number of ms between profiler ticks.
341cb0ef41Sopenharmony_ci * @constructor
351cb0ef41Sopenharmony_ci */
361cb0ef41Sopenharmony_ciexport function ViewBuilder(samplingRate) {
371cb0ef41Sopenharmony_ci  this.samplingRate = samplingRate;
381cb0ef41Sopenharmony_ci};
391cb0ef41Sopenharmony_ci
401cb0ef41Sopenharmony_ci
411cb0ef41Sopenharmony_ci/**
421cb0ef41Sopenharmony_ci * Builds a profile view for the specified call tree.
431cb0ef41Sopenharmony_ci *
441cb0ef41Sopenharmony_ci * @param {CallTree} callTree A call tree.
451cb0ef41Sopenharmony_ci * @param {boolean} opt_bottomUpViewWeights Whether remapping
461cb0ef41Sopenharmony_ci *     of self weights for a bottom up view is needed.
471cb0ef41Sopenharmony_ci */
481cb0ef41Sopenharmony_ciViewBuilder.prototype.buildView = function(
491cb0ef41Sopenharmony_ci    callTree, opt_bottomUpViewWeights) {
501cb0ef41Sopenharmony_ci  let head;
511cb0ef41Sopenharmony_ci  const samplingRate = this.samplingRate;
521cb0ef41Sopenharmony_ci  const createViewNode = this.createViewNode;
531cb0ef41Sopenharmony_ci  callTree.traverse(function(node, viewParent) {
541cb0ef41Sopenharmony_ci    const totalWeight = node.totalWeight * samplingRate;
551cb0ef41Sopenharmony_ci    let selfWeight = node.selfWeight * samplingRate;
561cb0ef41Sopenharmony_ci    if (opt_bottomUpViewWeights === true) {
571cb0ef41Sopenharmony_ci      if (viewParent === head) {
581cb0ef41Sopenharmony_ci        selfWeight = totalWeight;
591cb0ef41Sopenharmony_ci      } else {
601cb0ef41Sopenharmony_ci        selfWeight = 0;
611cb0ef41Sopenharmony_ci      }
621cb0ef41Sopenharmony_ci    }
631cb0ef41Sopenharmony_ci    const viewNode = createViewNode(node.label, totalWeight, selfWeight, head);
641cb0ef41Sopenharmony_ci    if (viewParent) {
651cb0ef41Sopenharmony_ci      viewParent.addChild(viewNode);
661cb0ef41Sopenharmony_ci    } else {
671cb0ef41Sopenharmony_ci      head = viewNode;
681cb0ef41Sopenharmony_ci    }
691cb0ef41Sopenharmony_ci    return viewNode;
701cb0ef41Sopenharmony_ci  });
711cb0ef41Sopenharmony_ci  const view = this.createView(head);
721cb0ef41Sopenharmony_ci  return view;
731cb0ef41Sopenharmony_ci};
741cb0ef41Sopenharmony_ci
751cb0ef41Sopenharmony_ci
761cb0ef41Sopenharmony_ci/**
771cb0ef41Sopenharmony_ci * Factory method for a profile view.
781cb0ef41Sopenharmony_ci *
791cb0ef41Sopenharmony_ci * @param {ProfileView.Node} head View head node.
801cb0ef41Sopenharmony_ci * @return {ProfileView} Profile view.
811cb0ef41Sopenharmony_ci */
821cb0ef41Sopenharmony_ciViewBuilder.prototype.createView = head => new ProfileView(head);
831cb0ef41Sopenharmony_ci
841cb0ef41Sopenharmony_ci
851cb0ef41Sopenharmony_ci/**
861cb0ef41Sopenharmony_ci * Factory method for a profile view node.
871cb0ef41Sopenharmony_ci *
881cb0ef41Sopenharmony_ci * @param {string} internalFuncName A fully qualified function name.
891cb0ef41Sopenharmony_ci * @param {number} totalTime Amount of time that application spent in the
901cb0ef41Sopenharmony_ci *     corresponding function and its descendants (not that depending on
911cb0ef41Sopenharmony_ci *     profile they can be either callees or callers.)
921cb0ef41Sopenharmony_ci * @param {number} selfTime Amount of time that application spent in the
931cb0ef41Sopenharmony_ci *     corresponding function only.
941cb0ef41Sopenharmony_ci * @param {ProfileView.Node} head Profile view head.
951cb0ef41Sopenharmony_ci * @return {ProfileView.Node} Profile view node.
961cb0ef41Sopenharmony_ci */
971cb0ef41Sopenharmony_ciViewBuilder.prototype.createViewNode = (
981cb0ef41Sopenharmony_ci    funcName, totalTime, selfTime, head) =>
991cb0ef41Sopenharmony_ci  new ProfileView.Node(
1001cb0ef41Sopenharmony_ci      funcName, totalTime, selfTime, head)
1011cb0ef41Sopenharmony_ci;
1021cb0ef41Sopenharmony_ci
1031cb0ef41Sopenharmony_ci
1041cb0ef41Sopenharmony_ci/**
1051cb0ef41Sopenharmony_ci * Creates a Profile View object. It allows to perform sorting
1061cb0ef41Sopenharmony_ci * and filtering actions on the profile.
1071cb0ef41Sopenharmony_ci *
1081cb0ef41Sopenharmony_ci * @param {ProfileView.Node} head Head (root) node.
1091cb0ef41Sopenharmony_ci * @constructor
1101cb0ef41Sopenharmony_ci */
1111cb0ef41Sopenharmony_ciexport function ProfileView(head) {
1121cb0ef41Sopenharmony_ci  this.head = head;
1131cb0ef41Sopenharmony_ci};
1141cb0ef41Sopenharmony_ci
1151cb0ef41Sopenharmony_ci
1161cb0ef41Sopenharmony_ci/**
1171cb0ef41Sopenharmony_ci * Sorts the profile view using the specified sort function.
1181cb0ef41Sopenharmony_ci *
1191cb0ef41Sopenharmony_ci * @param {function(ProfileView.Node,
1201cb0ef41Sopenharmony_ci *     ProfileView.Node):number} sortFunc A sorting
1211cb0ef41Sopenharmony_ci *     functions. Must comply with Array.sort sorting function requirements.
1221cb0ef41Sopenharmony_ci */
1231cb0ef41Sopenharmony_ciProfileView.prototype.sort = function(sortFunc) {
1241cb0ef41Sopenharmony_ci  this.traverse(function (node) {
1251cb0ef41Sopenharmony_ci    node.sortChildren(sortFunc);
1261cb0ef41Sopenharmony_ci  });
1271cb0ef41Sopenharmony_ci};
1281cb0ef41Sopenharmony_ci
1291cb0ef41Sopenharmony_ci
1301cb0ef41Sopenharmony_ci/**
1311cb0ef41Sopenharmony_ci * Traverses profile view nodes in preorder.
1321cb0ef41Sopenharmony_ci *
1331cb0ef41Sopenharmony_ci * @param {function(ProfileView.Node)} f Visitor function.
1341cb0ef41Sopenharmony_ci */
1351cb0ef41Sopenharmony_ciProfileView.prototype.traverse = function(f) {
1361cb0ef41Sopenharmony_ci  const nodesToTraverse = new ConsArray();
1371cb0ef41Sopenharmony_ci  nodesToTraverse.concat([this.head]);
1381cb0ef41Sopenharmony_ci  while (!nodesToTraverse.atEnd()) {
1391cb0ef41Sopenharmony_ci    const node = nodesToTraverse.next();
1401cb0ef41Sopenharmony_ci    f(node);
1411cb0ef41Sopenharmony_ci    nodesToTraverse.concat(node.children);
1421cb0ef41Sopenharmony_ci  }
1431cb0ef41Sopenharmony_ci};
1441cb0ef41Sopenharmony_ci
1451cb0ef41Sopenharmony_ci
1461cb0ef41Sopenharmony_ci/**
1471cb0ef41Sopenharmony_ci * Constructs a Profile View node object. Each node object corresponds to
1481cb0ef41Sopenharmony_ci * a function call.
1491cb0ef41Sopenharmony_ci *
1501cb0ef41Sopenharmony_ci * @param {string} internalFuncName A fully qualified function name.
1511cb0ef41Sopenharmony_ci * @param {number} totalTime Amount of time that application spent in the
1521cb0ef41Sopenharmony_ci *     corresponding function and its descendants (not that depending on
1531cb0ef41Sopenharmony_ci *     profile they can be either callees or callers.)
1541cb0ef41Sopenharmony_ci * @param {number} selfTime Amount of time that application spent in the
1551cb0ef41Sopenharmony_ci *     corresponding function only.
1561cb0ef41Sopenharmony_ci * @param {ProfileView.Node} head Profile view head.
1571cb0ef41Sopenharmony_ci * @constructor
1581cb0ef41Sopenharmony_ci */
1591cb0ef41Sopenharmony_ciProfileView.Node = function(
1601cb0ef41Sopenharmony_ci    internalFuncName, totalTime, selfTime, head) {
1611cb0ef41Sopenharmony_ci  this.internalFuncName = internalFuncName;
1621cb0ef41Sopenharmony_ci  this.totalTime = totalTime;
1631cb0ef41Sopenharmony_ci  this.selfTime = selfTime;
1641cb0ef41Sopenharmony_ci  this.head = head;
1651cb0ef41Sopenharmony_ci  this.parent = null;
1661cb0ef41Sopenharmony_ci  this.children = [];
1671cb0ef41Sopenharmony_ci};
1681cb0ef41Sopenharmony_ci
1691cb0ef41Sopenharmony_ci
1701cb0ef41Sopenharmony_ci/**
1711cb0ef41Sopenharmony_ci * Returns a share of the function's total time in its parent's total time.
1721cb0ef41Sopenharmony_ci */
1731cb0ef41Sopenharmony_ciProfileView.Node.prototype.__defineGetter__(
1741cb0ef41Sopenharmony_ci    'parentTotalPercent',
1751cb0ef41Sopenharmony_ci    function() { return this.totalTime /
1761cb0ef41Sopenharmony_ci      (this.parent ? this.parent.totalTime : this.totalTime) * 100.0; });
1771cb0ef41Sopenharmony_ci
1781cb0ef41Sopenharmony_ci
1791cb0ef41Sopenharmony_ci/**
1801cb0ef41Sopenharmony_ci * Adds a child to the node.
1811cb0ef41Sopenharmony_ci *
1821cb0ef41Sopenharmony_ci * @param {ProfileView.Node} node Child node.
1831cb0ef41Sopenharmony_ci */
1841cb0ef41Sopenharmony_ciProfileView.Node.prototype.addChild = function(node) {
1851cb0ef41Sopenharmony_ci  node.parent = this;
1861cb0ef41Sopenharmony_ci  this.children.push(node);
1871cb0ef41Sopenharmony_ci};
1881cb0ef41Sopenharmony_ci
1891cb0ef41Sopenharmony_ci
1901cb0ef41Sopenharmony_ci/**
1911cb0ef41Sopenharmony_ci * Sorts all the node's children recursively.
1921cb0ef41Sopenharmony_ci *
1931cb0ef41Sopenharmony_ci * @param {function(ProfileView.Node,
1941cb0ef41Sopenharmony_ci *     ProfileView.Node):number} sortFunc A sorting
1951cb0ef41Sopenharmony_ci *     functions. Must comply with Array.sort sorting function requirements.
1961cb0ef41Sopenharmony_ci */
1971cb0ef41Sopenharmony_ciProfileView.Node.prototype.sortChildren = function(
1981cb0ef41Sopenharmony_ci    sortFunc) {
1991cb0ef41Sopenharmony_ci  this.children.sort(sortFunc);
2001cb0ef41Sopenharmony_ci};
201