OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
43 /^(LoadGlobalIC: )|(Handler: )|(Stub: )|(Builtin: )|(BytecodeHandler: )|(?:C
allIC|LoadIC|StoreIC)|(?:Builtin: (?:Keyed)?(?:Load|Store)IC_)/; | 43 /^(LoadGlobalIC: )|(Handler: )|(Stub: )|(Builtin: )|(BytecodeHandler: )|(?:C
allIC|LoadIC|StoreIC)|(?:Builtin: (?:Keyed)?(?:Load|Store)IC_)/; |
44 | 44 |
45 | 45 |
46 /** | 46 /** |
47 * A thin wrapper around shell's 'read' function showing a file name on error. | 47 * A thin wrapper around shell's 'read' function showing a file name on error. |
48 */ | 48 */ |
49 function readFile(fileName) { | 49 function readFile(fileName) { |
50 try { | 50 try { |
51 return read(fileName); | 51 return read(fileName); |
52 } catch (e) { | 52 } catch (e) { |
53 print(fileName + ': ' + (e.message || e)); | 53 printErr(fileName + ': ' + (e.message || e)); |
54 throw e; | 54 throw e; |
55 } | 55 } |
56 } | 56 } |
57 | 57 |
58 | 58 |
59 /** | 59 /** |
60 * Parser for dynamic code optimization state. | 60 * Parser for dynamic code optimization state. |
61 */ | 61 */ |
62 function parseState(s) { | 62 function parseState(s) { |
63 switch (s) { | 63 switch (s) { |
(...skipping 10 matching lines...) Expand all Loading... |
74 separateIc, | 74 separateIc, |
75 callGraphSize, | 75 callGraphSize, |
76 ignoreUnknown, | 76 ignoreUnknown, |
77 stateFilter, | 77 stateFilter, |
78 distortion, | 78 distortion, |
79 range, | 79 range, |
80 sourceMap, | 80 sourceMap, |
81 timedRange, | 81 timedRange, |
82 pairwiseTimedRange, | 82 pairwiseTimedRange, |
83 onlySummary, | 83 onlySummary, |
84 runtimeTimerFilter) { | 84 runtimeTimerFilter, |
| 85 preprocessJson) { |
| 86 this.preprocessJson = preprocessJson; |
85 LogReader.call(this, { | 87 LogReader.call(this, { |
86 'shared-library': { parsers: [null, parseInt, parseInt, parseInt], | 88 'shared-library': { parsers: [null, parseInt, parseInt, parseInt], |
87 processor: this.processSharedLibrary }, | 89 processor: this.processSharedLibrary }, |
88 'code-creation': { | 90 'code-creation': { |
89 parsers: [null, parseInt, parseInt, parseInt, null, 'var-args'], | 91 parsers: [null, parseInt, parseInt, parseInt, null, 'var-args'], |
90 processor: this.processCodeCreation }, | 92 processor: this.processCodeCreation }, |
91 'code-move': { parsers: [parseInt, parseInt], | 93 'code-move': { parsers: [parseInt, parseInt], |
92 processor: this.processCodeMove }, | 94 processor: this.processCodeMove }, |
93 'code-delete': { parsers: [parseInt], | 95 'code-delete': { parsers: [parseInt], |
94 processor: this.processCodeDelete }, | 96 processor: this.processCodeDelete }, |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
142 var range_end = parseInt(rangelimits[1]); | 144 var range_end = parseInt(rangelimits[1]); |
143 // Convert milliseconds to nanoseconds. | 145 // Convert milliseconds to nanoseconds. |
144 this.range_start = isNaN(range_start) ? -Infinity : (range_start * 1000); | 146 this.range_start = isNaN(range_start) ? -Infinity : (range_start * 1000); |
145 this.range_end = isNaN(range_end) ? Infinity : (range_end * 1000) | 147 this.range_end = isNaN(range_end) ? Infinity : (range_end * 1000) |
146 | 148 |
147 V8Profile.prototype.handleUnknownCode = function( | 149 V8Profile.prototype.handleUnknownCode = function( |
148 operation, addr, opt_stackPos) { | 150 operation, addr, opt_stackPos) { |
149 var op = Profile.Operation; | 151 var op = Profile.Operation; |
150 switch (operation) { | 152 switch (operation) { |
151 case op.MOVE: | 153 case op.MOVE: |
152 print('Code move event for unknown code: 0x' + addr.toString(16)); | 154 printErr('Code move event for unknown code: 0x' + addr.toString(16)); |
153 break; | 155 break; |
154 case op.DELETE: | 156 case op.DELETE: |
155 print('Code delete event for unknown code: 0x' + addr.toString(16)); | 157 printErr('Code delete event for unknown code: 0x' + addr.toString(16)); |
156 break; | 158 break; |
157 case op.TICK: | 159 case op.TICK: |
158 // Only unknown PCs (the first frame) are reported as unaccounted, | 160 // Only unknown PCs (the first frame) are reported as unaccounted, |
159 // otherwise tick balance will be corrupted (this behavior is compatible | 161 // otherwise tick balance will be corrupted (this behavior is compatible |
160 // with the original tickprocessor.py script.) | 162 // with the original tickprocessor.py script.) |
161 if (opt_stackPos == 0) { | 163 if (opt_stackPos == 0) { |
162 ticks.unaccounted++; | 164 ticks.unaccounted++; |
163 } | 165 } |
164 break; | 166 break; |
165 } | 167 } |
166 }; | 168 }; |
167 | 169 |
168 this.profile_ = new V8Profile(separateIc); | 170 if (preprocessJson) { |
| 171 this.profile_ = new JsonProfile(); |
| 172 } else { |
| 173 this.profile_ = new V8Profile(separateIc); |
| 174 } |
169 this.codeTypes_ = {}; | 175 this.codeTypes_ = {}; |
170 // Count each tick as a time unit. | 176 // Count each tick as a time unit. |
171 this.viewBuilder_ = new ViewBuilder(1); | 177 this.viewBuilder_ = new ViewBuilder(1); |
172 this.lastLogFileName_ = null; | 178 this.lastLogFileName_ = null; |
173 | 179 |
174 this.generation_ = 1; | 180 this.generation_ = 1; |
175 this.currentProducerProfile_ = null; | 181 this.currentProducerProfile_ = null; |
176 this.onlySummary_ = onlySummary; | 182 this.onlySummary_ = onlySummary; |
177 }; | 183 }; |
178 inherits(TickProcessor, LogReader); | 184 inherits(TickProcessor, LogReader); |
(...skipping 18 matching lines...) Expand all Loading... |
197 | 203 |
198 | 204 |
199 TickProcessor.CALL_PROFILE_CUTOFF_PCT = 2.0; | 205 TickProcessor.CALL_PROFILE_CUTOFF_PCT = 2.0; |
200 | 206 |
201 TickProcessor.CALL_GRAPH_SIZE = 5; | 207 TickProcessor.CALL_GRAPH_SIZE = 5; |
202 | 208 |
203 /** | 209 /** |
204 * @override | 210 * @override |
205 */ | 211 */ |
206 TickProcessor.prototype.printError = function(str) { | 212 TickProcessor.prototype.printError = function(str) { |
207 print(str); | 213 printErr(str); |
208 }; | 214 }; |
209 | 215 |
210 | 216 |
211 TickProcessor.prototype.setCodeType = function(name, type) { | 217 TickProcessor.prototype.setCodeType = function(name, type) { |
212 this.codeTypes_[name] = TickProcessor.CodeTypes[type]; | 218 this.codeTypes_[name] = TickProcessor.CodeTypes[type]; |
213 }; | 219 }; |
214 | 220 |
215 | 221 |
216 TickProcessor.prototype.isSharedLibrary = function(name) { | 222 TickProcessor.prototype.isSharedLibrary = function(name) { |
217 return this.codeTypes_[name] == TickProcessor.CodeTypes.SHARED_LIB; | 223 return this.codeTypes_[name] == TickProcessor.CodeTypes.SHARED_LIB; |
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
326 tos_or_external_callback = 0; | 332 tos_or_external_callback = 0; |
327 } else if (tos_or_external_callback) { | 333 } else if (tos_or_external_callback) { |
328 // Find out, if top of stack was pointing inside a JS function | 334 // Find out, if top of stack was pointing inside a JS function |
329 // meaning that we have encountered a frameless invocation. | 335 // meaning that we have encountered a frameless invocation. |
330 var funcEntry = this.profile_.findEntry(tos_or_external_callback); | 336 var funcEntry = this.profile_.findEntry(tos_or_external_callback); |
331 if (!funcEntry || !funcEntry.isJSFunction || !funcEntry.isJSFunction()) { | 337 if (!funcEntry || !funcEntry.isJSFunction || !funcEntry.isJSFunction()) { |
332 tos_or_external_callback = 0; | 338 tos_or_external_callback = 0; |
333 } | 339 } |
334 } | 340 } |
335 | 341 |
336 this.profile_.recordTick(this.processStack(pc, tos_or_external_callback, stack
)); | 342 this.profile_.recordTick( |
| 343 ns_since_start, vmState, |
| 344 this.processStack(pc, tos_or_external_callback, stack)); |
337 }; | 345 }; |
338 | 346 |
339 | 347 |
340 TickProcessor.prototype.advanceDistortion = function() { | 348 TickProcessor.prototype.advanceDistortion = function() { |
341 this.distortion += this.distortion_per_entry; | 349 this.distortion += this.distortion_per_entry; |
342 } | 350 } |
343 | 351 |
344 | 352 |
345 TickProcessor.prototype.processHeapSampleBegin = function(space, state, ticks) { | 353 TickProcessor.prototype.processHeapSampleBegin = function(space, state, ticks) { |
346 if (space != 'Heap') return; | 354 if (space != 'Heap') return; |
(...skipping 13 matching lines...) Expand all Loading... |
360 return rec2.totalTime - rec1.totalTime || | 368 return rec2.totalTime - rec1.totalTime || |
361 (rec2.internalFuncName < rec1.internalFuncName ? -1 : 1); }); | 369 (rec2.internalFuncName < rec1.internalFuncName ? -1 : 1); }); |
362 this.printHeavyProfile(producersView.head.children); | 370 this.printHeavyProfile(producersView.head.children); |
363 | 371 |
364 this.currentProducerProfile_ = null; | 372 this.currentProducerProfile_ = null; |
365 this.generation_++; | 373 this.generation_++; |
366 }; | 374 }; |
367 | 375 |
368 | 376 |
369 TickProcessor.prototype.printStatistics = function() { | 377 TickProcessor.prototype.printStatistics = function() { |
| 378 if (this.preprocessJson) { |
| 379 this.profile_.writeJson(); |
| 380 return; |
| 381 } |
| 382 |
370 print('Statistical profiling result from ' + this.lastLogFileName_ + | 383 print('Statistical profiling result from ' + this.lastLogFileName_ + |
371 ', (' + this.ticks_.total + | 384 ', (' + this.ticks_.total + |
372 ' ticks, ' + this.ticks_.unaccounted + ' unaccounted, ' + | 385 ' ticks, ' + this.ticks_.unaccounted + ' unaccounted, ' + |
373 this.ticks_.excluded + ' excluded).'); | 386 this.ticks_.excluded + ' excluded).'); |
374 | 387 |
375 if (this.ticks_.total == 0) return; | 388 if (this.ticks_.total == 0) return; |
376 | 389 |
377 var flatProfile = this.profile_.getFlatProfile(); | 390 var flatProfile = this.profile_.getFlatProfile(); |
378 var flatView = this.viewBuilder_.buildView(flatProfile); | 391 var flatView = this.viewBuilder_.buildView(flatProfile); |
379 // Sort by self time, desc, then by name, desc. | 392 // Sort by self time, desc, then by name, desc. |
(...skipping 289 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
669 funcInfo.size = parseInt(fields[2], 16); | 682 funcInfo.size = parseInt(fields[2], 16); |
670 } | 683 } |
671 } | 684 } |
672 return funcInfo; | 685 return funcInfo; |
673 }; | 686 }; |
674 | 687 |
675 | 688 |
676 function MacCppEntriesProvider(nmExec, targetRootFS) { | 689 function MacCppEntriesProvider(nmExec, targetRootFS) { |
677 UnixCppEntriesProvider.call(this, nmExec, targetRootFS); | 690 UnixCppEntriesProvider.call(this, nmExec, targetRootFS); |
678 // Note an empty group. It is required, as UnixCppEntriesProvider expects 3 gr
oups. | 691 // Note an empty group. It is required, as UnixCppEntriesProvider expects 3 gr
oups. |
679 this.FUNC_RE = /^([0-9a-fA-F]{8,16}) ()[iItT] (.*)$/; | 692 this.FUNC_RE = /^([0-9a-fA-F]{8,16})() (.*)$/; |
680 }; | 693 }; |
681 inherits(MacCppEntriesProvider, UnixCppEntriesProvider); | 694 inherits(MacCppEntriesProvider, UnixCppEntriesProvider); |
682 | 695 |
683 | 696 |
684 MacCppEntriesProvider.prototype.loadSymbols = function(libName) { | 697 MacCppEntriesProvider.prototype.loadSymbols = function(libName) { |
685 this.parsePos = 0; | 698 this.parsePos = 0; |
686 libName = this.targetRootFS + libName; | 699 libName = this.targetRootFS + libName; |
687 | 700 |
688 // It seems that in OS X `nm` thinks that `-f` is a format option, not a | 701 // It seems that in OS X `nm` thinks that `-f` is a format option, not a |
689 // "flat" display option flag. | 702 // "flat" display option flag. |
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
816 'Specify the range limit as [start],[end]'], | 829 'Specify the range limit as [start],[end]'], |
817 '--distortion': ['distortion', 0, | 830 '--distortion': ['distortion', 0, |
818 'Specify the logging overhead in picoseconds'], | 831 'Specify the logging overhead in picoseconds'], |
819 '--source-map': ['sourceMap', null, | 832 '--source-map': ['sourceMap', null, |
820 'Specify the source map that should be used for output'], | 833 'Specify the source map that should be used for output'], |
821 '--timed-range': ['timedRange', true, | 834 '--timed-range': ['timedRange', true, |
822 'Ignore ticks before first and after last Date.now() call'], | 835 'Ignore ticks before first and after last Date.now() call'], |
823 '--pairwise-timed-range': ['pairwiseTimedRange', true, | 836 '--pairwise-timed-range': ['pairwiseTimedRange', true, |
824 'Ignore ticks outside pairs of Date.now() calls'], | 837 'Ignore ticks outside pairs of Date.now() calls'], |
825 '--only-summary': ['onlySummary', true, | 838 '--only-summary': ['onlySummary', true, |
826 'Print only tick summary, exclude other information'] | 839 'Print only tick summary, exclude other information'], |
| 840 '--preprocess': ['preprocessJson', true, |
| 841 'Preprocess for consumption with web interface'] |
827 }; | 842 }; |
828 this.argsDispatch_['--js'] = this.argsDispatch_['-j']; | 843 this.argsDispatch_['--js'] = this.argsDispatch_['-j']; |
829 this.argsDispatch_['--gc'] = this.argsDispatch_['-g']; | 844 this.argsDispatch_['--gc'] = this.argsDispatch_['-g']; |
830 this.argsDispatch_['--compiler'] = this.argsDispatch_['-c']; | 845 this.argsDispatch_['--compiler'] = this.argsDispatch_['-c']; |
831 this.argsDispatch_['--other'] = this.argsDispatch_['-o']; | 846 this.argsDispatch_['--other'] = this.argsDispatch_['-o']; |
832 this.argsDispatch_['--external'] = this.argsDispatch_['-e']; | 847 this.argsDispatch_['--external'] = this.argsDispatch_['-e']; |
833 this.argsDispatch_['--ptr'] = this.argsDispatch_['--pairwise-timed-range']; | 848 this.argsDispatch_['--ptr'] = this.argsDispatch_['--pairwise-timed-range']; |
834 }; | 849 }; |
835 | 850 |
836 | 851 |
837 ArgumentsProcessor.DEFAULTS = { | 852 ArgumentsProcessor.DEFAULTS = { |
838 logFileName: 'v8.log', | 853 logFileName: 'v8.log', |
839 platform: 'unix', | 854 platform: 'unix', |
840 stateFilter: null, | 855 stateFilter: null, |
841 callGraphSize: 5, | 856 callGraphSize: 5, |
842 ignoreUnknown: false, | 857 ignoreUnknown: false, |
843 separateIc: false, | 858 separateIc: false, |
| 859 preprocessJson: null, |
844 targetRootFS: '', | 860 targetRootFS: '', |
845 nm: 'nm', | 861 nm: 'nm', |
846 range: 'auto,auto', | 862 range: 'auto,auto', |
847 distortion: 0, | 863 distortion: 0, |
848 timedRange: false, | 864 timedRange: false, |
849 pairwiseTimedRange: false, | 865 pairwiseTimedRange: false, |
850 onlySummary: false, | 866 onlySummary: false, |
851 runtimeTimerFilter: null, | 867 runtimeTimerFilter: null, |
852 }; | 868 }; |
853 | 869 |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
901 for (var synArg in this.argsDispatch_) { | 917 for (var synArg in this.argsDispatch_) { |
902 if (arg !== synArg && dispatch === this.argsDispatch_[synArg]) { | 918 if (arg !== synArg && dispatch === this.argsDispatch_[synArg]) { |
903 synonyms.push(synArg); | 919 synonyms.push(synArg); |
904 delete this.argsDispatch_[synArg]; | 920 delete this.argsDispatch_[synArg]; |
905 } | 921 } |
906 } | 922 } |
907 print(' ' + padRight(synonyms.join(', '), 20) + " " + dispatch[2]); | 923 print(' ' + padRight(synonyms.join(', '), 20) + " " + dispatch[2]); |
908 } | 924 } |
909 quit(2); | 925 quit(2); |
910 }; | 926 }; |
OLD | NEW |