The data contained in this repository can be downloaded to your computer using one of several clients.
Please see the documentation of your version control software client for more information.

Please select the desired protocol below to get the URL.

This URL has Read-Only access.

Statistics
| Branch: | Revision:

main_repo / deps / v8 / tools / sodium / sodium.js @ f230a1cf

History | View | Annotate | Download (13.8 KB)

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
    document.getElementById('source-text-pre').innerHTML = '';
188
    sourceBegin = -1;
189
    codeObjects = [];
190
    processLines(fileContent, fileContent.length, processLine);
191
    var functionSelectElement = document.getElementById('function-selector-id');
192
    functionSelectElement.innerHTML = '';
193
    var length = codeObjects.length;
194
    for (var i = 0; i < codeObjects.length; ++i) {
195
      var code = codeObjects[i];
196
      if (code.kind == selectedFunctionKind) {
197
        var optionElement = document.createElement("option");
198
        optionElement.codeObject = code;
199
        optionElement.text = code.name;
200
        functionSelectElement.add(optionElement, null);
201
      }
202
    }
203
  }
204

    
205
  function asmClick(element) {
206
    if (element == selectedAsm) return;
207
    if (selectedAsm != null) {
208
      selectedAsm.classList.remove('highlight-yellow');
209
    }
210
    selectedAsm = element;
211
    selectedAsm.classList.add('highlight-yellow');
212

    
213
    var pc = element.firstChild.innerText;
214
    var sourceLine = null;
215
    if (addressFinder.exec(pc) != null) {
216
      var position = findSourcePosition(pc);
217
      var line = findSourceLine(position);
218
      sourceLine = document.getElementById('source-line-' + line);
219
      var sourceLineTop = sourceLine.offsetTop;
220
      makeSourcePosVisible(sourceLineTop);
221
    }
222
    if (selectedSource == sourceLine) return;
223
    if (selectedSource != null) {
224
      selectedSource.classList.remove('highlight-yellow');
225
      selectedSource.classList.add(selectedSourceClass);
226
    }
227
    if (sourceLine != null) {
228
      selectedSourceClass = sourceLine.classList[0];
229
      sourceLine.classList.remove(selectedSourceClass);
230
      sourceLine.classList.add('highlight-yellow');
231
    }
232
    selectedSource = sourceLine;
233
  }
234

    
235
  function makeContainerPosVisible(container, newTop) {
236
    var height = container.offsetHeight;
237
    var margin = Math.floor(height / 4);
238
    if (newTop < container.scrollTop + margin) {
239
      newTop -= margin;
240
      if (newTop < 0) newTop = 0;
241
      container.scrollTop = newTop;
242
      return;
243
    }
244
    if (newTop > (container.scrollTop + 3 * margin)) {
245
      newTop = newTop - 3 * margin;
246
      container.scrollTop = newTop;
247
    }
248
  }
249

    
250
  function makeAsmPosVisible(newTop) {
251
    var asmContainer = document.getElementById('asm-container');
252
    makeContainerPosVisible(asmContainer, newTop);
253
  }
254

    
255
  function makeSourcePosVisible(newTop) {
256
    var sourceContainer = document.getElementById('source-container');
257
    makeContainerPosVisible(sourceContainer, newTop);
258
  }
259

    
260
  function addressClick(element, event) {
261
    event.stopPropagation();
262
    var asmLineId = 'address-' + element.innerText;
263
    var asmLineElement = document.getElementById(asmLineId);
264
    if (asmLineElement != null) {
265
      var asmLineTop = asmLineElement.parentNode.offsetTop;
266
      makeAsmPosVisible(asmLineTop);
267
      asmLineElement.classList.add('highlight-flash-blue');
268
      window.setTimeout(function() {
269
        asmLineElement.classList.remove('highlight-flash-blue');
270
      }, 1500);
271
    }
272
  }
273

    
274
  function prepareAsm(originalSource) {
275
    var newSource = "";
276
    var lineNumber = 1;
277
    var functionProcessLine = function(text, begin, end) {
278
      var currentLine = text.substring(begin, end);
279
      var matches = instructionFinder.exec(currentLine);
280
      var clickHandler = "";
281
      if (matches != null) {
282
        var restOfLine = matches[2];
283
        restOfLine = restOfLine.replace(
284
          addressReplacer,
285
          '<span class="hover-underline" ' +
286
            'onclick="Sodium.addressClick(this, event);">\$1</span>');
287
        currentLine = '<span id="address-' + matches[1] + '" >' +
288
          matches[1] + '</span>' + restOfLine;
289
        clickHandler = 'onclick=\'Sodium.asmClick(this)\' ';
290
      } else if (whiteSpaceLineFinder.exec(currentLine)) {
291
        currentLine = "<br>";
292
      }
293
      newSource += '<pre style=\'margin-bottom: -12px;\' ' + clickHandler + '>' +
294
        currentLine + '</pre>';
295
      lineNumber++;
296
    }
297
    processLines(originalSource, originalSource.length, functionProcessLine);
298
    return newSource;
299
  }
