blob: 5a05f42dd6f20457115bc15cf05136257d790268 [file] [log] [blame]
// 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);
}
}
function printCallsites(stack) {
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() + ')');
}
}
function checkCallsiteArray(stack, expected) {
assertEquals(expected.length, stack.length, 'stack size');
for (var i = 0; i < expected.length; ++i) {
var cs = stack[i];
assertMatches('^' + filename + '$', cs.getFileName(), 'file name at ' + i);
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);
assertNotNull(cs.getThis(), 'receiver should be global');
assertEquals(stack[0].getThis(), cs.getThis(), 'receiver should be global');
}
}
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);
}
function throwException() {
throw new Error('exception from JS');
}
function generateWasmFromAsmJs(stdlib, foreign) {
'use asm';
var throwFunc = foreign.throwFunc;
function callThrow() {
throwFunc();
}
function redirectFun(i) {
i = i | 0;
switch (i | 0) {
case 0: callThrow(); break;
case 1: redirectFun(0); break;
case 2: redirectFun(1); break;
case 3: funTable[i & 0](2); break;
case 4: forwardFun(); break;
}
}
function forwardFun() {
redirectFun(3);
}
var funTable = [ redirectFun ];
return redirectFun;
}
(function PreformattedStackTraceFromJS() {
var fun = generateWasmFromAsmJs(this, {throwFunc: throwException});
assertTrue(%IsWasmCode(fun));
var e = null;
try {
fun(0);
} catch (ex) {
e = ex;
}
assertInstanceof(e, Error, 'exception should have been thrown');
checkPreformattedStack(e, [
'^Error: exception from JS$',
'^ *at throwException \\(' + filename + ':56:9\\)$',
'^ *at callThrow \\(' + filename + ':63:5\\)$',
'^ *at redirectFun \\(' + filename + ':68:15\\)$',
'^ *at PreformattedStackTraceFromJS \\(' + filename + ':87:5\\)$',
'^ *at ' + filename + ':100:3$'
]);
})();
// Now collect the Callsite objects instead of just a string.
Error.prepareStackTrace = function(error, frames) {
return frames;
};
(function CallsiteObjectsFromJS() {
var fun = generateWasmFromAsmJs(this, {throwFunc: throwException});
assertTrue(%IsWasmCode(fun));
var e = null;
try {
fun(4);
} catch (ex) {
e = ex;
}
assertInstanceof(e, Error, 'exception should have been thrown');
checkFunctionsOnCallsites(e, [
['throwException', 56, 9], // --
['callThrow', 63, 5], // --
['redirectFun', 68, 15], // --
['redirectFun', 69, 15], // --
['redirectFun', 70, 15], // --
['redirectFun', 71, 30], // --
['forwardFun', 76, 5], // --
['redirectFun', 72, 15], // --
['CallsiteObjectsFromJS', 112, 5], // --
[null, 129, 3]
]);
})();
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 {
fun(23);
} catch (ex) {
e = ex;
}
assertInstanceof(e, RangeError, 'RangeError should have been thrown');
checkTopFunctionsOnCallsites(e, [
['f', 133, 13], // --
['f', 135, 12], // --
['f', 135, 12], // --
['f', 135, 12] // --
]);
})();