asm-wasm-stack.js 4.53 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
// Copyright 2016 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Flags: --validate-asm --allow-natives-syntax

var filename = '(?:[^ ]+/)?test/mjsunit/wasm/asm-wasm-stack.js';
filename = filename.replace(/\//g, '[/\\\\]');

function checkPreformattedStack(e, expected_lines) {
  print('preformatted stack: ' + e.stack);
  var lines = e.stack.split('\n');
  assertEquals(expected_lines.length, lines.length);
  for (var i = 0; i < lines.length; ++i) {
    assertMatches(expected_lines[i], lines[i], 'line ' + i);
  }
}

19
function printCallsites(stack) {
20 21 22 23 24 25 26
  print('callsite objects (size ' + stack.length + '):');
  for (var i = 0; i < stack.length; ++i) {
    var s = stack[i];
    print(
        ' [' + i + '] ' + s.getFunctionName() + ' (' + s.getFileName() + ':' +
        s.getLineNumber() + ':' + s.getColumnNumber() + ')');
  }
27 28 29 30 31
}

function checkCallsiteArray(stack, expected) {
  assertEquals(expected.length, stack.length, 'stack size');
  for (var i = 0; i < expected.length; ++i) {
32 33
    var cs = stack[i];
    assertMatches('^' + filename + '$', cs.getFileName(), 'file name at ' + i);
34 35 36
    assertEquals(expected[i][0], cs.getFunctionName(), 'function name at ' + i);
    assertEquals(expected[i][1], cs.getLineNumber(), 'line number at ' + i);
    assertEquals(expected[i][2], cs.getColumnNumber(), 'column number at ' + i);
37 38 39 40 41
    assertNotNull(cs.getThis(), 'receiver should be global');
    assertEquals(stack[0].getThis(), cs.getThis(), 'receiver should be global');
  }
}

42 43 44 45 46 47 48 49 50 51 52 53 54
function checkFunctionsOnCallsites(e, expected) {
  printCallsites(e.stack);
  checkCallsiteArray(e.stack, expected);
}

function checkTopFunctionsOnCallsites(e, expected) {
  printCallsites(e.stack);
  assertTrue(
      e.stack.length >= expected.length, 'expected at least ' +
          expected.length + ' callsites, got ' + e.stack.length);
  checkCallsiteArray(e.stack.slice(0, expected.length), expected);
}

55 56 57 58
function throwException() {
  throw new Error('exception from JS');
}

59
function generateWasmFromAsmJs(stdlib, foreign) {
60 61 62 63 64
  'use asm';
  var throwFunc = foreign.throwFunc;
  function callThrow() {
    throwFunc();
  }
65
  function redirectFun(i) {
66 67
    i = i | 0;
    switch (i | 0) {
68 69 70
      case 0: callThrow(); break;
      case 1: redirectFun(0); break;
      case 2: redirectFun(1); break;
71
      case 3: funTable[i & 0](2); break;
72
      case 4: forwardFun(); break;
73
    }
74
  }
75 76 77
  function forwardFun() {
    redirectFun(3);
  }
78
  var funTable = [ redirectFun ];
79 80 81 82
  return redirectFun;
}

(function PreformattedStackTraceFromJS() {
83 84
  var fun = generateWasmFromAsmJs(this, {throwFunc: throwException});
  assertTrue(%IsWasmCode(fun));
85 86
  var e = null;
  try {
87
    fun(0);
88 89 90 91 92 93
  } catch (ex) {
    e = ex;
  }
  assertInstanceof(e, Error, 'exception should have been thrown');
  checkPreformattedStack(e, [
    '^Error: exception from JS$',
94 95 96
    '^ *at throwException \\(' + filename + ':56:9\\)$',
    '^ *at callThrow \\(' + filename + ':63:5\\)$',
    '^ *at redirectFun \\(' + filename + ':68:15\\)$',
97 98
    '^ *at PreformattedStackTraceFromJS \\(' + filename + ':87:5\\)$',
    '^ *at ' + filename + ':100:3$'
99 100 101 102 103 104 105 106 107
  ]);
})();

// Now collect the Callsite objects instead of just a string.
Error.prepareStackTrace = function(error, frames) {
  return frames;
};

(function CallsiteObjectsFromJS() {
108 109
  var fun = generateWasmFromAsmJs(this, {throwFunc: throwException});
  assertTrue(%IsWasmCode(fun));
110 111
  var e = null;
  try {
112
    fun(4);
113 114 115 116 117
  } catch (ex) {
    e = ex;
  }
  assertInstanceof(e, Error, 'exception should have been thrown');
  checkFunctionsOnCallsites(e, [
118 119 120 121 122
    ['throwException', 56, 9],          // --
    ['callThrow', 63, 5],               // --
    ['redirectFun', 68, 15],            // --
    ['redirectFun', 69, 15],            // --
    ['redirectFun', 70, 15],            // --
123
    ['redirectFun', 71, 30],            // --
124 125 126 127
    ['forwardFun', 76, 5],             // --
    ['redirectFun', 72, 15],            // --
    ['CallsiteObjectsFromJS', 112, 5],  // --
    [null, 129, 3]
128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144
  ]);
})();

function generateOverflowWasmFromAsmJs() {
  'use asm';
  function f(a) {
    a = a | 0;
    return f(a) | 0;
  }
  return f;
}

(function StackOverflowPosition() {
  var fun = generateOverflowWasmFromAsmJs();
  assertTrue(%IsWasmCode(fun));
  var e = null;
  try {
145
    fun(23);
146 147 148
  } catch (ex) {
    e = ex;
  }
149
  assertInstanceof(e, RangeError, 'RangeError should have been thrown');
150
  checkTopFunctionsOnCallsites(e, [
151
    ['f', 133,  3],  // --
152 153 154
    ['f', 135, 12],  // --
    ['f', 135, 12],  // --
    ['f', 135, 12]   // --
155 156
  ]);
})();