Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(11)

Side by Side Diff: tools/profile.js

Issue 6456025: Shorten constructor names in JS tickprocessor. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: and CallTree Created 9 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « tools/logreader.js ('k') | tools/profile_view.js » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2009 the V8 project authors. All rights reserved. 1 // Copyright 2009 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
11 // with the distribution. 11 // with the distribution.
12 // * Neither the name of Google Inc. nor the names of its 12 // * Neither the name of Google Inc. nor the names of its
13 // contributors may be used to endorse or promote products derived 13 // contributors may be used to endorse or promote products derived
14 // from this software without specific prior written permission. 14 // from this software without specific prior written permission.
15 // 15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 27
28 28
29 // Initlialize namespaces
30 var devtools = devtools || {};
31 devtools.profiler = devtools.profiler || {};
32
33
34 /** 29 /**
35 * Creates a profile object for processing profiling-related events 30 * Creates a profile object for processing profiling-related events
36 * and calculating function execution times. 31 * and calculating function execution times.
37 * 32 *
38 * @constructor 33 * @constructor
39 */ 34 */
40 devtools.profiler.Profile = function() { 35 function Profile() {
41 this.codeMap_ = new devtools.profiler.CodeMap(); 36 this.codeMap_ = new CodeMap();
42 this.topDownTree_ = new devtools.profiler.CallTree(); 37 this.topDownTree_ = new CallTree();
43 this.bottomUpTree_ = new devtools.profiler.CallTree(); 38 this.bottomUpTree_ = new CallTree();
44 }; 39 };
45 40
46 /** 41 /**
47 * Version of profiler log. 42 * Version of profiler log.
48 */ 43 */
49 devtools.profiler.Profile.VERSION = 2; 44 Profile.VERSION = 2;
50 45
51 46
52 /** 47 /**
53 * Returns whether a function with the specified name must be skipped. 48 * Returns whether a function with the specified name must be skipped.
54 * Should be overriden by subclasses. 49 * Should be overriden by subclasses.
55 * 50 *
56 * @param {string} name Function name. 51 * @param {string} name Function name.
57 */ 52 */
58 devtools.profiler.Profile.prototype.skipThisFunction = function(name) { 53 Profile.prototype.skipThisFunction = function(name) {
59 return false; 54 return false;
60 }; 55 };
61 56
62 57
63 /** 58 /**
64 * Enum for profiler operations that involve looking up existing 59 * Enum for profiler operations that involve looking up existing
65 * code entries. 60 * code entries.
66 * 61 *
67 * @enum {number} 62 * @enum {number}
68 */ 63 */
69 devtools.profiler.Profile.Operation = { 64 Profile.Operation = {
70 MOVE: 0, 65 MOVE: 0,
71 DELETE: 1, 66 DELETE: 1,
72 TICK: 2 67 TICK: 2
73 }; 68 };
74 69
75 70
76 /** 71 /**
77 * Called whenever the specified operation has failed finding a function 72 * Called whenever the specified operation has failed finding a function
78 * containing the specified address. Should be overriden by subclasses. 73 * containing the specified address. Should be overriden by subclasses.
79 * See the devtools.profiler.Profile.Operation enum for the list of 74 * See the Profile.Operation enum for the list of
80 * possible operations. 75 * possible operations.
81 * 76 *
82 * @param {number} operation Operation. 77 * @param {number} operation Operation.
83 * @param {number} addr Address of the unknown code. 78 * @param {number} addr Address of the unknown code.
84 * @param {number} opt_stackPos If an unknown address is encountered 79 * @param {number} opt_stackPos If an unknown address is encountered
85 * during stack strace processing, specifies a position of the frame 80 * during stack strace processing, specifies a position of the frame
86 * containing the address. 81 * containing the address.
87 */ 82 */
88 devtools.profiler.Profile.prototype.handleUnknownCode = function( 83 Profile.prototype.handleUnknownCode = function(
89 operation, addr, opt_stackPos) { 84 operation, addr, opt_stackPos) {
90 }; 85 };
91 86
92 87
93 /** 88 /**
94 * Registers a library. 89 * Registers a library.
95 * 90 *
96 * @param {string} name Code entry name. 91 * @param {string} name Code entry name.
97 * @param {number} startAddr Starting address. 92 * @param {number} startAddr Starting address.
98 * @param {number} endAddr Ending address. 93 * @param {number} endAddr Ending address.
99 */ 94 */
100 devtools.profiler.Profile.prototype.addLibrary = function( 95 Profile.prototype.addLibrary = function(
101 name, startAddr, endAddr) { 96 name, startAddr, endAddr) {
102 var entry = new devtools.profiler.CodeMap.CodeEntry( 97 var entry = new CodeMap.CodeEntry(
103 endAddr - startAddr, name); 98 endAddr - startAddr, name);
104 this.codeMap_.addLibrary(startAddr, entry); 99 this.codeMap_.addLibrary(startAddr, entry);
105 return entry; 100 return entry;
106 }; 101 };
107 102
108 103
109 /** 104 /**
110 * Registers statically compiled code entry. 105 * Registers statically compiled code entry.
111 * 106 *
112 * @param {string} name Code entry name. 107 * @param {string} name Code entry name.
113 * @param {number} startAddr Starting address. 108 * @param {number} startAddr Starting address.
114 * @param {number} endAddr Ending address. 109 * @param {number} endAddr Ending address.
115 */ 110 */
116 devtools.profiler.Profile.prototype.addStaticCode = function( 111 Profile.prototype.addStaticCode = function(
117 name, startAddr, endAddr) { 112 name, startAddr, endAddr) {
118 var entry = new devtools.profiler.CodeMap.CodeEntry( 113 var entry = new CodeMap.CodeEntry(
119 endAddr - startAddr, name); 114 endAddr - startAddr, name);
120 this.codeMap_.addStaticCode(startAddr, entry); 115 this.codeMap_.addStaticCode(startAddr, entry);
121 return entry; 116 return entry;
122 }; 117 };
123 118
124 119
125 /** 120 /**
126 * Registers dynamic (JIT-compiled) code entry. 121 * Registers dynamic (JIT-compiled) code entry.
127 * 122 *
128 * @param {string} type Code entry type. 123 * @param {string} type Code entry type.
129 * @param {string} name Code entry name. 124 * @param {string} name Code entry name.
130 * @param {number} start Starting address. 125 * @param {number} start Starting address.
131 * @param {number} size Code entry size. 126 * @param {number} size Code entry size.
132 */ 127 */
133 devtools.profiler.Profile.prototype.addCode = function( 128 Profile.prototype.addCode = function(
134 type, name, start, size) { 129 type, name, start, size) {
135 var entry = new devtools.profiler.Profile.DynamicCodeEntry(size, type, name); 130 var entry = new Profile.DynamicCodeEntry(size, type, name);
136 this.codeMap_.addCode(start, entry); 131 this.codeMap_.addCode(start, entry);
137 return entry; 132 return entry;
138 }; 133 };
139 134
140 135
141 /** 136 /**
142 * Creates an alias entry for a code entry. 137 * Creates an alias entry for a code entry.
143 * 138 *
144 * @param {number} aliasAddr Alias address. 139 * @param {number} aliasAddr Alias address.
145 * @param {number} addr Code entry address. 140 * @param {number} addr Code entry address.
146 */ 141 */
147 devtools.profiler.Profile.prototype.addCodeAlias = function( 142 Profile.prototype.addCodeAlias = function(
148 aliasAddr, addr) { 143 aliasAddr, addr) {
149 var entry = this.codeMap_.findDynamicEntryByStartAddress(addr); 144 var entry = this.codeMap_.findDynamicEntryByStartAddress(addr);
150 if (entry) { 145 if (entry) {
151 this.codeMap_.addCode(aliasAddr, entry); 146 this.codeMap_.addCode(aliasAddr, entry);
152 } 147 }
153 }; 148 };
154 149
155 150
156 /** 151 /**
157 * Reports about moving of a dynamic code entry. 152 * Reports about moving of a dynamic code entry.
158 * 153 *
159 * @param {number} from Current code entry address. 154 * @param {number} from Current code entry address.
160 * @param {number} to New code entry address. 155 * @param {number} to New code entry address.
161 */ 156 */
162 devtools.profiler.Profile.prototype.moveCode = function(from, to) { 157 Profile.prototype.moveCode = function(from, to) {
163 try { 158 try {
164 this.codeMap_.moveCode(from, to); 159 this.codeMap_.moveCode(from, to);
165 } catch (e) { 160 } catch (e) {
166 this.handleUnknownCode(devtools.profiler.Profile.Operation.MOVE, from); 161 this.handleUnknownCode(Profile.Operation.MOVE, from);
167 } 162 }
168 }; 163 };
169 164
170 165
171 /** 166 /**
172 * Reports about deletion of a dynamic code entry. 167 * Reports about deletion of a dynamic code entry.
173 * 168 *
174 * @param {number} start Starting address. 169 * @param {number} start Starting address.
175 */ 170 */
176 devtools.profiler.Profile.prototype.deleteCode = function(start) { 171 Profile.prototype.deleteCode = function(start) {
177 try { 172 try {
178 this.codeMap_.deleteCode(start); 173 this.codeMap_.deleteCode(start);
179 } catch (e) { 174 } catch (e) {
180 this.handleUnknownCode(devtools.profiler.Profile.Operation.DELETE, start); 175 this.handleUnknownCode(Profile.Operation.DELETE, start);
181 } 176 }
182 }; 177 };
183 178
184 179
185 /** 180 /**
186 * Reports about moving of a dynamic code entry. 181 * Reports about moving of a dynamic code entry.
187 * 182 *
188 * @param {number} from Current code entry address. 183 * @param {number} from Current code entry address.
189 * @param {number} to New code entry address. 184 * @param {number} to New code entry address.
190 */ 185 */
191 devtools.profiler.Profile.prototype.safeMoveDynamicCode = function(from, to) { 186 Profile.prototype.safeMoveDynamicCode = function(from, to) {
192 if (this.codeMap_.findDynamicEntryByStartAddress(from)) { 187 if (this.codeMap_.findDynamicEntryByStartAddress(from)) {
193 this.codeMap_.moveCode(from, to); 188 this.codeMap_.moveCode(from, to);
194 } 189 }
195 }; 190 };
196 191
197 192
198 /** 193 /**
199 * Reports about deletion of a dynamic code entry. 194 * Reports about deletion of a dynamic code entry.
200 * 195 *
201 * @param {number} start Starting address. 196 * @param {number} start Starting address.
202 */ 197 */
203 devtools.profiler.Profile.prototype.safeDeleteDynamicCode = function(start) { 198 Profile.prototype.safeDeleteDynamicCode = function(start) {
204 if (this.codeMap_.findDynamicEntryByStartAddress(start)) { 199 if (this.codeMap_.findDynamicEntryByStartAddress(start)) {
205 this.codeMap_.deleteCode(start); 200 this.codeMap_.deleteCode(start);
206 } 201 }
207 }; 202 };
208 203
209 204
210 /** 205 /**
211 * Retrieves a code entry by an address. 206 * Retrieves a code entry by an address.
212 * 207 *
213 * @param {number} addr Entry address. 208 * @param {number} addr Entry address.
214 */ 209 */
215 devtools.profiler.Profile.prototype.findEntry = function(addr) { 210 Profile.prototype.findEntry = function(addr) {
216 return this.codeMap_.findEntry(addr); 211 return this.codeMap_.findEntry(addr);
217 }; 212 };
218 213
219 214
220 /** 215 /**
221 * Records a tick event. Stack must contain a sequence of 216 * Records a tick event. Stack must contain a sequence of
222 * addresses starting with the program counter value. 217 * addresses starting with the program counter value.
223 * 218 *
224 * @param {Array<number>} stack Stack sample. 219 * @param {Array<number>} stack Stack sample.
225 */ 220 */
226 devtools.profiler.Profile.prototype.recordTick = function(stack) { 221 Profile.prototype.recordTick = function(stack) {
227 var processedStack = this.resolveAndFilterFuncs_(stack); 222 var processedStack = this.resolveAndFilterFuncs_(stack);
228 this.bottomUpTree_.addPath(processedStack); 223 this.bottomUpTree_.addPath(processedStack);
229 processedStack.reverse(); 224 processedStack.reverse();
230 this.topDownTree_.addPath(processedStack); 225 this.topDownTree_.addPath(processedStack);
231 }; 226 };
232 227
233 228
234 /** 229 /**
235 * Translates addresses into function names and filters unneeded 230 * Translates addresses into function names and filters unneeded
236 * functions. 231 * functions.
237 * 232 *
238 * @param {Array<number>} stack Stack sample. 233 * @param {Array<number>} stack Stack sample.
239 */ 234 */
240 devtools.profiler.Profile.prototype.resolveAndFilterFuncs_ = function(stack) { 235 Profile.prototype.resolveAndFilterFuncs_ = function(stack) {
241 var result = []; 236 var result = [];
242 for (var i = 0; i < stack.length; ++i) { 237 for (var i = 0; i < stack.length; ++i) {
243 var entry = this.codeMap_.findEntry(stack[i]); 238 var entry = this.codeMap_.findEntry(stack[i]);
244 if (entry) { 239 if (entry) {
245 var name = entry.getName(); 240 var name = entry.getName();
246 if (!this.skipThisFunction(name)) { 241 if (!this.skipThisFunction(name)) {
247 result.push(name); 242 result.push(name);
248 } 243 }
249 } else { 244 } else {
250 this.handleUnknownCode( 245 this.handleUnknownCode(
251 devtools.profiler.Profile.Operation.TICK, stack[i], i); 246 Profile.Operation.TICK, stack[i], i);
252 } 247 }
253 } 248 }
254 return result; 249 return result;
255 }; 250 };
256 251
257 252
258 /** 253 /**
259 * Performs a BF traversal of the top down call graph. 254 * Performs a BF traversal of the top down call graph.
260 * 255 *
261 * @param {function(devtools.profiler.CallTree.Node)} f Visitor function. 256 * @param {function(CallTree.Node)} f Visitor function.
262 */ 257 */
263 devtools.profiler.Profile.prototype.traverseTopDownTree = function(f) { 258 Profile.prototype.traverseTopDownTree = function(f) {
264 this.topDownTree_.traverse(f); 259 this.topDownTree_.traverse(f);
265 }; 260 };
266 261
267 262
268 /** 263 /**
269 * Performs a BF traversal of the bottom up call graph. 264 * Performs a BF traversal of the bottom up call graph.
270 * 265 *
271 * @param {function(devtools.profiler.CallTree.Node)} f Visitor function. 266 * @param {function(CallTree.Node)} f Visitor function.
272 */ 267 */
273 devtools.profiler.Profile.prototype.traverseBottomUpTree = function(f) { 268 Profile.prototype.traverseBottomUpTree = function(f) {
274 this.bottomUpTree_.traverse(f); 269 this.bottomUpTree_.traverse(f);
275 }; 270 };
276 271
277 272
278 /** 273 /**
279 * Calculates a top down profile for a node with the specified label. 274 * Calculates a top down profile for a node with the specified label.
280 * If no name specified, returns the whole top down calls tree. 275 * If no name specified, returns the whole top down calls tree.
281 * 276 *
282 * @param {string} opt_label Node label. 277 * @param {string} opt_label Node label.
283 */ 278 */
284 devtools.profiler.Profile.prototype.getTopDownProfile = function(opt_label) { 279 Profile.prototype.getTopDownProfile = function(opt_label) {
285 return this.getTreeProfile_(this.topDownTree_, opt_label); 280 return this.getTreeProfile_(this.topDownTree_, opt_label);
286 }; 281 };
287 282
288 283
289 /** 284 /**
290 * Calculates a bottom up profile for a node with the specified label. 285 * Calculates a bottom up profile for a node with the specified label.
291 * If no name specified, returns the whole bottom up calls tree. 286 * If no name specified, returns the whole bottom up calls tree.
292 * 287 *
293 * @param {string} opt_label Node label. 288 * @param {string} opt_label Node label.
294 */ 289 */
295 devtools.profiler.Profile.prototype.getBottomUpProfile = function(opt_label) { 290 Profile.prototype.getBottomUpProfile = function(opt_label) {
296 return this.getTreeProfile_(this.bottomUpTree_, opt_label); 291 return this.getTreeProfile_(this.bottomUpTree_, opt_label);
297 }; 292 };
298 293
299 294
300 /** 295 /**
301 * Helper function for calculating a tree profile. 296 * Helper function for calculating a tree profile.
302 * 297 *
303 * @param {devtools.profiler.Profile.CallTree} tree Call tree. 298 * @param {Profile.CallTree} tree Call tree.
304 * @param {string} opt_label Node label. 299 * @param {string} opt_label Node label.
305 */ 300 */
306 devtools.profiler.Profile.prototype.getTreeProfile_ = function(tree, opt_label) { 301 Profile.prototype.getTreeProfile_ = function(tree, opt_label) {
307 if (!opt_label) { 302 if (!opt_label) {
308 tree.computeTotalWeights(); 303 tree.computeTotalWeights();
309 return tree; 304 return tree;
310 } else { 305 } else {
311 var subTree = tree.cloneSubtree(opt_label); 306 var subTree = tree.cloneSubtree(opt_label);
312 subTree.computeTotalWeights(); 307 subTree.computeTotalWeights();
313 return subTree; 308 return subTree;
314 } 309 }
315 }; 310 };
316 311
317 312
318 /** 313 /**
319 * Calculates a flat profile of callees starting from a node with 314 * Calculates a flat profile of callees starting from a node with
320 * the specified label. If no name specified, starts from the root. 315 * the specified label. If no name specified, starts from the root.
321 * 316 *
322 * @param {string} opt_label Starting node label. 317 * @param {string} opt_label Starting node label.
323 */ 318 */
324 devtools.profiler.Profile.prototype.getFlatProfile = function(opt_label) { 319 Profile.prototype.getFlatProfile = function(opt_label) {
325 var counters = new devtools.profiler.CallTree(); 320 var counters = new CallTree();
326 var rootLabel = opt_label || devtools.profiler.CallTree.ROOT_NODE_LABEL; 321 var rootLabel = opt_label || CallTree.ROOT_NODE_LABEL;
327 var precs = {}; 322 var precs = {};
328 precs[rootLabel] = 0; 323 precs[rootLabel] = 0;
329 var root = counters.findOrAddChild(rootLabel); 324 var root = counters.findOrAddChild(rootLabel);
330 325
331 this.topDownTree_.computeTotalWeights(); 326 this.topDownTree_.computeTotalWeights();
332 this.topDownTree_.traverseInDepth( 327 this.topDownTree_.traverseInDepth(
333 function onEnter(node) { 328 function onEnter(node) {
334 if (!(node.label in precs)) { 329 if (!(node.label in precs)) {
335 precs[node.label] = 0; 330 precs[node.label] = 0;
336 } 331 }
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
371 366
372 367
373 /** 368 /**
374 * Creates a dynamic code entry. 369 * Creates a dynamic code entry.
375 * 370 *
376 * @param {number} size Code size. 371 * @param {number} size Code size.
377 * @param {string} type Code type. 372 * @param {string} type Code type.
378 * @param {string} name Function name. 373 * @param {string} name Function name.
379 * @constructor 374 * @constructor
380 */ 375 */
381 devtools.profiler.Profile.DynamicCodeEntry = function(size, type, name) { 376 Profile.DynamicCodeEntry = function(size, type, name) {
382 devtools.profiler.CodeMap.CodeEntry.call(this, size, name); 377 CodeMap.CodeEntry.call(this, size, name);
383 this.type = type; 378 this.type = type;
384 }; 379 };
385 380
386 381
387 /** 382 /**
388 * Returns node name. 383 * Returns node name.
389 */ 384 */
390 devtools.profiler.Profile.DynamicCodeEntry.prototype.getName = function() { 385 Profile.DynamicCodeEntry.prototype.getName = function() {
391 var name = this.name; 386 var name = this.name;
392 if (name.length == 0) { 387 if (name.length == 0) {
393 name = '<anonymous>'; 388 name = '<anonymous>';
394 } else if (name.charAt(0) == ' ') { 389 } else if (name.charAt(0) == ' ') {
395 // An anonymous function with location: " aaa.js:10". 390 // An anonymous function with location: " aaa.js:10".
396 name = '<anonymous>' + name; 391 name = '<anonymous>' + name;
397 } 392 }
398 return this.type + ': ' + name; 393 return this.type + ': ' + name;
399 }; 394 };
400 395
401 396
402 /** 397 /**
403 * Returns raw node name (without type decoration). 398 * Returns raw node name (without type decoration).
404 */ 399 */
405 devtools.profiler.Profile.DynamicCodeEntry.prototype.getRawName = function() { 400 Profile.DynamicCodeEntry.prototype.getRawName = function() {
406 return this.name; 401 return this.name;
407 }; 402 };
408 403
409 404
410 devtools.profiler.Profile.DynamicCodeEntry.prototype.isJSFunction = function() { 405 Profile.DynamicCodeEntry.prototype.isJSFunction = function() {
411 return this.type == "Function" || 406 return this.type == "Function" ||
412 this.type == "LazyCompile" || 407 this.type == "LazyCompile" ||
413 this.type == "Script"; 408 this.type == "Script";
414 }; 409 };
415 410
416 411
417 /** 412 /**
418 * Constructs a call graph. 413 * Constructs a call graph.
419 * 414 *
420 * @constructor 415 * @constructor
421 */ 416 */
422 devtools.profiler.CallTree = function() { 417 function CallTree() {
423 this.root_ = new devtools.profiler.CallTree.Node( 418 this.root_ = new CallTree.Node(
424 devtools.profiler.CallTree.ROOT_NODE_LABEL); 419 CallTree.ROOT_NODE_LABEL);
425 }; 420 };
426 421
427 422
428 /** 423 /**
429 * The label of the root node. 424 * The label of the root node.
430 */ 425 */
431 devtools.profiler.CallTree.ROOT_NODE_LABEL = ''; 426 CallTree.ROOT_NODE_LABEL = '';
432 427
433 428
434 /** 429 /**
435 * @private 430 * @private
436 */ 431 */
437 devtools.profiler.CallTree.prototype.totalsComputed_ = false; 432 CallTree.prototype.totalsComputed_ = false;
438 433
439 434
440 /** 435 /**
441 * Returns the tree root. 436 * Returns the tree root.
442 */ 437 */
443 devtools.profiler.CallTree.prototype.getRoot = function() { 438 CallTree.prototype.getRoot = function() {
444 return this.root_; 439 return this.root_;
445 }; 440 };
446 441
447 442
448 /** 443 /**
449 * Adds the specified call path, constructing nodes as necessary. 444 * Adds the specified call path, constructing nodes as necessary.
450 * 445 *
451 * @param {Array<string>} path Call path. 446 * @param {Array<string>} path Call path.
452 */ 447 */
453 devtools.profiler.CallTree.prototype.addPath = function(path) { 448 CallTree.prototype.addPath = function(path) {
454 if (path.length == 0) { 449 if (path.length == 0) {
455 return; 450 return;
456 } 451 }
457 var curr = this.root_; 452 var curr = this.root_;
458 for (var i = 0; i < path.length; ++i) { 453 for (var i = 0; i < path.length; ++i) {
459 curr = curr.findOrAddChild(path[i]); 454 curr = curr.findOrAddChild(path[i]);
460 } 455 }
461 curr.selfWeight++; 456 curr.selfWeight++;
462 this.totalsComputed_ = false; 457 this.totalsComputed_ = false;
463 }; 458 };
464 459
465 460
466 /** 461 /**
467 * Finds an immediate child of the specified parent with the specified 462 * Finds an immediate child of the specified parent with the specified
468 * label, creates a child node if necessary. If a parent node isn't 463 * label, creates a child node if necessary. If a parent node isn't
469 * specified, uses tree root. 464 * specified, uses tree root.
470 * 465 *
471 * @param {string} label Child node label. 466 * @param {string} label Child node label.
472 */ 467 */
473 devtools.profiler.CallTree.prototype.findOrAddChild = function(label) { 468 CallTree.prototype.findOrAddChild = function(label) {
474 return this.root_.findOrAddChild(label); 469 return this.root_.findOrAddChild(label);
475 }; 470 };
476 471
477 472
478 /** 473 /**
479 * Creates a subtree by cloning and merging all subtrees rooted at nodes 474 * Creates a subtree by cloning and merging all subtrees rooted at nodes
480 * with a given label. E.g. cloning the following call tree on label 'A' 475 * with a given label. E.g. cloning the following call tree on label 'A'
481 * will give the following result: 476 * will give the following result:
482 * 477 *
483 * <A>--<B> <B> 478 * <A>--<B> <B>
484 * / / 479 * / /
485 * <root> == clone on 'A' ==> <root>--<A> 480 * <root> == clone on 'A' ==> <root>--<A>
486 * \ \ 481 * \ \
487 * <C>--<A>--<D> <D> 482 * <C>--<A>--<D> <D>
488 * 483 *
489 * And <A>'s selfWeight will be the sum of selfWeights of <A>'s from the 484 * And <A>'s selfWeight will be the sum of selfWeights of <A>'s from the
490 * source call tree. 485 * source call tree.
491 * 486 *
492 * @param {string} label The label of the new root node. 487 * @param {string} label The label of the new root node.
493 */ 488 */
494 devtools.profiler.CallTree.prototype.cloneSubtree = function(label) { 489 CallTree.prototype.cloneSubtree = function(label) {
495 var subTree = new devtools.profiler.CallTree(); 490 var subTree = new CallTree();
496 this.traverse(function(node, parent) { 491 this.traverse(function(node, parent) {
497 if (!parent && node.label != label) { 492 if (!parent && node.label != label) {
498 return null; 493 return null;
499 } 494 }
500 var child = (parent ? parent : subTree).findOrAddChild(node.label); 495 var child = (parent ? parent : subTree).findOrAddChild(node.label);
501 child.selfWeight += node.selfWeight; 496 child.selfWeight += node.selfWeight;
502 return child; 497 return child;
503 }); 498 });
504 return subTree; 499 return subTree;
505 }; 500 };
506 501
507 502
508 /** 503 /**
509 * Computes total weights in the call graph. 504 * Computes total weights in the call graph.
510 */ 505 */
511 devtools.profiler.CallTree.prototype.computeTotalWeights = function() { 506 CallTree.prototype.computeTotalWeights = function() {
512 if (this.totalsComputed_) { 507 if (this.totalsComputed_) {
513 return; 508 return;
514 } 509 }
515 this.root_.computeTotalWeight(); 510 this.root_.computeTotalWeight();
516 this.totalsComputed_ = true; 511 this.totalsComputed_ = true;
517 }; 512 };
518 513
519 514
520 /** 515 /**
521 * Traverses the call graph in preorder. This function can be used for 516 * Traverses the call graph in preorder. This function can be used for
522 * building optionally modified tree clones. This is the boilerplate code 517 * building optionally modified tree clones. This is the boilerplate code
523 * for this scenario: 518 * for this scenario:
524 * 519 *
525 * callTree.traverse(function(node, parentClone) { 520 * callTree.traverse(function(node, parentClone) {
526 * var nodeClone = cloneNode(node); 521 * var nodeClone = cloneNode(node);
527 * if (parentClone) 522 * if (parentClone)
528 * parentClone.addChild(nodeClone); 523 * parentClone.addChild(nodeClone);
529 * return nodeClone; 524 * return nodeClone;
530 * }); 525 * });
531 * 526 *
532 * @param {function(devtools.profiler.CallTree.Node, *)} f Visitor function. 527 * @param {function(CallTree.Node, *)} f Visitor function.
533 * The second parameter is the result of calling 'f' on the parent node. 528 * The second parameter is the result of calling 'f' on the parent node.
534 */ 529 */
535 devtools.profiler.CallTree.prototype.traverse = function(f) { 530 CallTree.prototype.traverse = function(f) {
536 var pairsToProcess = new ConsArray(); 531 var pairsToProcess = new ConsArray();
537 pairsToProcess.concat([{node: this.root_, param: null}]); 532 pairsToProcess.concat([{node: this.root_, param: null}]);
538 while (!pairsToProcess.atEnd()) { 533 while (!pairsToProcess.atEnd()) {
539 var pair = pairsToProcess.next(); 534 var pair = pairsToProcess.next();
540 var node = pair.node; 535 var node = pair.node;
541 var newParam = f(node, pair.param); 536 var newParam = f(node, pair.param);
542 var morePairsToProcess = []; 537 var morePairsToProcess = [];
543 node.forEachChild(function (child) { 538 node.forEachChild(function (child) {
544 morePairsToProcess.push({node: child, param: newParam}); }); 539 morePairsToProcess.push({node: child, param: newParam}); });
545 pairsToProcess.concat(morePairsToProcess); 540 pairsToProcess.concat(morePairsToProcess);
546 } 541 }
547 }; 542 };
548 543
549 544
550 /** 545 /**
551 * Performs an indepth call graph traversal. 546 * Performs an indepth call graph traversal.
552 * 547 *
553 * @param {function(devtools.profiler.CallTree.Node)} enter A function called 548 * @param {function(CallTree.Node)} enter A function called
554 * prior to visiting node's children. 549 * prior to visiting node's children.
555 * @param {function(devtools.profiler.CallTree.Node)} exit A function called 550 * @param {function(CallTree.Node)} exit A function called
556 * after visiting node's children. 551 * after visiting node's children.
557 */ 552 */
558 devtools.profiler.CallTree.prototype.traverseInDepth = function(enter, exit) { 553 CallTree.prototype.traverseInDepth = function(enter, exit) {
559 function traverse(node) { 554 function traverse(node) {
560 enter(node); 555 enter(node);
561 node.forEachChild(traverse); 556 node.forEachChild(traverse);
562 exit(node); 557 exit(node);
563 } 558 }
564 traverse(this.root_); 559 traverse(this.root_);
565 }; 560 };
566 561
567 562
568 /** 563 /**
569 * Constructs a call graph node. 564 * Constructs a call graph node.
570 * 565 *
571 * @param {string} label Node label. 566 * @param {string} label Node label.
572 * @param {devtools.profiler.CallTree.Node} opt_parent Node parent. 567 * @param {CallTree.Node} opt_parent Node parent.
573 */ 568 */
574 devtools.profiler.CallTree.Node = function(label, opt_parent) { 569 CallTree.Node = function(label, opt_parent) {
575 this.label = label; 570 this.label = label;
576 this.parent = opt_parent; 571 this.parent = opt_parent;
577 this.children = {}; 572 this.children = {};
578 }; 573 };
579 574
580 575
581 /** 576 /**
582 * Node self weight (how many times this node was the last node in 577 * Node self weight (how many times this node was the last node in
583 * a call path). 578 * a call path).
584 * @type {number} 579 * @type {number}
585 */ 580 */
586 devtools.profiler.CallTree.Node.prototype.selfWeight = 0; 581 CallTree.Node.prototype.selfWeight = 0;
587 582
588 583
589 /** 584 /**
590 * Node total weight (includes weights of all children). 585 * Node total weight (includes weights of all children).
591 * @type {number} 586 * @type {number}
592 */ 587 */
593 devtools.profiler.CallTree.Node.prototype.totalWeight = 0; 588 CallTree.Node.prototype.totalWeight = 0;
594 589
595 590
596 /** 591 /**
597 * Adds a child node. 592 * Adds a child node.
598 * 593 *
599 * @param {string} label Child node label. 594 * @param {string} label Child node label.
600 */ 595 */
601 devtools.profiler.CallTree.Node.prototype.addChild = function(label) { 596 CallTree.Node.prototype.addChild = function(label) {
602 var child = new devtools.profiler.CallTree.Node(label, this); 597 var child = new CallTree.Node(label, this);
603 this.children[label] = child; 598 this.children[label] = child;
604 return child; 599 return child;
605 }; 600 };
606 601
607 602
608 /** 603 /**
609 * Computes node's total weight. 604 * Computes node's total weight.
610 */ 605 */
611 devtools.profiler.CallTree.Node.prototype.computeTotalWeight = 606 CallTree.Node.prototype.computeTotalWeight =
612 function() { 607 function() {
613 var totalWeight = this.selfWeight; 608 var totalWeight = this.selfWeight;
614 this.forEachChild(function(child) { 609 this.forEachChild(function(child) {
615 totalWeight += child.computeTotalWeight(); }); 610 totalWeight += child.computeTotalWeight(); });
616 return this.totalWeight = totalWeight; 611 return this.totalWeight = totalWeight;
617 }; 612 };
618 613
619 614
620 /** 615 /**
621 * Returns all node's children as an array. 616 * Returns all node's children as an array.
622 */ 617 */
623 devtools.profiler.CallTree.Node.prototype.exportChildren = function() { 618 CallTree.Node.prototype.exportChildren = function() {
624 var result = []; 619 var result = [];
625 this.forEachChild(function (node) { result.push(node); }); 620 this.forEachChild(function (node) { result.push(node); });
626 return result; 621 return result;
627 }; 622 };
628 623
629 624
630 /** 625 /**
631 * Finds an immediate child with the specified label. 626 * Finds an immediate child with the specified label.
632 * 627 *
633 * @param {string} label Child node label. 628 * @param {string} label Child node label.
634 */ 629 */
635 devtools.profiler.CallTree.Node.prototype.findChild = function(label) { 630 CallTree.Node.prototype.findChild = function(label) {
636 return this.children[label] || null; 631 return this.children[label] || null;
637 }; 632 };
638 633
639 634
640 /** 635 /**
641 * Finds an immediate child with the specified label, creates a child 636 * Finds an immediate child with the specified label, creates a child
642 * node if necessary. 637 * node if necessary.
643 * 638 *
644 * @param {string} label Child node label. 639 * @param {string} label Child node label.
645 */ 640 */
646 devtools.profiler.CallTree.Node.prototype.findOrAddChild = function(label) { 641 CallTree.Node.prototype.findOrAddChild = function(label) {
647 return this.findChild(label) || this.addChild(label); 642 return this.findChild(label) || this.addChild(label);
648 }; 643 };
649 644
650 645
651 /** 646 /**
652 * Calls the specified function for every child. 647 * Calls the specified function for every child.
653 * 648 *
654 * @param {function(devtools.profiler.CallTree.Node)} f Visitor function. 649 * @param {function(CallTree.Node)} f Visitor function.
655 */ 650 */
656 devtools.profiler.CallTree.Node.prototype.forEachChild = function(f) { 651 CallTree.Node.prototype.forEachChild = function(f) {
657 for (var c in this.children) { 652 for (var c in this.children) {
658 f(this.children[c]); 653 f(this.children[c]);
659 } 654 }
660 }; 655 };
661 656
662 657
663 /** 658 /**
664 * Walks up from the current node up to the call tree root. 659 * Walks up from the current node up to the call tree root.
665 * 660 *
666 * @param {function(devtools.profiler.CallTree.Node)} f Visitor function. 661 * @param {function(CallTree.Node)} f Visitor function.
667 */ 662 */
668 devtools.profiler.CallTree.Node.prototype.walkUpToRoot = function(f) { 663 CallTree.Node.prototype.walkUpToRoot = function(f) {
669 for (var curr = this; curr != null; curr = curr.parent) { 664 for (var curr = this; curr != null; curr = curr.parent) {
670 f(curr); 665 f(curr);
671 } 666 }
672 }; 667 };
673 668
674 669
675 /** 670 /**
676 * Tries to find a node with the specified path. 671 * Tries to find a node with the specified path.
677 * 672 *
678 * @param {Array<string>} labels The path. 673 * @param {Array<string>} labels The path.
679 * @param {function(devtools.profiler.CallTree.Node)} opt_f Visitor function. 674 * @param {function(CallTree.Node)} opt_f Visitor function.
680 */ 675 */
681 devtools.profiler.CallTree.Node.prototype.descendToChild = function( 676 CallTree.Node.prototype.descendToChild = function(
682 labels, opt_f) { 677 labels, opt_f) {
683 for (var pos = 0, curr = this; pos < labels.length && curr != null; pos++) { 678 for (var pos = 0, curr = this; pos < labels.length && curr != null; pos++) {
684 var child = curr.findChild(labels[pos]); 679 var child = curr.findChild(labels[pos]);
685 if (opt_f) { 680 if (opt_f) {
686 opt_f(child, pos); 681 opt_f(child, pos);
687 } 682 }
688 curr = child; 683 curr = child;
689 } 684 }
690 return curr; 685 return curr;
691 }; 686 };
OLDNEW
« no previous file with comments | « tools/logreader.js ('k') | tools/profile_view.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698