| // 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, 3], // -- |
| ['f', 135, 12], // -- |
| ['f', 135, 12], // -- |
| ['f', 135, 12] // -- |
| ]); |
| })(); |