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

Side by Side Diff: tools/tickprocessor.js

Issue 22897021: Add source map support to tick processor. (Closed) Base URL: git://github.com/v8/v8.git@master
Patch Set: Created 7 years, 4 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
« no previous file with comments | « src/log.cc ('k') | tools/tickprocessor-driver.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 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 12 matching lines...) Expand all
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 function inherits(childCtor, parentCtor) { 29 function inherits(childCtor, parentCtor) {
30 childCtor.prototype.__proto__ = parentCtor.prototype; 30 childCtor.prototype.__proto__ = parentCtor.prototype;
31 }; 31 };
32 32
33
Jakob Kummerow 2013/08/23 13:08:35 nit: leave this line in please.
Daniel Kurka 2013/08/23 13:31:43 Done.
34 function V8Profile(separateIc) { 33 function V8Profile(separateIc) {
35 Profile.call(this); 34 Profile.call(this);
36 if (!separateIc) { 35 if (!separateIc) {
37 this.skipThisFunction = function(name) { return V8Profile.IC_RE.test(name); }; 36 this.skipThisFunction = function(name) { return V8Profile.IC_RE.test(name); };
38 } 37 }
39 }; 38 };
40 inherits(V8Profile, Profile); 39 inherits(V8Profile, Profile);
41 40
42 41
43 V8Profile.IC_RE = 42 V8Profile.IC_RE =
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
146 145
147 146
148 function TickProcessor( 147 function TickProcessor(
149 cppEntriesProvider, 148 cppEntriesProvider,
150 separateIc, 149 separateIc,
151 callGraphSize, 150 callGraphSize,
152 ignoreUnknown, 151 ignoreUnknown,
153 stateFilter, 152 stateFilter,
154 snapshotLogProcessor, 153 snapshotLogProcessor,
155 distortion, 154 distortion,
156 range) { 155 range,
156 sourceMap) {
157 LogReader.call(this, { 157 LogReader.call(this, {
158 'shared-library': { parsers: [null, parseInt, parseInt], 158 'shared-library': { parsers: [null, parseInt, parseInt],
159 processor: this.processSharedLibrary }, 159 processor: this.processSharedLibrary },
160 'code-creation': { 160 'code-creation': {
161 parsers: [null, parseInt, parseInt, parseInt, null, 'var-args'], 161 parsers: [null, parseInt, parseInt, parseInt, null, 'var-args'],
162 processor: this.processCodeCreation }, 162 processor: this.processCodeCreation },
163 'code-move': { parsers: [parseInt, parseInt], 163 'code-move': { parsers: [parseInt, parseInt],
164 processor: this.processCodeMove }, 164 processor: this.processCodeMove },
165 'code-delete': { parsers: [parseInt], 165 'code-delete': { parsers: [parseInt],
166 processor: this.processCodeDelete }, 166 processor: this.processCodeDelete },
(...skipping 22 matching lines...) Expand all
189 // Obsolete row types. 189 // Obsolete row types.
190 'code-allocate': null, 190 'code-allocate': null,
191 'begin-code-region': null, 191 'begin-code-region': null,
192 'end-code-region': null }); 192 'end-code-region': null });
193 193
194 this.cppEntriesProvider_ = cppEntriesProvider; 194 this.cppEntriesProvider_ = cppEntriesProvider;
195 this.callGraphSize_ = callGraphSize; 195 this.callGraphSize_ = callGraphSize;
196 this.ignoreUnknown_ = ignoreUnknown; 196 this.ignoreUnknown_ = ignoreUnknown;
197 this.stateFilter_ = stateFilter; 197 this.stateFilter_ = stateFilter;
198 this.snapshotLogProcessor_ = snapshotLogProcessor; 198 this.snapshotLogProcessor_ = snapshotLogProcessor;
199 this.sourceMap = sourceMap;
199 this.deserializedEntriesNames_ = []; 200 this.deserializedEntriesNames_ = [];
200 var ticks = this.ticks_ = 201 var ticks = this.ticks_ =
201 { total: 0, unaccounted: 0, excluded: 0, gc: 0 }; 202 { total: 0, unaccounted: 0, excluded: 0, gc: 0 };
202 203
203 distortion = parseInt(distortion); 204 distortion = parseInt(distortion);
204 // Convert picoseconds to nanoseconds. 205 // Convert picoseconds to nanoseconds.
205 this.distortion_per_entry = isNaN(distortion) ? 0 : (distortion / 1000); 206 this.distortion_per_entry = isNaN(distortion) ? 0 : (distortion / 1000);
206 this.distortion = 0; 207 this.distortion = 0;
207 var rangelimits = range ? range.split(",") : []; 208 var rangelimits = range ? range.split(",") : [];
208 var range_start = parseInt(rangelimits[0]); 209 var range_start = parseInt(rangelimits[0]);
(...skipping 328 matching lines...) Expand 10 before | Expand all | Expand 10 after
537 profile, filterP, func) { 538 profile, filterP, func) {
538 for (var i = 0, n = profile.length; i < n; ++i) { 539 for (var i = 0, n = profile.length; i < n; ++i) {
539 var rec = profile[i]; 540 var rec = profile[i];
540 if (!filterP(rec.internalFuncName)) { 541 if (!filterP(rec.internalFuncName)) {
541 continue; 542 continue;
542 } 543 }
543 func(rec); 544 func(rec);
544 } 545 }
545 }; 546 };
546 547
548 TickProcessor.prototype.getLineAndColumn = function(name) {
549 var re = /:([0-9]+):([0-9]+)$/;
550 var array = re.exec(name);
551 if (!array) {
552 return null;
Jakob Kummerow 2013/08/23 13:08:35 nit: indentation
Daniel Kurka 2013/08/23 13:31:43 Done.
553 }
554 return {line: array[1], column: array[2]};
555 }
556
557 TickProcessor.prototype.hasSourceMap = function() {
558 return this.sourceMap != null;
559 };
560
561
562 TickProcessor.prototype.formatFunctionName = function(funcName) {
563 if (!this.hasSourceMap()) {
564 return funcName;
565 }
566 var lc = this.getLineAndColumn(funcName);
567 if (lc == null) {
568 return funcName;
569 }
570 // in source maps lines and columns are zero based
571 var lineNumber = lc.line - 1;
572 var column = lc.column - 1;
573 var entry = this.sourceMap.findEntry(lineNumber, column);
574 var sourceFile = entry[2];
575 var sourceLine = entry[3] + 1;
576 var sourceColumn = entry[4] + 1;
577
578 return sourceFile + ':' + sourceLine + ':' + sourceColumn + ' -> ' + funcName;
579 };
547 580
548 TickProcessor.prototype.printEntries = function( 581 TickProcessor.prototype.printEntries = function(
549 profile, nonLibTicks, filterP) { 582 profile, nonLibTicks, filterP) {
583 var that = this;
550 this.processProfile(profile, filterP, function (rec) { 584 this.processProfile(profile, filterP, function (rec) {
551 if (rec.selfTime == 0) return; 585 if (rec.selfTime == 0) return;
552 var nonLibPct = nonLibTicks != null ? 586 var nonLibPct = nonLibTicks != null ?
553 rec.selfTime * 100.0 / nonLibTicks : 0.0; 587 rec.selfTime * 100.0 / nonLibTicks : 0.0;
588 var funcName = that.formatFunctionName(rec.internalFuncName);
589
554 print(' ' + padLeft(rec.selfTime, 5) + ' ' + 590 print(' ' + padLeft(rec.selfTime, 5) + ' ' +
555 padLeft(rec.selfPercent.toFixed(1), 5) + '% ' + 591 padLeft(rec.selfPercent.toFixed(1), 5) + '% ' +
556 padLeft(nonLibPct.toFixed(1), 5) + '% ' + 592 padLeft(nonLibPct.toFixed(1), 5) + '% ' +
557 rec.internalFuncName); 593 funcName);
558 }); 594 });
559 }; 595 };
560 596
561 597
562 TickProcessor.prototype.printHeavyProfile = function(profile, opt_indent) { 598 TickProcessor.prototype.printHeavyProfile = function(profile, opt_indent) {
563 var self = this; 599 var self = this;
564 var indent = opt_indent || 0; 600 var indent = opt_indent || 0;
565 var indentStr = padLeft('', indent); 601 var indentStr = padLeft('', indent);
566 this.processProfile(profile, function() { return true; }, function (rec) { 602 this.processProfile(profile, function() { return true; }, function (rec) {
567 // Cut off too infrequent callers. 603 // Cut off too infrequent callers.
568 if (rec.parentTotalPercent < TickProcessor.CALL_PROFILE_CUTOFF_PCT) return; 604 if (rec.parentTotalPercent < TickProcessor.CALL_PROFILE_CUTOFF_PCT) return;
605 var funcName = self.formatFunctionName(rec.internalFuncName);
569 print(' ' + padLeft(rec.totalTime, 5) + ' ' + 606 print(' ' + padLeft(rec.totalTime, 5) + ' ' +
570 padLeft(rec.parentTotalPercent.toFixed(1), 5) + '% ' + 607 padLeft(rec.parentTotalPercent.toFixed(1), 5) + '% ' +
571 indentStr + rec.internalFuncName); 608 indentStr + funcName);
572 // Limit backtrace depth. 609 // Limit backtrace depth.
573 if (indent < 2 * self.callGraphSize_) { 610 if (indent < 2 * self.callGraphSize_) {
574 self.printHeavyProfile(rec.children, indent + 2); 611 self.printHeavyProfile(rec.children, indent + 2);
575 } 612 }
576 // Delimit top-level functions. 613 // Delimit top-level functions.
577 if (indent == 0) { 614 if (indent == 0) {
578 print(''); 615 print('');
579 } 616 }
580 }); 617 });
581 }; 618 };
(...skipping 236 matching lines...) Expand 10 before | Expand all | Expand 10 after
818 'Specify that we are running on Mac OS X platform'], 855 'Specify that we are running on Mac OS X platform'],
819 '--nm': ['nm', 'nm', 856 '--nm': ['nm', 'nm',
820 'Specify the \'nm\' executable to use (e.g. --nm=/my_dir/nm)'], 857 'Specify the \'nm\' executable to use (e.g. --nm=/my_dir/nm)'],
821 '--target': ['targetRootFS', '', 858 '--target': ['targetRootFS', '',
822 'Specify the target root directory for cross environment'], 859 'Specify the target root directory for cross environment'],
823 '--snapshot-log': ['snapshotLogFileName', 'snapshot.log', 860 '--snapshot-log': ['snapshotLogFileName', 'snapshot.log',
824 'Specify snapshot log file to use (e.g. --snapshot-log=snapshot.log)'], 861 'Specify snapshot log file to use (e.g. --snapshot-log=snapshot.log)'],
825 '--range': ['range', 'auto,auto', 862 '--range': ['range', 'auto,auto',
826 'Specify the range limit as [start],[end]'], 863 'Specify the range limit as [start],[end]'],
827 '--distortion': ['distortion', 0, 864 '--distortion': ['distortion', 0,
828 'Specify the logging overhead in picoseconds'] 865 'Specify the logging overhead in picoseconds'],
866 '--sourceMap': ['sourceMap', null,
Jakob Kummerow 2013/08/23 13:08:35 For consistency with other arg names, let's call t
Daniel Kurka 2013/08/23 13:31:43 Done.
867 'Specify the source map that should be used for output']
Jakob Kummerow 2013/08/23 13:08:35 nit: indentation
Daniel Kurka 2013/08/23 13:31:43 Done.
829 }; 868 };
830 this.argsDispatch_['--js'] = this.argsDispatch_['-j']; 869 this.argsDispatch_['--js'] = this.argsDispatch_['-j'];
831 this.argsDispatch_['--gc'] = this.argsDispatch_['-g']; 870 this.argsDispatch_['--gc'] = this.argsDispatch_['-g'];
832 this.argsDispatch_['--compiler'] = this.argsDispatch_['-c']; 871 this.argsDispatch_['--compiler'] = this.argsDispatch_['-c'];
833 this.argsDispatch_['--other'] = this.argsDispatch_['-o']; 872 this.argsDispatch_['--other'] = this.argsDispatch_['-o'];
834 this.argsDispatch_['--external'] = this.argsDispatch_['-e']; 873 this.argsDispatch_['--external'] = this.argsDispatch_['-e'];
835 }; 874 };
836 875
837 876
838 ArgumentsProcessor.DEFAULTS = { 877 ArgumentsProcessor.DEFAULTS = {
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
904 if (arg !== synArg && dispatch === this.argsDispatch_[synArg]) { 943 if (arg !== synArg && dispatch === this.argsDispatch_[synArg]) {
905 synonims.push(synArg); 944 synonims.push(synArg);
906 delete this.argsDispatch_[synArg]; 945 delete this.argsDispatch_[synArg];
907 } 946 }
908 } 947 }
909 print(' ' + padRight(synonims.join(', '), 20) + dispatch[2]); 948 print(' ' + padRight(synonims.join(', '), 20) + dispatch[2]);
910 } 949 }
911 quit(2); 950 quit(2);
912 }; 951 };
913 952
953
954 /**
955 * Implements Source Map V3 model. See http://code.google.com/p/closure-compiler /wiki/SourceMaps
Jakob Kummerow 2013/08/23 13:08:35 This section looks a lot like http://src.chromium.
Daniel Kurka 2013/08/23 13:31:43 Actually we only need a modified load method The
956 * for format description.
957 * @constructor
958 * @param {string} sourceMappingURL
959 * @param {SourceMapV3} payload
960 */
961 SourceMap = function(sourceMappingURL, payload)
962 {
963 if (!SourceMap.prototype._base64Map) {
964 const base64Digits = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwx yz0123456789+/";
965 SourceMap.prototype._base64Map = {};
966 for (var i = 0; i < base64Digits.length; ++i)
967 SourceMap.prototype._base64Map[base64Digits.charAt(i)] = i;
968 }
969
970 this._sourceMappingURL = sourceMappingURL;
971 this._reverseMappingsBySourceURL = {};
972 this._mappings = [];
973 this._sources = {};
974 this._sourceContentByURL = {};
975 this._parseMappingPayload(payload);
976 }
977
978 /**
979 * @param {string} sourceMapURL
980 */
981 SourceMap.load = function(sourceMapURL)
982 {
983 var content = readFile(sourceMapURL);
984 var sourceMapObject = /** @type {SourceMapV3} */ (JSON.parse(content));
985 return new SourceMap(sourceMapURL, sourceMapObject);
986 }
987
988 SourceMap.prototype = {
989 /**
990 * @return {Array.<string>}
991 */
992 sources: function()
993 {
994 return Object.keys(this._sources);
995 },
996
997 /**
998 * @param {SourceMapV3} mappingPayload
999 */
1000 _parseMappingPayload: function(mappingPayload)
1001 {
1002 if (mappingPayload.sections)
1003 this._parseSections(mappingPayload.sections);
1004 else
1005 this._parseMap(mappingPayload, 0, 0);
1006 },
1007
1008 /**
1009 * @param {Array.<SourceMapV3.Section>} sections
1010 */
1011 _parseSections: function(sections)
1012 {
1013 for (var i = 0; i < sections.length; ++i) {
1014 var section = sections[i];
1015 this._parseMap(section.map, section.offset.line, section.offset.colu mn);
1016 }
1017 },
1018
1019 /**
1020 * @param {number} lineNumber in compiled resource
1021 * @param {number} columnNumber in compiled resource
1022 * @return {?Array}
1023 */
1024 findEntry: function(lineNumber, columnNumber)
1025 {
1026 var first = 0;
1027 var count = this._mappings.length;
1028 while (count > 1) {
1029 var step = count >> 1;
1030 var middle = first + step;
1031 var mapping = this._mappings[middle];
1032 if (lineNumber < mapping[0] || (lineNumber === mapping[0] && columnNum ber < mapping[1]))
1033 count = step;
1034 else {
1035 first = middle;
1036 count -= step;
1037 }
1038 }
1039 var entry = this._mappings[first];
1040 if (!first && entry && (lineNumber < entry[0] || (lineNumber === entry[0 ] && columnNumber < entry[1])))
1041 return null;
1042 return entry;
1043 },
1044
1045 /**
1046 * @override
1047 */
1048 _parseMap: function(map, lineNumber, columnNumber)
1049 {
1050 var sourceIndex = 0;
1051 var sourceLineNumber = 0;
1052 var sourceColumnNumber = 0;
1053 var nameIndex = 0;
1054
1055 var sources = [];
1056 var originalToCanonicalURLMap = {};
1057 for (var i = 0; i < map.sources.length; ++i) {
1058 var originalSourceURL = map.sources[i];
1059 var sourceRoot = map.sourceRoot || "";
1060 if (sourceRoot && !sourceRoot.endsWith("/"))
1061 sourceRoot += "/";
1062 var href = sourceRoot + originalSourceURL;
1063 var url = href;
1064 originalToCanonicalURLMap[originalSourceURL] = url;
1065 sources.push(url);
1066 this._sources[url] = true;
1067
1068 if (map.sourcesContent && map.sourcesContent[i])
1069 this._sourceContentByURL[url] = map.sourcesContent[i];
1070 }
1071
1072 var stringCharIterator = new SourceMap.StringCharIterator(map.mappings);
1073 var sourceURL = sources[sourceIndex];
1074
1075 while (true) {
1076 if (stringCharIterator.peek() === ",")
1077 stringCharIterator.next();
1078 else {
1079 while (stringCharIterator.peek() === ";") {
1080 lineNumber += 1;
1081 columnNumber = 0;
1082 stringCharIterator.next();
1083 }
1084 if (!stringCharIterator.hasNext())
1085 break;
1086 }
1087
1088 columnNumber += this._decodeVLQ(stringCharIterator);
1089 if (this._isSeparator(stringCharIterator.peek())) {
1090 this._mappings.push([lineNumber, columnNumber]);
1091 continue;
1092 }
1093
1094 var sourceIndexDelta = this._decodeVLQ(stringCharIterator);
1095 if (sourceIndexDelta) {
1096 sourceIndex += sourceIndexDelta;
1097 sourceURL = sources[sourceIndex];
1098 }
1099 sourceLineNumber += this._decodeVLQ(stringCharIterator);
1100 sourceColumnNumber += this._decodeVLQ(stringCharIterator);
1101 if (!this._isSeparator(stringCharIterator.peek()))
1102 nameIndex += this._decodeVLQ(stringCharIterator);
1103
1104 this._mappings.push([lineNumber, columnNumber, sourceURL, sourceLine Number, sourceColumnNumber]);
1105 }
1106
1107 for (var i = 0; i < this._mappings.length; ++i) {
1108 var mapping = this._mappings[i];
1109 var url = mapping[2];
1110 if (!url)
1111 continue;
1112 if (!this._reverseMappingsBySourceURL[url])
1113 this._reverseMappingsBySourceURL[url] = [];
1114 var reverseMappings = this._reverseMappingsBySourceURL[url];
1115 var sourceLine = mapping[3];
1116 if (!reverseMappings[sourceLine])
1117 reverseMappings[sourceLine] = [mapping[0], mapping[1]];
1118 }
1119 },
1120
1121 /**
1122 * @param {string} char
1123 * @return {boolean}
1124 */
1125 _isSeparator: function(char)
1126 {
1127 return char === "," || char === ";";
1128 },
1129
1130 /**
1131 * @param {SourceMap.StringCharIterator} stringCharIterator
1132 * @return {number}
1133 */
1134 _decodeVLQ: function(stringCharIterator)
1135 {
1136 // Read unsigned value.
1137 var result = 0;
1138 var shift = 0;
1139 do {
1140 var digit = this._base64Map[stringCharIterator.next()];
1141 result += (digit & this._VLQ_BASE_MASK) << shift;
1142 shift += this._VLQ_BASE_SHIFT;
1143 } while (digit & this._VLQ_CONTINUATION_MASK);
1144
1145 // Fix the sign.
1146 var negative = result & 1;
1147 result >>= 1;
1148 return negative ? -result : result;
1149 },
1150
1151 _VLQ_BASE_SHIFT: 5,
1152 _VLQ_BASE_MASK: (1 << 5) - 1,
1153 _VLQ_CONTINUATION_MASK: 1 << 5
1154 }
1155
1156 /**
1157 * @constructor
1158 * @param {string} string
1159 */
1160 SourceMap.StringCharIterator = function(string)
1161 {
1162 this._string = string;
1163 this._position = 0;
1164 }
1165
1166 SourceMap.StringCharIterator.prototype = {
1167 /**
1168 * @return {string}
1169 */
1170 next: function()
1171 {
1172 return this._string.charAt(this._position++);
1173 },
1174
1175 /**
1176 * @return {string}
1177 */
1178 peek: function()
1179 {
1180 return this._string.charAt(this._position);
1181 },
1182
1183 /**
1184 * @return {boolean}
1185 */
1186 hasNext: function()
1187 {
1188 return this._position < this._string.length;
1189 }
1190 }
OLDNEW
« no previous file with comments | « src/log.cc ('k') | tools/tickprocessor-driver.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698