300

    
301
  function findSourcePosition(pcToSearch) {
302
    var position = 0;
303
    var distance = 0x7FFFFFFF;
304
    var pcToSearchOffset = parseInt(pcToSearch);
305
    var processOneLine = function(text, begin, end) {
306
      var currentLine = text.substring(begin, end);
307
      var matches = positionFinder.exec(currentLine);
308
      if (matches != null) {
309
        var pcOffset = parseInt(matches[1]);
310
        if (pcOffset <= pcToSearchOffset) {
311
          var dist =  pcToSearchOffset - pcOffset;
312
          var pos = parseInt(matches[2]);
313
          if ((dist < distance) || (dist == distance && pos > position)) {
314
            position = pos;
315
            distance = dist;
316
          }
317
        }
318
      }
319
    }
320
    var asmText = getCurrentAsmText();
321
    processLines(asmText, asmText.length, processOneLine);
322
    var code = getCurrentCodeObject();
323
    if (position == 0) return 0;
324
    return position - code.firstSourcePosition;
325
  }
326

    
327
  function findSourceLine(position) {
328
    if (position == 0) return 1;
329
    var line = 0;
330
    var processOneLine = function(text, begin, end) {
331
      if (begin < position) {
332
        line++;
333
      }
334
    }
335
    var sourceText = getCurrentSourceText();
336
    processLines(sourceText, sourceText.length, processOneLine);
337
    return line;
338
  }
339

    
340
  function functionChangedHandler() {
341
    var functionSelect = document.getElementById('function-selector-id');
342
    var source = getCurrentSourceText();
343
    var sourceDivElement = document.getElementById('source-text');
344
    var code = getCurrentCodeObject();
345
    var newHtml = "<pre class=\"prettyprint linenums\" id=\"source-text\">"
346
      + 'function ' + code.name + source + "</pre>";
347
    sourceDivElement.innerHTML = newHtml;
348
    try {
349
      // Wrap in try to work when offline.
350
      PR.prettyPrint();
351
    } catch (e) {
352
    }
353
    var sourceLineContainer = sourceDivElement.firstChild.firstChild;
354
    var lineCount = sourceLineContainer.childElementCount;
355
    var current = sourceLineContainer.firstChild;
356
    for (var i = 1; i < lineCount; ++i) {
357
      current.id = "source-line-" + i;
358
      current = current.nextElementSibling;
359
    }
360

    
361
    var asm = getCurrentAsmText();
362
    document.getElementById('asm-text').innerHTML = prepareAsm(asm);
363
  }
364

    
365
  function kindChangedHandler(element) {
366
    setKindByIndex(element.selectedIndex);
367
    processFileContent();
368
    functionChangedHandler();
369
  }
370

    
371
  function readLog(evt) {
372
    //Retrieve the first (and only!) File from the FileList object
373
    var f = evt.target.files[0];
374
    if (f) {
375
      var r = new FileReader();
376
      r.onload = function(e) {
377
        var file = evt.target.files[0];
378
        currentFunctionKind = "";
379
        fileContent = e.target.result;
380
        processFileContent();
381
        functionChangedHandler();
382
      }
383
      r.readAsText(f);
384
    } else {
385
      alert("Failed to load file");
386
    }
387
  }
388

    
389
  function buildFunctionKindSelector(kindSelectElement) {
390
    for (var x = 0; x < kinds.length; ++x) {
391
      var optionElement = document.createElement("option");
392
      optionElement.value = x;
393
      optionElement.text = kinds[x];
394
      kindSelectElement.add(optionElement, null);
395
    }
396
    kindSelectElement.selectedIndex = 1;
397
    setKindByIndex(1);
398
  }
399

    
400
  return {
401
    buildFunctionKindSelector: buildFunctionKindSelector,
402
    kindChangedHandler: kindChangedHandler,
403
    functionChangedHandler: functionChangedHandler,
404
    asmClick: asmClick,
405
    addressClick: addressClick,
406
    readLog: readLog
407
  };
408

    
409
})();