OLD | NEW |
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 |
(...skipping 18 matching lines...) Expand all Loading... |
29 /** | 29 /** |
30 * Creates a profile object for processing profiling-related events | 30 * Creates a profile object for processing profiling-related events |
31 * and calculating function execution times. | 31 * and calculating function execution times. |
32 * | 32 * |
33 * @constructor | 33 * @constructor |
34 */ | 34 */ |
35 function Profile() { | 35 function Profile() { |
36 this.codeMap_ = new CodeMap(); | 36 this.codeMap_ = new CodeMap(); |
37 this.topDownTree_ = new CallTree(); | 37 this.topDownTree_ = new CallTree(); |
38 this.bottomUpTree_ = new CallTree(); | 38 this.bottomUpTree_ = new CallTree(); |
| 39 this.c_entries_ = {}; |
39 }; | 40 }; |
40 | 41 |
41 | 42 |
42 /** | 43 /** |
43 * Returns whether a function with the specified name must be skipped. | 44 * Returns whether a function with the specified name must be skipped. |
44 * Should be overriden by subclasses. | 45 * Should be overriden by subclasses. |
45 * | 46 * |
46 * @param {string} name Function name. | 47 * @param {string} name Function name. |
47 */ | 48 */ |
48 Profile.prototype.skipThisFunction = function(name) { | 49 Profile.prototype.skipThisFunction = function(name) { |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
95 /** | 96 /** |
96 * Registers a library. | 97 * Registers a library. |
97 * | 98 * |
98 * @param {string} name Code entry name. | 99 * @param {string} name Code entry name. |
99 * @param {number} startAddr Starting address. | 100 * @param {number} startAddr Starting address. |
100 * @param {number} endAddr Ending address. | 101 * @param {number} endAddr Ending address. |
101 */ | 102 */ |
102 Profile.prototype.addLibrary = function( | 103 Profile.prototype.addLibrary = function( |
103 name, startAddr, endAddr) { | 104 name, startAddr, endAddr) { |
104 var entry = new CodeMap.CodeEntry( | 105 var entry = new CodeMap.CodeEntry( |
105 endAddr - startAddr, name); | 106 endAddr - startAddr, name, 'SHARED_LIB'); |
106 this.codeMap_.addLibrary(startAddr, entry); | 107 this.codeMap_.addLibrary(startAddr, entry); |
107 return entry; | 108 return entry; |
108 }; | 109 }; |
109 | 110 |
110 | 111 |
111 /** | 112 /** |
112 * Registers statically compiled code entry. | 113 * Registers statically compiled code entry. |
113 * | 114 * |
114 * @param {string} name Code entry name. | 115 * @param {string} name Code entry name. |
115 * @param {number} startAddr Starting address. | 116 * @param {number} startAddr Starting address. |
116 * @param {number} endAddr Ending address. | 117 * @param {number} endAddr Ending address. |
117 */ | 118 */ |
118 Profile.prototype.addStaticCode = function( | 119 Profile.prototype.addStaticCode = function( |
119 name, startAddr, endAddr) { | 120 name, startAddr, endAddr) { |
120 var entry = new CodeMap.CodeEntry( | 121 var entry = new CodeMap.CodeEntry( |
121 endAddr - startAddr, name); | 122 endAddr - startAddr, name, 'CPP'); |
122 this.codeMap_.addStaticCode(startAddr, entry); | 123 this.codeMap_.addStaticCode(startAddr, entry); |
123 return entry; | 124 return entry; |
124 }; | 125 }; |
125 | 126 |
126 | 127 |
127 /** | 128 /** |
128 * Registers dynamic (JIT-compiled) code entry. | 129 * Registers dynamic (JIT-compiled) code entry. |
129 * | 130 * |
130 * @param {string} type Code entry type. | 131 * @param {string} type Code entry type. |
131 * @param {string} name Code entry name. | 132 * @param {string} name Code entry name. |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
243 | 244 |
244 | 245 |
245 /** | 246 /** |
246 * Translates addresses into function names and filters unneeded | 247 * Translates addresses into function names and filters unneeded |
247 * functions. | 248 * functions. |
248 * | 249 * |
249 * @param {Array<number>} stack Stack sample. | 250 * @param {Array<number>} stack Stack sample. |
250 */ | 251 */ |
251 Profile.prototype.resolveAndFilterFuncs_ = function(stack) { | 252 Profile.prototype.resolveAndFilterFuncs_ = function(stack) { |
252 var result = []; | 253 var result = []; |
| 254 var last_seen_c_function = ''; |
| 255 var look_for_first_c_function = false; |
253 for (var i = 0; i < stack.length; ++i) { | 256 for (var i = 0; i < stack.length; ++i) { |
254 var entry = this.codeMap_.findEntry(stack[i]); | 257 var entry = this.codeMap_.findEntry(stack[i]); |
255 if (entry) { | 258 if (entry) { |
256 var name = entry.getName(); | 259 var name = entry.getName(); |
| 260 if (i == 0 && (entry.type == 'CPP' || entry.type == 'SHARED_LIB')) { |
| 261 look_for_first_c_function = true; |
| 262 } |
| 263 if (look_for_first_c_function) { |
| 264 if (entry.type == 'CPP') { |
| 265 last_seen_c_function = name; |
| 266 } else if (i > 0 && last_seen_c_function != '') { |
| 267 if (this.c_entries_[last_seen_c_function] === undefined) { |
| 268 this.c_entries_[last_seen_c_function] = 0; |
| 269 } |
| 270 this.c_entries_[last_seen_c_function]++; |
| 271 look_for_first_c_function = false; // Found it, we're done. |
| 272 } |
| 273 } |
257 if (!this.skipThisFunction(name)) { | 274 if (!this.skipThisFunction(name)) { |
258 result.push(name); | 275 result.push(name); |
259 } | 276 } |
260 } else { | 277 } else { |
261 this.handleUnknownCode( | 278 this.handleUnknownCode( |
262 Profile.Operation.TICK, stack[i], i); | 279 Profile.Operation.TICK, stack[i], i); |
263 } | 280 } |
264 } | 281 } |
265 return result; | 282 return result; |
266 }; | 283 }; |
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
374 counters.root_ = root; | 391 counters.root_ = root; |
375 } else { | 392 } else { |
376 // Propagate weights so percents can be calculated correctly. | 393 // Propagate weights so percents can be calculated correctly. |
377 counters.getRoot().selfWeight = root.selfWeight; | 394 counters.getRoot().selfWeight = root.selfWeight; |
378 counters.getRoot().totalWeight = root.totalWeight; | 395 counters.getRoot().totalWeight = root.totalWeight; |
379 } | 396 } |
380 return counters; | 397 return counters; |
381 }; | 398 }; |
382 | 399 |
383 | 400 |
| 401 Profile.CEntryNode = function(name, ticks) { |
| 402 this.name = name; |
| 403 this.ticks = ticks; |
| 404 } |
| 405 |
| 406 |
| 407 Profile.prototype.getCEntryProfile = function() { |
| 408 var result = [new Profile.CEntryNode("TOTAL", 0)]; |
| 409 var total_ticks = 0; |
| 410 for (var f in this.c_entries_) { |
| 411 var ticks = this.c_entries_[f]; |
| 412 total_ticks += ticks; |
| 413 result.push(new Profile.CEntryNode(f, ticks)); |
| 414 } |
| 415 result[0].ticks = total_ticks; // Sorting will keep this at index 0. |
| 416 result.sort(function(n1, n2) { |
| 417 return n2.ticks - n1.ticks || (n2.name < n1.name ? -1 : 1) |
| 418 }); |
| 419 return result; |
| 420 } |
| 421 |
| 422 |
384 /** | 423 /** |
385 * Cleans up function entries that are not referenced by code entries. | 424 * Cleans up function entries that are not referenced by code entries. |
386 */ | 425 */ |
387 Profile.prototype.cleanUpFuncEntries = function() { | 426 Profile.prototype.cleanUpFuncEntries = function() { |
388 var referencedFuncEntries = []; | 427 var referencedFuncEntries = []; |
389 var entries = this.codeMap_.getAllDynamicEntriesWithAddresses(); | 428 var entries = this.codeMap_.getAllDynamicEntriesWithAddresses(); |
390 for (var i = 0, l = entries.length; i < l; ++i) { | 429 for (var i = 0, l = entries.length; i < l; ++i) { |
391 if (entries[i][1].constructor === Profile.FunctionEntry) { | 430 if (entries[i][1].constructor === Profile.FunctionEntry) { |
392 entries[i][1].used = false; | 431 entries[i][1].used = false; |
393 } | 432 } |
(...skipping 14 matching lines...) Expand all Loading... |
408 | 447 |
409 /** | 448 /** |
410 * Creates a dynamic code entry. | 449 * Creates a dynamic code entry. |
411 * | 450 * |
412 * @param {number} size Code size. | 451 * @param {number} size Code size. |
413 * @param {string} type Code type. | 452 * @param {string} type Code type. |
414 * @param {string} name Function name. | 453 * @param {string} name Function name. |
415 * @constructor | 454 * @constructor |
416 */ | 455 */ |
417 Profile.DynamicCodeEntry = function(size, type, name) { | 456 Profile.DynamicCodeEntry = function(size, type, name) { |
418 CodeMap.CodeEntry.call(this, size, name); | 457 CodeMap.CodeEntry.call(this, size, name, type); |
419 this.type = type; | |
420 }; | 458 }; |
421 | 459 |
422 | 460 |
423 /** | 461 /** |
424 * Returns node name. | 462 * Returns node name. |
425 */ | 463 */ |
426 Profile.DynamicCodeEntry.prototype.getName = function() { | 464 Profile.DynamicCodeEntry.prototype.getName = function() { |
427 return this.type + ': ' + this.name; | 465 return this.type + ': ' + this.name; |
428 }; | 466 }; |
429 | 467 |
(...skipping 19 matching lines...) Expand all Loading... |
449 /** | 487 /** |
450 * Creates a dynamic code entry. | 488 * Creates a dynamic code entry. |
451 * | 489 * |
452 * @param {number} size Code size. | 490 * @param {number} size Code size. |
453 * @param {string} type Code type. | 491 * @param {string} type Code type. |
454 * @param {Profile.FunctionEntry} func Shared function entry. | 492 * @param {Profile.FunctionEntry} func Shared function entry. |
455 * @param {Profile.CodeState} state Code optimization state. | 493 * @param {Profile.CodeState} state Code optimization state. |
456 * @constructor | 494 * @constructor |
457 */ | 495 */ |
458 Profile.DynamicFuncCodeEntry = function(size, type, func, state) { | 496 Profile.DynamicFuncCodeEntry = function(size, type, func, state) { |
459 CodeMap.CodeEntry.call(this, size); | 497 CodeMap.CodeEntry.call(this, size, '', type); |
460 this.type = type; | |
461 this.func = func; | 498 this.func = func; |
462 this.state = state; | 499 this.state = state; |
463 }; | 500 }; |
464 | 501 |
465 Profile.DynamicFuncCodeEntry.STATE_PREFIX = ["", "~", "*"]; | 502 Profile.DynamicFuncCodeEntry.STATE_PREFIX = ["", "~", "*"]; |
466 | 503 |
467 /** | 504 /** |
468 * Returns node name. | 505 * Returns node name. |
469 */ | 506 */ |
470 Profile.DynamicFuncCodeEntry.prototype.getName = function() { | 507 Profile.DynamicFuncCodeEntry.prototype.getName = function() { |
(...skipping 315 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
786 labels, opt_f) { | 823 labels, opt_f) { |
787 for (var pos = 0, curr = this; pos < labels.length && curr != null; pos++) { | 824 for (var pos = 0, curr = this; pos < labels.length && curr != null; pos++) { |
788 var child = curr.findChild(labels[pos]); | 825 var child = curr.findChild(labels[pos]); |
789 if (opt_f) { | 826 if (opt_f) { |
790 opt_f(child, pos); | 827 opt_f(child, pos); |
791 } | 828 } |
792 curr = child; | 829 curr = child; |
793 } | 830 } |
794 return curr; | 831 return curr; |
795 }; | 832 }; |
OLD | NEW |