15ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org// Copyright 2009 the V8 project authors. All rights reserved. 25ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org// Redistribution and use in source and binary forms, with or without 35ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org// modification, are permitted provided that the following conditions are 45ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org// met: 55ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org// 65ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org// * Redistributions of source code must retain the above copyright 75ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org// notice, this list of conditions and the following disclaimer. 85ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org// * Redistributions in binary form must reproduce the above 95ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org// copyright notice, this list of conditions and the following 105ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org// disclaimer in the documentation and/or other materials provided 115ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org// with the distribution. 125ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org// * Neither the name of Google Inc. nor the names of its 135ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org// contributors may be used to endorse or promote products derived 145ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org// from this software without specific prior written permission. 155ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org// 165ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 175ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 185ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 195ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 205ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 215ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 225ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 235ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 245ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 255ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 265ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 275ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org 285ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org 295ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org/** 305ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org * Creates a Profile View builder object. 315ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org * 325ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org * @param {number} samplingRate Number of ms between profiler ticks. 335ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org * @constructor 345ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org */ 35496c03a64f12710e837204e261ef155601247895sgjesse@chromium.orgfunction ViewBuilder(samplingRate) { 365ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org this.samplingRate = samplingRate; 375ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org}; 385ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org 395ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org 405ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org/** 415ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org * Builds a profile view for the specified call tree. 425ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org * 43496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org * @param {CallTree} callTree A call tree. 44b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org * @param {boolean} opt_bottomUpViewWeights Whether remapping 45b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org * of self weights for a bottom up view is needed. 465ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org */ 47496c03a64f12710e837204e261ef155601247895sgjesse@chromium.orgViewBuilder.prototype.buildView = function( 48b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org callTree, opt_bottomUpViewWeights) { 495ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org var head; 505ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org var samplingRate = this.samplingRate; 51e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org var createViewNode = this.createViewNode; 525ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org callTree.traverse(function(node, viewParent) { 53b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org var totalWeight = node.totalWeight * samplingRate; 54b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org var selfWeight = node.selfWeight * samplingRate; 55b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org if (opt_bottomUpViewWeights === true) { 56b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org if (viewParent === head) { 57b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org selfWeight = totalWeight; 58b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org } else { 59b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org selfWeight = 0; 60b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org } 61b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org } 62e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org var viewNode = createViewNode(node.label, totalWeight, selfWeight, head); 635ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org if (viewParent) { 645ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org viewParent.addChild(viewNode); 655ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org } else { 665ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org head = viewNode; 675ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org } 685ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org return viewNode; 695ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org }); 70e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org var view = this.createView(head); 715ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org return view; 725ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org}; 735ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org 745ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org 755ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org/** 76e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org * Factory method for a profile view. 77e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org * 78496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org * @param {ProfileView.Node} head View head node. 79496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org * @return {ProfileView} Profile view. 80e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org */ 81496c03a64f12710e837204e261ef155601247895sgjesse@chromium.orgViewBuilder.prototype.createView = function(head) { 82496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org return new ProfileView(head); 83e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org}; 84e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org 85e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org 86e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org/** 87e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org * Factory method for a profile view node. 88e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org * 89e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org * @param {string} internalFuncName A fully qualified function name. 90e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org * @param {number} totalTime Amount of time that application spent in the 91e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org * corresponding function and its descendants (not that depending on 92e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org * profile they can be either callees or callers.) 93e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org * @param {number} selfTime Amount of time that application spent in the 94e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org * corresponding function only. 95496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org * @param {ProfileView.Node} head Profile view head. 96496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org * @return {ProfileView.Node} Profile view node. 97e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org */ 98496c03a64f12710e837204e261ef155601247895sgjesse@chromium.orgViewBuilder.prototype.createViewNode = function( 99e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org funcName, totalTime, selfTime, head) { 100496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org return new ProfileView.Node( 101e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org funcName, totalTime, selfTime, head); 102e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org}; 103e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org 104e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org 105e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org/** 1065ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org * Creates a Profile View object. It allows to perform sorting 107e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org * and filtering actions on the profile. 1085ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org * 109496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org * @param {ProfileView.Node} head Head (root) node. 1105ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org * @constructor 1115ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org */ 112496c03a64f12710e837204e261ef155601247895sgjesse@chromium.orgfunction ProfileView(head) { 1135ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org this.head = head; 1145ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org}; 1155ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org 1165ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org 1175ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org/** 1185ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org * Sorts the profile view using the specified sort function. 1195ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org * 120496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org * @param {function(ProfileView.Node, 121496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org * ProfileView.Node):number} sortFunc A sorting 1225ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org * functions. Must comply with Array.sort sorting function requirements. 1235ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org */ 124496c03a64f12710e837204e261ef155601247895sgjesse@chromium.orgProfileView.prototype.sort = function(sortFunc) { 1255ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org this.traverse(function (node) { 1265ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org node.sortChildren(sortFunc); 1275ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org }); 1285ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org}; 1295ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org 1305ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org 1315ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org/** 1325ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org * Traverses profile view nodes in preorder. 1335ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org * 134496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org * @param {function(ProfileView.Node)} f Visitor function. 1355ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org */ 136496c03a64f12710e837204e261ef155601247895sgjesse@chromium.orgProfileView.prototype.traverse = function(f) { 1375ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org var nodesToTraverse = new ConsArray(); 1385ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org nodesToTraverse.concat([this.head]); 1395ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org while (!nodesToTraverse.atEnd()) { 1405ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org var node = nodesToTraverse.next(); 1415ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org f(node); 1425ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org nodesToTraverse.concat(node.children); 1435ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org } 1445ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org}; 1455ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org 1465ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org 1475ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org/** 1485ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org * Constructs a Profile View node object. Each node object corresponds to 1495ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org * a function call. 1505ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org * 1515ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org * @param {string} internalFuncName A fully qualified function name. 1525ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org * @param {number} totalTime Amount of time that application spent in the 1535ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org * corresponding function and its descendants (not that depending on 1545ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org * profile they can be either callees or callers.) 1555ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org * @param {number} selfTime Amount of time that application spent in the 1565ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org * corresponding function only. 157496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org * @param {ProfileView.Node} head Profile view head. 1585ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org * @constructor 1595ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org */ 160496c03a64f12710e837204e261ef155601247895sgjesse@chromium.orgProfileView.Node = function( 1615ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org internalFuncName, totalTime, selfTime, head) { 1625ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org this.internalFuncName = internalFuncName; 1635ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org this.totalTime = totalTime; 1645ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org this.selfTime = selfTime; 1655ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org this.head = head; 1665ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org this.parent = null; 1675ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org this.children = []; 1685ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org}; 1695ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org 1705ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org 1715ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org/** 1725ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org * Returns a share of the function's total time in its parent's total time. 1735ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org */ 174496c03a64f12710e837204e261ef155601247895sgjesse@chromium.orgProfileView.Node.prototype.__defineGetter__( 1755ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org 'parentTotalPercent', 1765ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org function() { return this.totalTime / 1775ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org (this.parent ? this.parent.totalTime : this.totalTime) * 100.0; }); 1785ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org 1795ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org 1805ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org/** 1815ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org * Adds a child to the node. 1825ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org * 183496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org * @param {ProfileView.Node} node Child node. 1845ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org */ 185496c03a64f12710e837204e261ef155601247895sgjesse@chromium.orgProfileView.Node.prototype.addChild = function(node) { 1865ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org node.parent = this; 1875ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org this.children.push(node); 1885ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org}; 1895ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org 1905ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org 1915ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org/** 1925ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org * Sorts all the node's children recursively. 1935ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org * 194496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org * @param {function(ProfileView.Node, 195496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org * ProfileView.Node):number} sortFunc A sorting 1965ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org * functions. Must comply with Array.sort sorting function requirements. 1975ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org */ 198496c03a64f12710e837204e261ef155601247895sgjesse@chromium.orgProfileView.Node.prototype.sortChildren = function( 1995ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org sortFunc) { 2005ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org this.children.sort(sortFunc); 2015ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org}; 202