v8/test/mjsunit/wasm/asm-wasm-stack.js
Michael Starzinger 6a3756f9de [asm.js] Fix names for forward declared functions.
This fixes the name stored with functions where the declaration was
hoisted above the actual function definition. It also extends test
coverage and emits proper source position mapping for such cases.

R=clemensh@chromium.org
TEST=mjsunit/wasm/asm-wasm-stack
BUG=v8:6127

Change-Id: I675a98b244fe2157925e799b5c46b7f6bd53c9da
Reviewed-on: https://chromium-review.googlesource.com/466247
Reviewed-by: Clemens Hammacher <clemensh@chromium.org>
Commit-Queue: Michael Starzinger <mstarzinger@chromium.org>
Cr-Commit-Position: refs/heads/master@{#44361}
2017-04-04 07:55:54 +00:00

157 lines
4.5 KiB
JavaScript

// 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] // --
]);
})();