| Index: tools/sodium/sodium.js
|
| diff --git a/tools/sodium/sodium.js b/tools/sodium/sodium.js
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..44475a177f77151e6fddf78438ce03d899e71cc4
|
| --- /dev/null
|
| +++ b/tools/sodium/sodium.js
|
| @@ -0,0 +1,409 @@
|
| +// Copyright 2013 the V8 project authors. All rights reserved.
|
| +// Redistribution and use in source and binary forms, with or without
|
| +// modification, are permitted provided that the following conditions are
|
| +// met:
|
| +//
|
| +// * Redistributions of source code must retain the above copyright
|
| +// notice, this list of conditions and the following disclaimer.
|
| +// * Redistributions in binary form must reproduce the above
|
| +// copyright notice, this list of conditions and the following
|
| +// disclaimer in the documentation and/or other materials provided
|
| +// with the distribution.
|
| +// * Neither the name of Google Inc. nor the names of its
|
| +// contributors may be used to endorse or promote products derived
|
| +// from this software without specific prior written permission.
|
| +//
|
| +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
| +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
| +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
| +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
| +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
| +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
| +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
| +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
| +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
| +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
| +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
| +
|
| +var Sodium = (function() {
|
| + "use strict";
|
| +
|
| + var kinds = ["FUNCTION", "OPTIMIZED_FUNCTION", "STUB", "BUILTIN",
|
| + "LOAD_IC", "KEYED_LOAD_IC", "CALL_IC", "KEYED_CALL_IC",
|
| + "STORE_IC", "KEYED_STORE_IC", "BINARY_OP_IC", "COMPARE_IC",
|
| + "COMPARE_NIL_IC", "TO_BOOLEAN_IC"];
|
| + var kindsWithSource = {
|
| + 'FUNCTION': true,
|
| + 'OPTIMIZED_FUNCTION': true
|
| + };
|
| +
|
| + var addressRegEx = "0x[0-9a-f]{8,16}";
|
| + var nameFinder = new RegExp("^name = (.+)$");
|
| + var kindFinder = new RegExp("^kind = (.+)$");
|
| + var firstPositionFinder = new RegExp("^source_position = (\\d+)$");
|
| + var separatorFilter = new RegExp("^--- (.)+ ---$");
|
| + var rawSourceFilter = new RegExp("^--- Raw source ---$");
|
| + var codeEndFinder = new RegExp("^--- End code ---$");
|
| + var whiteSpaceLineFinder = new RegExp("^\\W*$");
|
| + var instructionBeginFinder =
|
| + new RegExp("^Instructions\\W+\\(size = \\d+\\)");
|
| + var instructionFinder =
|
| + new RegExp("^\(" + addressRegEx + "\)\(\\W+\\d+\\W+.+\)");
|
| + var positionFinder =
|
| + new RegExp("^(" + addressRegEx + ")\\W+position\\W+\\((\\d+)\\)");
|
| + var addressFinder = new RegExp("\(" + addressRegEx + "\)");
|
| + var addressReplacer = new RegExp("\(" + addressRegEx + "\)", "gi");
|
| +
|
| + var fileContent = "";
|
| + var selectedFunctionKind = "";
|
| + var currentFunctionKind = "";
|
| +
|
| + var currentFunctionName = "";
|
| + var firstSourcePosition = 0;
|
| + var startAddress = "";
|
| + var readingSource = false;
|
| + var readingAsm = false;
|
| + var sourceBegin = -1;
|
| + var sourceEnd = -1;
|
| + var asmBegin = -1;
|
| + var asmEnd = -1;
|
| + var codeObjects = [];
|
| + var selectedAsm = null;
|
| + var selectedSource = null;
|
| + var selectedSourceClass = "";
|
| +
|
| + function Code(name, kind, sourceBegin, sourceEnd, asmBegin, asmEnd,
|
| + firstSourcePosition, startAddress) {
|
| + this.name = name;
|
| + this.kind = kind;
|
| + this.sourceBegin = sourceBegin;
|
| + this.sourceEnd = sourceEnd;
|
| + this.asmBegin = asmBegin;
|
| + this.asmEnd = asmEnd;
|
| + this.firstSourcePosition = firstSourcePosition;
|
| + this.startAddress = startAddress;
|
| + }
|
| +
|
| + function getCurrentCodeObject() {
|
| + var functionSelect = document.getElementById('function-selector-id');
|
| + return functionSelect.options[functionSelect.selectedIndex].codeObject;
|
| + }
|
| +
|
| + function getCurrentSourceText() {
|
| + var code = getCurrentCodeObject();
|
| + if (code.sourceBegin == -1 || code.sourceEnd == -1) return "";
|
| + return fileContent.substring(code.sourceBegin, code.sourceEnd);
|
| + }
|
| +
|
| + function getCurrentAsmText() {
|
| + var code = getCurrentCodeObject();
|
| + if (code.asmBegin == -1 || code.asmEnd == -1) return "";
|
| + return fileContent.substring(code.asmBegin, code.asmEnd);
|
| + }
|
| +
|
| + function setKindByIndex(index) {
|
| + selectedFunctionKind = kinds[index];
|
| + }
|
| +
|
| + function processLine(text, begin, end) {
|
| + var line = text.substring(begin, end);
|
| + if (readingSource) {
|
| + if (separatorFilter.exec(line) != null) {
|
| + readingSource = false;
|
| + } else {
|
| + if (sourceBegin == -1) {
|
| + sourceBegin = begin;
|
| + }
|
| + sourceEnd = end;
|
| + }
|
| + } else {
|
| + if (readingAsm) {
|
| + if (codeEndFinder.exec(line) != null) {
|
| + readingAsm = false;
|
| + asmEnd = begin;
|
| + var newCode =
|
| + new Code(currentFunctionName, currentFunctionKind,
|
| + sourceBegin, sourceEnd, asmBegin, asmEnd,
|
| + firstSourcePosition, startAddress);
|
| + codeObjects.push(newCode);
|
| + currentFunctionKind = null;
|
| + } else {
|
| + if (asmBegin == -1) {
|
| + matches = instructionBeginFinder.exec(line);
|
| + if (matches != null) {
|
| + asmBegin = begin;
|
| + }
|
| + }
|
| + if (startAddress == "") {
|
| + matches = instructionFinder.exec(line);
|
| + if (matches != null) {
|
| + startAddress = matches[1];
|
| + }
|
| + }
|
| + }
|
| + } else {
|
| + var matches = kindFinder.exec(line);
|
| + if (matches != null) {
|
| + currentFunctionKind = matches[1];
|
| + if (!kindsWithSource[currentFunctionKind]) {
|
| + sourceBegin = -1;
|
| + sourceEnd = -1;
|
| + }
|
| + } else if (currentFunctionKind != null) {
|
| + matches = nameFinder.exec(line);
|
| + if (matches != null) {
|
| + readingAsm = true;
|
| + asmBegin = -1;
|
| + currentFunctionName = matches[1];
|
| + }
|
| + } else if (rawSourceFilter.exec(line) != null) {
|
| + readingSource = true;
|
| + sourceBegin = -1;
|
| + } else {
|
| + var matches = firstPositionFinder.exec(line);
|
| + if (matches != null) {
|
| + firstSourcePosition = parseInt(matches[1]);
|
| + }
|
| + }
|
| + }
|
| + }
|
| + }
|
| +
|
| + function processLines(source, size, processLine) {
|
| + var firstChar = 0;
|
| + for (var x = 0; x < size; x++) {
|
| + var curChar = source[x];
|
| + if (curChar == '\n' || curChar == '\r') {
|
| + processLine(source, firstChar, x);
|
| + firstChar = x + 1;
|
| + }
|
| + }
|
| + if (firstChar != size - 1) {
|
| + processLine(source, firstChar, size - 1);
|
| + }
|
| + }
|
| +
|
| + function processFileContent() {
|
| + document.getElementById('source-text-pre').innerHTML = '';
|
| + sourceBegin = -1;
|
| + codeObjects = [];
|
| + processLines(fileContent, fileContent.length, processLine);
|
| + var functionSelectElement = document.getElementById('function-selector-id');
|
| + functionSelectElement.innerHTML = '';
|
| + var length = codeObjects.length;
|
| + for (var i = 0; i < codeObjects.length; ++i) {
|
| + var code = codeObjects[i];
|
| + if (code.kind == selectedFunctionKind) {
|
| + var optionElement = document.createElement("option");
|
| + optionElement.codeObject = code;
|
| + optionElement.text = code.name;
|
| + functionSelectElement.add(optionElement, null);
|
| + }
|
| + }
|
| + }
|
| +
|
| + function asmClick(element) {
|
| + if (element == selectedAsm) return;
|
| + if (selectedAsm != null) {
|
| + selectedAsm.classList.remove('highlight-yellow');
|
| + }
|
| + selectedAsm = element;
|
| + selectedAsm.classList.add('highlight-yellow');
|
| +
|
| + var pc = element.firstChild.innerText;
|
| + var sourceLine = null;
|
| + if (addressFinder.exec(pc) != null) {
|
| + var position = findSourcePosition(pc);
|
| + var line = findSourceLine(position);
|
| + sourceLine = document.getElementById('source-line-' + line);
|
| + var sourceLineTop = sourceLine.offsetTop;
|
| + makeSourcePosVisible(sourceLineTop);
|
| + }
|
| + if (selectedSource == sourceLine) return;
|
| + if (selectedSource != null) {
|
| + selectedSource.classList.remove('highlight-yellow');
|
| + selectedSource.classList.add(selectedSourceClass);
|
| + }
|
| + if (sourceLine != null) {
|
| + selectedSourceClass = sourceLine.classList[0];
|
| + sourceLine.classList.remove(selectedSourceClass);
|
| + sourceLine.classList.add('highlight-yellow');
|
| + }
|
| + selectedSource = sourceLine;
|
| + }
|
| +
|
| + function makeContainerPosVisible(container, newTop) {
|
| + var height = container.offsetHeight;
|
| + var margin = Math.floor(height / 4);
|
| + if (newTop < container.scrollTop + margin) {
|
| + newTop -= margin;
|
| + if (newTop < 0) newTop = 0;
|
| + container.scrollTop = newTop;
|
| + return;
|
| + }
|
| + if (newTop > (container.scrollTop + 3 * margin)) {
|
| + newTop = newTop - 3 * margin;
|
| + container.scrollTop = newTop;
|
| + }
|
| + }
|
| +
|
| + function makeAsmPosVisible(newTop) {
|
| + var asmContainer = document.getElementById('asm-container');
|
| + makeContainerPosVisible(asmContainer, newTop);
|
| + }
|
| +
|
| + function makeSourcePosVisible(newTop) {
|
| + var sourceContainer = document.getElementById('source-container');
|
| + makeContainerPosVisible(sourceContainer, newTop);
|
| + }
|
| +
|
| + function addressClick(element, event) {
|
| + event.stopPropagation();
|
| + var asmLineId = 'address-' + element.innerText;
|
| + var asmLineElement = document.getElementById(asmLineId);
|
| + if (asmLineElement != null) {
|
| + var asmLineTop = asmLineElement.parentNode.offsetTop;
|
| + makeAsmPosVisible(asmLineTop);
|
| + asmLineElement.classList.add('highlight-flash-blue');
|
| + window.setTimeout(function() {
|
| + asmLineElement.classList.remove('highlight-flash-blue');
|
| + }, 1500);
|
| + }
|
| + }
|
| +
|
| + function prepareAsm(originalSource) {
|
| + var newSource = "";
|
| + var lineNumber = 1;
|
| + var functionProcessLine = function(text, begin, end) {
|
| + var currentLine = text.substring(begin, end);
|
| + var matches = instructionFinder.exec(currentLine);
|
| + var clickHandler = "";
|
| + if (matches != null) {
|
| + var restOfLine = matches[2];
|
| + restOfLine = restOfLine.replace(
|
| + addressReplacer,
|
| + '<span class="hover-underline" ' +
|
| + 'onclick="Sodium.addressClick(this, event);">\$1</span>');
|
| + currentLine = '<span id="address-' + matches[1] + '" >' +
|
| + matches[1] + '</span>' + restOfLine;
|
| + clickHandler = 'onclick=\'Sodium.asmClick(this)\' ';
|
| + } else if (whiteSpaceLineFinder.exec(currentLine)) {
|
| + currentLine = "<br>";
|
| + }
|
| + newSource += '<pre style=\'margin-bottom: -12px;\' ' + clickHandler + '>' +
|
| + currentLine + '</pre>';
|
| + lineNumber++;
|
| + }
|
| + processLines(originalSource, originalSource.length, functionProcessLine);
|
| + return newSource;
|
| + }
|
| +
|
| + function findSourcePosition(pcToSearch) {
|
| + var position = 0;
|
| + var distance = 0x7FFFFFFF;
|
| + var pcToSearchOffset = parseInt(pcToSearch);
|
| + var processOneLine = function(text, begin, end) {
|
| + var currentLine = text.substring(begin, end);
|
| + var matches = positionFinder.exec(currentLine);
|
| + if (matches != null) {
|
| + var pcOffset = parseInt(matches[1]);
|
| + if (pcOffset <= pcToSearchOffset) {
|
| + var dist = pcToSearchOffset - pcOffset;
|
| + var pos = parseInt(matches[2]);
|
| + if ((dist < distance) || (dist == distance && pos > position)) {
|
| + position = pos;
|
| + distance = dist;
|
| + }
|
| + }
|
| + }
|
| + }
|
| + var asmText = getCurrentAsmText();
|
| + processLines(asmText, asmText.length, processOneLine);
|
| + var code = getCurrentCodeObject();
|
| + if (position == 0) return 0;
|
| + return position - code.firstSourcePosition;
|
| + }
|
| +
|
| + function findSourceLine(position) {
|
| + if (position == 0) return 1;
|
| + var line = 0;
|
| + var processOneLine = function(text, begin, end) {
|
| + if (begin < position) {
|
| + line++;
|
| + }
|
| + }
|
| + var sourceText = getCurrentSourceText();
|
| + processLines(sourceText, sourceText.length, processOneLine);
|
| + return line;
|
| + }
|
| +
|
| + function functionChangedHandler() {
|
| + var functionSelect = document.getElementById('function-selector-id');
|
| + var source = getCurrentSourceText();
|
| + var sourceDivElement = document.getElementById('source-text');
|
| + var code = getCurrentCodeObject();
|
| + var newHtml = "<pre class=\"prettyprint linenums\" id=\"source-text\">"
|
| + + 'function ' + code.name + source + "</pre>";
|
| + sourceDivElement.innerHTML = newHtml;
|
| + try {
|
| + // Wrap in try to work when offline.
|
| + PR.prettyPrint();
|
| + } catch (e) {
|
| + }
|
| + var sourceLineContainer = sourceDivElement.firstChild.firstChild;
|
| + var lineCount = sourceLineContainer.childElementCount;
|
| + var current = sourceLineContainer.firstChild;
|
| + for (var i = 1; i < lineCount; ++i) {
|
| + current.id = "source-line-" + i;
|
| + current = current.nextElementSibling;
|
| + }
|
| +
|
| + var asm = getCurrentAsmText();
|
| + document.getElementById('asm-text').innerHTML = prepareAsm(asm);
|
| + }
|
| +
|
| + function kindChangedHandler(element) {
|
| + setKindByIndex(element.selectedIndex);
|
| + processFileContent();
|
| + functionChangedHandler();
|
| + }
|
| +
|
| + function readLog(evt) {
|
| + //Retrieve the first (and only!) File from the FileList object
|
| + var f = evt.target.files[0];
|
| + if (f) {
|
| + var r = new FileReader();
|
| + r.onload = function(e) {
|
| + var file = evt.target.files[0];
|
| + currentFunctionKind = "";
|
| + fileContent = e.target.result;
|
| + processFileContent();
|
| + functionChangedHandler();
|
| + }
|
| + r.readAsText(f);
|
| + } else {
|
| + alert("Failed to load file");
|
| + }
|
| + }
|
| +
|
| + function buildFunctionKindSelector(kindSelectElement) {
|
| + for (var x = 0; x < kinds.length; ++x) {
|
| + var optionElement = document.createElement("option");
|
| + optionElement.value = x;
|
| + optionElement.text = kinds[x];
|
| + kindSelectElement.add(optionElement, null);
|
| + }
|
| + kindSelectElement.selectedIndex = 1;
|
| + setKindByIndex(1);
|
| + }
|
| +
|
| + return {
|
| + buildFunctionKindSelector: buildFunctionKindSelector,
|
| + kindChangedHandler: kindChangedHandler,
|
| + functionChangedHandler: functionChangedHandler,
|
| + asmClick: asmClick,
|
| + addressClick: addressClick,
|
| + readLog: readLog
|
| + };
|
| +
|
| +})();
|
|
|