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

Side by Side Diff: tools/sodium/sodium.js

Issue 24957003: Add tool to visualize machine code/lithium. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Final polish before review Created 7 years, 2 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
OLDNEW
(Empty)
1 // Copyright 2013 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are
4 // met:
5 //
6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided
11 // with the distribution.
12 // * Neither the name of Google Inc. nor the names of its
13 // contributors may be used to endorse or promote products derived
14 // from this software without specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
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.
27
28 var Sodium = (function() {
29 "use strict";
30
31 var kinds = ["FUNCTION", "OPTIMIZED_FUNCTION", "STUB", "BUILTIN",
32 "LOAD_IC", "KEYED_LOAD_IC", "CALL_IC", "KEYED_CALL_IC",
33 "STORE_IC", "KEYED_STORE_IC", "BINARY_OP_IC", "COMPARE_IC",
34 "COMPARE_NIL_IC", "TO_BOOLEAN_IC"];
35 var kindsWithSource = {
36 'FUNCTION': true,
37 'OPTIMIZED_FUNCTION': true
38 };
39
40 var addressRegEx = "0x[0-9a-f]{8,16}";
41 var nameFinder = new RegExp("^name = (.+)$");
42 var kindFinder = new RegExp("^kind = (.+)$");
43 var firstPositionFinder = new RegExp("^source_position = (\\d+)$");
44 var separatorFilter = new RegExp("^--- (.)+ ---$");
45 var rawSourceFilter = new RegExp("^--- Raw source ---$");
46 var codeEndFinder = new RegExp("^--- End code ---$");
47 var whiteSpaceLineFinder = new RegExp("^\\W*$");
48 var instructionBeginFinder =
49 new RegExp("^Instructions\\W+\\(size = \\d+\\)");
50 var instructionFinder =
51 new RegExp("^\(" + addressRegEx + "\)\(\\W+\\d+\\W+.+\)");
52 var positionFinder =
53 new RegExp("^(" + addressRegEx + ")\\W+position\\W+\\((\\d+)\\)");
54 var addressFinder = new RegExp("\(" + addressRegEx + "\)");
55 var addressReplacer = new RegExp("\(" + addressRegEx + "\)", "gi");
56
57 var fileContent = "";
58 var selectedFunctionKind = "";
59 var currentFunctionKind = "";
60
61 var currentFunctionName = "";
62 var firstSourcePosition = 0;
63 var startAddress = "";
64 var readingSource = false;
65 var readingAsm = false;
66 var sourceBegin = -1;
67 var sourceEnd = -1;
68 var asmBegin = -1;
69 var asmEnd = -1;
70 var codeObjects = [];
71 var selectedAsm = null;
72 var selectedSource = null;
73 var selectedSourceClass = "";
74
75 function Code(name, kind, sourceBegin, sourceEnd, asmBegin, asmEnd,
76 firstSourcePosition, startAddress) {
77 this.name = name;
78 this.kind = kind;
79 this.sourceBegin = sourceBegin;
80 this.sourceEnd = sourceEnd;
81 this.asmBegin = asmBegin;
82 this.asmEnd = asmEnd;
83 this.firstSourcePosition = firstSourcePosition;
84 this.startAddress = startAddress;
85 }
86
87 function getCurrentCodeObject() {
88 var functionSelect = document.getElementById('function-selector-id');
89 return functionSelect.options[functionSelect.selectedIndex].codeObject;
90 }
91
92 function getCurrentSourceText() {
93 var code = getCurrentCodeObject();
94 if (code.sourceBegin == -1 || code.sourceEnd == -1) return "";
95 return fileContent.substring(code.sourceBegin, code.sourceEnd);
96 }
97
98 function getCurrentAsmText() {
99 var code = getCurrentCodeObject();
100 if (code.asmBegin == -1 || code.asmEnd == -1) return "";
101 return fileContent.substring(code.asmBegin, code.asmEnd);
102 }
103
104 function setKindByIndex(index) {
105 selectedFunctionKind = kinds[index];
106 }
107
108 function processLine(text, begin, end) {
109 var line = text.substring(begin, end);
110 if (readingSource) {
111 if (separatorFilter.exec(line) != null) {
112 readingSource = false;
113 } else {
114 if (sourceBegin == -1) {
115 sourceBegin = begin;
116 }
117 sourceEnd = end;
118 }
119 } else {
120 if (readingAsm) {
121 if (codeEndFinder.exec(line) != null) {
122 readingAsm = false;
123 asmEnd = begin;
124 var newCode =
125 new Code(currentFunctionName, currentFunctionKind,
126 sourceBegin, sourceEnd, asmBegin, asmEnd,
127 firstSourcePosition, startAddress);
128 codeObjects.push(newCode);
129 currentFunctionKind = null;
130 } else {
131 if (asmBegin == -1) {
132 matches = instructionBeginFinder.exec(line);
133 if (matches != null) {
134 asmBegin = begin;
135 }
136 }
137 if (startAddress == "") {
138 matches = instructionFinder.exec(line);
139 if (matches != null) {
140 startAddress = matches[1];
141 }
142 }
143 }
144 } else {
145 var matches = kindFinder.exec(line);
146 if (matches != null) {
147 currentFunctionKind = matches[1];
148 if (!kindsWithSource[currentFunctionKind]) {
149 sourceBegin = -1;
150 sourceEnd = -1;
151 }
152 } else if (currentFunctionKind != null) {
153 matches = nameFinder.exec(line);
154 if (matches != null) {
155 readingAsm = true;
156 asmBegin = -1;
157 currentFunctionName = matches[1];
158 }
159 } else if (rawSourceFilter.exec(line) != null) {
160 readingSource = true;
161 sourceBegin = -1;
162 } else {
163 var matches = firstPositionFinder.exec(line);
164 if (matches != null) {
165 firstSourcePosition = parseInt(matches[1]);
166 }
167 }
168 }
169 }
170 }
171
172 function processLines(source, size, processLine) {
173 var firstChar = 0;
174 for (var x = 0; x < size; x++) {
175 var curChar = source[x];
176 if (curChar == '\n' || curChar == '\r') {
177 processLine(source, firstChar, x);
178 firstChar = x + 1;
179 }
180 }
181 if (firstChar != size - 1) {
182 processLine(source, firstChar, size - 1);
183 }
184 }
185
186 function processFileContent() {
187 var sourceDivElement = document.getElementById('source-text');
188 sourceDivElement.innerHTML = "<pre/>";
189 sourceBegin = -1;
190 codeObjects = [];
191 processLines(fileContent, fileContent.length, processLine);
192 var functionSelectElement = document.getElementById('function-selector-id');
193 functionSelectElement.innerHTML =
194 "<select id=\"function-selector-id\"></select>";
195 var length = codeObjects.length;
196 for (var i = 0; i < codeObjects.length; ++i) {
197 var code = codeObjects[i];
198 if (code.kind == selectedFunctionKind) {
199 var optionElement = document.createElement("option");
200 optionElement.codeObject = code;
201 optionElement.text = code.name;
202 functionSelectElement.add(optionElement, null);
203 }
204 }
205 }
206
207 function asmClick(element) {
208 if (element == selectedAsm) return;
209 if (selectedAsm != null) {
210 selectedAsm.classList.remove('highlight-yellow');
211 }
212 selectedAsm = element;
213 selectedAsm.classList.add('highlight-yellow');
214
215 var pc = element.firstChild.innerText;
216 var sourceLine = null;
217 if (addressFinder.exec(pc) != null) {
218 var position = findSourcePosition(pc);
219 var line = findSourceLine(position);
220 sourceLine = document.getElementById('source-line-' + line);
221 var sourceLineTop = sourceLine.offsetTop;
222 makeSourcePosVisible(sourceLineTop);
223 }
224 if (selectedSource == sourceLine) return;
225 if (selectedSource != null) {
226 selectedSource.classList.remove('highlight-yellow');
227 selectedSource.classList.add(selectedSourceClass);
228 }
229 if (sourceLine != null) {
230 selectedSourceClass = sourceLine.classList[0];
231 sourceLine.classList.remove(selectedSourceClass);
232 sourceLine.classList.add('highlight-yellow');
233 }
234 selectedSource = sourceLine;
235 }
236
237 function makeContainerPosVisible(container, newTop) {
238 var height = container.offsetHeight;
239 var margin = Math.floor(height / 4);
240 if (newTop < container.scrollTop + margin) {
241 newTop -= margin;
242 if (newTop < 0) newTop = 0;
243 container.scrollTop = newTop;
244 return;
245 }
246 if (newTop > (container.scrollTop + 3 * margin)) {
247 newTop = newTop - 3 * margin;
248 container.scrollTop = newTop;
249 }
250 }
251
252 function makeAsmPosVisible(newTop) {
253 var asmContainer = document.getElementById('asm-container');
254 makeContainerPosVisible(asmContainer, newTop);
255 }
256
257 function makeSourcePosVisible(newTop) {
258 var sourceContainer = document.getElementById('source-container');
259 makeContainerPosVisible(sourceContainer, newTop);
260 }
261
262 function addressClick(element, event) {
263 event.stopPropagation();
264 var asmLineId = 'address-' + element.innerText;
265 var asmLineElement = document.getElementById(asmLineId);
266 if (asmLineElement != null) {
267 var asmLineTop = asmLineElement.parentNode.offsetTop;
268 makeAsmPosVisible(asmLineTop);
269 asmLineElement.classList.add('highlight-flash-blue');
270 window.setTimeout(function() {
271 asmLineElement.classList.remove('highlight-flash-blue');
272 }, 1500);
273 }
274 }
275
276 function prepareAsm(originalSource) {
277 var newSource = "";
278 var lineNumber = 1;
279 var functionProcessLine = function(text, begin, end) {
280 var currentLine = text.substring(begin, end);
281 var matches = instructionFinder.exec(currentLine);
282 var clickHandler = "";
283 if (matches != null) {
284 var restOfLine = matches[2];
285 restOfLine = restOfLine.replace(
286 addressReplacer,
287 '<span class="hover-underline" ' +
288 'onclick="Sodium.addressClick(this, event);">\$1</span>');
289 currentLine = '<span id="address-' + matches[1] + '" >' +
290 matches[1] + '</span>' + restOfLine;
291 clickHandler = 'onclick=\'Sodium.asmClick(this)\' ';
292 } else if (whiteSpaceLineFinder.exec(currentLine)) {
293 currentLine = "<br>";
294 }
295 newSource += '<pre style=\'margin-bottom: -12px;\' ' + clickHandler + '>' +
296 currentLine + '</pre>';
297 lineNumber++;
298 }
299 processLines(originalSource, originalSource.length, functionProcessLine);
300 return newSource;
301 }
302
303 function findSourcePosition(pcToSearch) {
304 var position = 0;
305 var distance = 0x7FFFFFFF;
306 var pcToSearchOffset = parseInt(pcToSearch);
307 var processOneLine = function(text, begin, end) {
308 var currentLine = text.substring(begin, end);
309 var matches = positionFinder.exec(currentLine);
310 if (matches != null) {
311 var pcOffset = parseInt(matches[1]);
312 if (pcOffset <= pcToSearchOffset) {
313 var dist = pcToSearchOffset - pcOffset;
314 var pos = parseInt(matches[2]);
315 if ((dist < distance) || (dist == distance && pos > position)) {
316 position = pos;
317 distance = dist;
318 }
319 }
320 }
321 }
322 var asmText = getCurrentAsmText();
323 processLines(asmText, asmText.length, processOneLine);
324 var code = getCurrentCodeObject();
325 if (position == 0) return 0;
326 return position - code.firstSourcePosition;
327 }
328
329 function findSourceLine(position) {
330 if (position == 0) return 1;
331 var line = 0;
332 var processOneLine = function(text, begin, end) {
333 if (begin < position) {
334 line++;
335 }
336 }
337 var sourceText = getCurrentSourceText();
338 processLines(sourceText, sourceText.length, processOneLine);
339 return line;
340 }
341
342 function functionChangedHandler() {
343 var functionSelect = document.getElementById('function-selector-id');
344 var source = getCurrentSourceText();
345 var sourceDivElement = document.getElementById('source-text');
346 var code = getCurrentCodeObject();
347 var newHtml = "<pre class=\"prettyprint linenums\" id=\"source-text\">" +
348 + 'function ' + code.name + source + "</pre>";
349 sourceDivElement.innerHTML = newHtml;
350 try {
351 // Wrap in try to work when offline.
352 PR.prettyPrint();
353 } catch (e) {
354 }
355 var sourceLineContainer = sourceDivElement.firstChild.firstChild;
356 var lineCount = sourceLineContainer.childElementCount;
357 var current = sourceLineContainer.firstChild;
358 for (var i = 1; i < lineCount; ++i) {
359 current.id = "source-line-" + i;
360 current = current.nextElementSibling;
361 }
362
363 var asmDivElement = document.getElementById('asm-container');
364 var asm = getCurrentAsmText();
365 newHtml = prepareAsm(asm);
366 asmDivElement.innerHTML = '<div id=\"asm-text\">' + newHtml + '</div>';
Dmitry Lomov (no reviews) 2013/10/18 16:07:53 Use createElement here
danno 2013/10/19 17:11:40 Done.
367 }
368
369 function kindChangedHandler(element) {
370 setKindByIndex(element.selectedIndex);
371 processFileContent();
372 functionChangedHandler();
373 }
374
375 function readLog(evt) {
376 //Retrieve the first (and only!) File from the FileList object
377 var f = evt.target.files[0];
378 if (f) {
379 var r = new FileReader();
380 r.onload = function(e) {
381 var file = evt.target.files[0];
382 currentFunctionKind = "";
383 fileContent = e.target.result;
384 processFileContent();
385 functionChangedHandler();
386 }
387 r.readAsText(f);
388 } else {
389 alert("Failed to load file");
390 }
391 }
392
393 function buildFunctionKindSelector() {
394 document.getElementById('log-file-id').addEventListener('change',
Dmitry Lomov (no reviews) 2013/10/18 16:07:53 Consider replacing getElementById with parameters
danno 2013/10/19 17:11:40 Done.
395 readLog, false);
396 var kindSelectElement = document.getElementById('kind-selector-id');
397 for (var x = 0; x < kinds.length; ++x) {
398 var optionElement = document.createElement("option");
399 optionElement.value = x;
400 optionElement.text = kinds[x];
401 kindSelectElement.add(optionElement, null);
402 }
403 kindSelectElement.selectedIndex = 1;
404 setKindByIndex(1);
405 }
406
407 return {
408 buildFunctionKindSelector: buildFunctionKindSelector,
409 kindChangedHandler: kindChangedHandler,
410 functionChangedHandler: functionChangedHandler,
411 asmClick: asmClick,
412 addressClick: addressClick
413 };
414
415 })();
OLDNEW
« tools/sodium/index.html ('K') | « tools/sodium/index.html ('k') | tools/sodium/styles.css » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698