| Index: tools/profile.js
|
| diff --git a/tools/profile.js b/tools/profile.js
|
| index e70d244de6a570ad848c8a0d274723dc67ea72d6..d2b53223c042edcdb17063c625372264fd924fa4 100644
|
| --- a/tools/profile.js
|
| +++ b/tools/profile.js
|
| @@ -56,15 +56,32 @@ devtools.profiler.Profile.prototype.skipThisFunction = function(name) {
|
|
|
|
|
| /**
|
| + * Enum for profiler operations that involve looking up existing
|
| + * code entries.
|
| + *
|
| + * @enum {number}
|
| + */
|
| +devtools.profiler.Profile.Operation = {
|
| + MOVE: 0,
|
| + DELETE: 1,
|
| + TICK: 2
|
| +};
|
| +
|
| +
|
| +/**
|
| * Called whenever the specified operation has failed finding a function
|
| * containing the specified address. Should be overriden by subclasses.
|
| - * Operation is one of the following: 'move', 'delete', 'tick'.
|
| + * See the devtools.profiler.Profile.Operation enum for the list of
|
| + * possible operations.
|
| *
|
| - * @param {string} operation Operation name.
|
| + * @param {number} operation Operation.
|
| * @param {number} addr Address of the unknown code.
|
| + * @param {number} opt_stackPos If an unknown address is encountered
|
| + * during stack strace processing, specifies a position of the frame
|
| + * containing the address.
|
| */
|
| devtools.profiler.Profile.prototype.handleUnknownCode = function(
|
| - operation, addr) {
|
| + operation, addr, opt_stackPos) {
|
| };
|
|
|
|
|
| @@ -77,8 +94,10 @@ devtools.profiler.Profile.prototype.handleUnknownCode = function(
|
| */
|
| devtools.profiler.Profile.prototype.addStaticCode = function(
|
| name, startAddr, endAddr) {
|
| - this.codeMap_.addStaticCode(startAddr,
|
| - new devtools.profiler.CodeMap.CodeEntry(endAddr - startAddr, name));
|
| + var entry = new devtools.profiler.CodeMap.CodeEntry(
|
| + endAddr - startAddr, name);
|
| + this.codeMap_.addStaticCode(startAddr, entry);
|
| + return entry;
|
| };
|
|
|
|
|
| @@ -92,8 +111,9 @@ devtools.profiler.Profile.prototype.addStaticCode = function(
|
| */
|
| devtools.profiler.Profile.prototype.addCode = function(
|
| type, name, start, size) {
|
| - this.codeMap_.addCode(start,
|
| - new devtools.profiler.Profile.DynamicCodeEntry(size, type, name));
|
| + var entry = new devtools.profiler.Profile.DynamicCodeEntry(size, type, name);
|
| + this.codeMap_.addCode(start, entry);
|
| + return entry;
|
| };
|
|
|
|
|
| @@ -107,7 +127,7 @@ devtools.profiler.Profile.prototype.moveCode = function(from, to) {
|
| try {
|
| this.codeMap_.moveCode(from, to);
|
| } catch (e) {
|
| - this.handleUnknownCode('move', from);
|
| + this.handleUnknownCode(devtools.profiler.Profile.Operation.MOVE, from);
|
| }
|
| };
|
|
|
| @@ -121,7 +141,7 @@ devtools.profiler.Profile.prototype.deleteCode = function(start) {
|
| try {
|
| this.codeMap_.deleteCode(start);
|
| } catch (e) {
|
| - this.handleUnknownCode('delete', start);
|
| + this.handleUnknownCode(devtools.profiler.Profile.Operation.DELETE, start);
|
| }
|
| };
|
|
|
| @@ -156,7 +176,8 @@ devtools.profiler.Profile.prototype.resolveAndFilterFuncs_ = function(stack) {
|
| result.push(name);
|
| }
|
| } else {
|
| - this.handleUnknownCode('tick', stack[i]);
|
| + this.handleUnknownCode(
|
| + devtools.profiler.Profile.Operation.TICK, stack[i], i);
|
| }
|
| }
|
| return result;
|
| @@ -168,7 +189,7 @@ devtools.profiler.Profile.prototype.resolveAndFilterFuncs_ = function(stack) {
|
| */
|
| devtools.profiler.Profile.prototype.getTopDownTreeRoot = function() {
|
| this.topDownTree_.computeTotalWeights();
|
| - return this.topDownTree_.root_;
|
| + return this.topDownTree_.getRoot();
|
| };
|
|
|
|
|
| @@ -177,7 +198,7 @@ devtools.profiler.Profile.prototype.getTopDownTreeRoot = function() {
|
| */
|
| devtools.profiler.Profile.prototype.getBottomUpTreeRoot = function() {
|
| this.bottomUpTree_.computeTotalWeights();
|
| - return this.bottomUpTree_.root_;
|
| + return this.bottomUpTree_.getRoot();
|
| };
|
|
|
|
|
| @@ -202,12 +223,42 @@ devtools.profiler.Profile.prototype.traverseBottomUpTree = function(f) {
|
|
|
|
|
| /**
|
| + * Calculates a top down profile starting from the specified node.
|
| + *
|
| + * @param {devtools.profiler.CallTree.Node} opt_root Starting node.
|
| + */
|
| +devtools.profiler.Profile.prototype.getTopDownProfile = function(opt_root) {
|
| + if (!opt_root) {
|
| + this.topDownTree_.computeTotalWeights();
|
| + return this.topDownTree_;
|
| + } else {
|
| + throw Error('not implemented');
|
| + }
|
| +};
|
| +
|
| +
|
| +/**
|
| + * Calculates a bottom up profile starting from the specified node.
|
| + *
|
| + * @param {devtools.profiler.CallTree.Node} opt_root Starting node.
|
| + */
|
| +devtools.profiler.Profile.prototype.getBottomUpProfile = function(opt_root) {
|
| + if (!opt_root) {
|
| + this.bottomUpTree_.computeTotalWeights();
|
| + return this.bottomUpTree_;
|
| + } else {
|
| + throw Error('not implemented');
|
| + }
|
| +};
|
| +
|
| +
|
| +/**
|
| * Calculates a flat profile of callees starting from the specified node.
|
| *
|
| * @param {devtools.profiler.CallTree.Node} opt_root Starting node.
|
| */
|
| devtools.profiler.Profile.prototype.getFlatProfile = function(opt_root) {
|
| - var counters = new devtools.profiler.CallTree.Node('');
|
| + var counters = new devtools.profiler.CallTree();
|
| var precs = {};
|
| this.topDownTree_.computeTotalWeights();
|
| this.topDownTree_.traverseInDepth(
|
| @@ -226,7 +277,7 @@ devtools.profiler.Profile.prototype.getFlatProfile = function(opt_root) {
|
| precs[node.label]--;
|
| },
|
| opt_root);
|
| - return counters.exportChildren();
|
| + return counters;
|
| };
|
|
|
|
|
| @@ -276,6 +327,14 @@ devtools.profiler.CallTree.prototype.totalsComputed_ = false;
|
|
|
|
|
| /**
|
| + * Returns the tree root.
|
| + */
|
| +devtools.profiler.CallTree.prototype.getRoot = function() {
|
| + return this.root_;
|
| +};
|
| +
|
| +
|
| +/**
|
| * Adds the specified call path, constructing nodes as necessary.
|
| *
|
| * @param {Array<string>} path Call path.
|
| @@ -294,6 +353,20 @@ devtools.profiler.CallTree.prototype.addPath = function(path) {
|
|
|
|
|
| /**
|
| + * Finds an immediate child of the specified parent with the specified
|
| + * label, creates a child node if necessary. If a parent node isn't
|
| + * specified, uses tree root.
|
| + *
|
| + * @param {string} label Child node label.
|
| + */
|
| +devtools.profiler.CallTree.prototype.findOrAddChild = function(
|
| + label, opt_parent) {
|
| + var parent = opt_parent || this.root_;
|
| + return parent.findOrAddChild(label);
|
| +};
|
| +
|
| +
|
| +/**
|
| * Computes total weights in the call graph.
|
| */
|
| devtools.profiler.CallTree.prototype.computeTotalWeights = function() {
|
| @@ -306,17 +379,30 @@ devtools.profiler.CallTree.prototype.computeTotalWeights = function() {
|
|
|
|
|
| /**
|
| - * Traverses the call graph in preorder.
|
| + * Traverses the call graph in preorder. This function can be used for
|
| + * building optionally modified tree clones. This is the boilerplate code
|
| + * for this scenario:
|
| *
|
| - * @param {function(devtools.profiler.CallTree.Node)} f Visitor function.
|
| + * callTree.traverse(function(node, parentClone) {
|
| + * var nodeClone = cloneNode(node);
|
| + * if (parentClone)
|
| + * parentClone.addChild(nodeClone);
|
| + * return nodeClone;
|
| + * });
|
| + *
|
| + * @param {function(devtools.profiler.CallTree.Node, *)} f Visitor function.
|
| + * The second parameter is the result of calling 'f' on the parent node.
|
| * @param {devtools.profiler.CallTree.Node} opt_start Starting node.
|
| */
|
| devtools.profiler.CallTree.prototype.traverse = function(f, opt_start) {
|
| - var nodesToVisit = [opt_start || this.root_];
|
| - while (nodesToVisit.length > 0) {
|
| - var node = nodesToVisit.shift();
|
| - f(node);
|
| - nodesToVisit = nodesToVisit.concat(node.exportChildren());
|
| + var pairsToProcess = [{node: opt_start || this.root_, param: null}];
|
| + while (pairsToProcess.length > 0) {
|
| + var pair = pairsToProcess.shift();
|
| + var node = pair.node;
|
| + var newParam = f(node, pair.param);
|
| + node.forEachChild(
|
| + function (child) { pairsToProcess.push({node: child, param: newParam}); }
|
| + );
|
| }
|
| };
|
|
|
|
|