| OLD | NEW |
| 1 // Copyright 2016 the V8 project authors. All rights reserved. | 1 // Copyright 2016 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 // clang-format off | 5 // clang-format off |
| 6 // Flags: --expose-wasm | 6 // Flags: --expose-wasm |
| 7 | 7 |
| 8 load("test/mjsunit/wasm/wasm-constants.js"); | 8 load("test/mjsunit/wasm/wasm-constants.js"); |
| 9 load("test/mjsunit/wasm/wasm-module-builder.js"); | 9 load("test/mjsunit/wasm/wasm-module-builder.js"); |
| 10 | 10 |
| 11 // The stack trace contains file path, only keep "stack.js". | 11 // The stack trace contains file path, only keep "stack.js". |
| 12 function stripPath(s) { | 12 function stripPath(s) { |
| 13 return s.replace(/[^ (]*stack\.js/g, "stack.js"); | 13 return s.replace(/[^ (]*stack\.js/g, "stack.js"); |
| 14 } | 14 } |
| 15 | 15 |
| 16 function verifyStack(frames, expected) { | 16 function verifyStack(frames, expected) { |
| 17 assertEquals(expected.length, frames.length, "number of frames mismatch"); | 17 assertEquals(expected.length, frames.length, "number of frames mismatch"); |
| 18 expected.forEach(function(exp, i) { | 18 expected.forEach(function(exp, i) { |
| 19 assertEquals(exp[0], frames[i].getFunctionName(), | 19 if (exp[0] != "?") { |
| 20 "["+i+"].getFunctionName()"); | 20 assertEquals(exp[0], frames[i].getFunctionName(), |
| 21 "["+i+"].getFunctionName()"); |
| 22 } |
| 21 assertEquals(exp[1], frames[i].getLineNumber(), | 23 assertEquals(exp[1], frames[i].getLineNumber(), |
| 22 "["+i+"].getLineNumber()"); | 24 "["+i+"].getLineNumber()"); |
| 23 assertContains(exp[2], frames[i].getFileName(), | 25 assertContains(exp[2], frames[i].getFileName(), |
| 24 "["+i+"].getFileName()"); | 26 "["+i+"].getFileName()"); |
| 25 assertContains(exp[3], frames[i].toString(), | 27 assertContains(exp[3], frames[i].toString(), |
| 26 "["+i+"].toString()"); | 28 "["+i+"].toString()"); |
| 27 }); | 29 }); |
| 28 } | 30 } |
| 29 | 31 |
| 32 function verifyWasmStack(frames, expected) { |
| 33 assertEquals(expected.length, frames.length, "number of frames mismatch"); |
| 34 expected.forEach(function(exp, i) { |
| 35 assertEquals(exp[0], frames[i].isWasm(), |
| 36 "["+i+"].isWasm()"); |
| 37 assertEquals(exp[0], frames[i].getWasmObject() != null, |
| 38 "["+i+"].getWasmObject() != null"); |
| 39 assertEquals(exp[1], frames[i].getWasmFunctionIndex(), |
| 40 "["+i+"].getWasmFunctionIndex()"); |
| 41 if (exp[0]) |
| 42 assertEquals(exp[2], frames[i].getPosition(), |
| 43 "["+i+"].getPosition()"); |
| 44 }); |
| 45 } |
| 46 |
| 30 | 47 |
| 31 var stack; | 48 var stack; |
| 32 function STACK() { | 49 function STACK() { |
| 33 var e = new Error(); | 50 var e = new Error(); |
| 34 stack = e.stack; | 51 stack = e.stack; |
| 35 } | 52 } |
| 36 | 53 |
| 37 var builder = new WasmModuleBuilder(); | 54 var builder = new WasmModuleBuilder(); |
| 38 | 55 |
| 39 builder.addImport("func", [kAstStmt]); | 56 builder.addImport("func", [kAstStmt]); |
| 40 | 57 |
| 41 builder.addFunction("main", [kAstStmt]) | 58 var main_func = builder.addFunction("main", [kAstStmt]) |
| 42 .addBody([kExprCallImport, 0]) | 59 .addBody([kExprCallImport, 0]) |
| 43 .exportAs("main"); | 60 .exportAs("main"); |
| 44 | 61 |
| 45 builder.addFunction("exec_unreachable", [kAstStmt]) | 62 var unreach_func = builder.addFunction("exec_unreachable", [kAstStmt]) |
| 46 .addBody([kExprUnreachable]) | 63 .addBody([kExprUnreachable]) |
| 47 .exportAs("exec_unreachable"); | 64 .exportAs("exec_unreachable"); |
| 48 | 65 |
| 49 // make this function unnamed, just to test also this case | 66 // Make this function unnamed, just to test also this case. |
| 50 var mem_oob_func = builder.addFunction(undefined, [kAstStmt]) | 67 var mem_oob_func = builder.addFunction(undefined, [kAstStmt]) |
| 51 // access the memory at offset -1 | 68 // Access the memory at offset -1, to provoke a trap. |
| 52 .addBody([kExprI32LoadMem8S, 0, 0, kExprI32Const, 0x7f]) | 69 .addBody([kExprI32LoadMem8S, 0, 0, kExprI32Const, 0x7f]) |
| 53 .exportAs("mem_out_of_bounds"); | 70 .exportAs("mem_out_of_bounds"); |
| 54 | 71 |
| 55 // call the mem_out_of_bounds function, in order to have two WASM stack frames | 72 // Call the mem_out_of_bounds function, in order to have two WASM stack frames. |
| 56 builder.addFunction("call_mem_out_of_bounds", [kAstStmt]) | 73 var call_mem_oob_func = builder.addFunction("call_mem_out_of_bounds", |
| 74 [kAstStmt]) |
| 57 .addBody([kExprCallFunction, mem_oob_func.index]) | 75 .addBody([kExprCallFunction, mem_oob_func.index]) |
| 58 .exportAs("call_mem_out_of_bounds"); | 76 .exportAs("call_mem_out_of_bounds"); |
| 59 | 77 |
| 60 var module = builder.instantiate({func: STACK}); | 78 var module = builder.instantiate({func: STACK}); |
| 61 | 79 |
| 62 (function testSimpleStack() { | 80 (function testSimpleStack() { |
| 63 var expected_string = "Error\n" + | 81 var expected_string = "Error\n" + |
| 64 // The line numbers below will change as this test gains / loses lines.. | 82 // The line numbers below will change as this test gains / loses lines.. |
| 65 " at STACK (stack.js:33:11)\n" + // -- | 83 " at STACK (stack.js:50:11)\n" + // -- |
| 66 " at <WASM> (<anonymous>)\n" + // TODO(jfb): wasm stack here. | 84 " at main (<WASM>:1)\n" + // -- |
| 67 " at testSimpleStack (stack.js:70:18)\n" + // -- | 85 " at testSimpleStack (stack.js:88:18)\n" + // -- |
| 68 " at stack.js:72:3"; // -- | 86 " at stack.js:90:3"; // -- |
| 69 | 87 |
| 70 module.exports.main(); | 88 module.exports.main(); |
| 71 assertEquals(expected_string, stripPath(stack)); | 89 assertEquals(expected_string, stripPath(stack)); |
| 72 })(); | 90 })(); |
| 73 | 91 |
| 74 // For the remaining tests, collect the Callsite objects instead of just a | 92 // For the remaining tests, collect the Callsite objects instead of just a |
| 75 // string: | 93 // string: |
| 76 Error.prepareStackTrace = function(error, frames) { | 94 Error.prepareStackTrace = function(error, frames) { |
| 77 return frames; | 95 return frames; |
| 78 }; | 96 }; |
| 79 | 97 |
| 80 (function testStackFrames() { | 98 (function testStackFrames() { |
| 81 module.exports.main(); | 99 module.exports.main(); |
| 82 | 100 |
| 83 // TODO(clemensh): add a isWasm() method or similar, and test it | |
| 84 verifyStack(stack, [ | 101 verifyStack(stack, [ |
| 85 // function line file toString | 102 // function line file toString |
| 86 [ "STACK", 33, "stack.js", "stack.js:33:11"], | 103 [ "STACK", 50, "stack.js", "stack.js:50:11"], |
| 87 [ "<WASM>", null, null, "<WASM>"], | 104 [ "main", null, null, "main (<WASM>:1)"], |
| 88 ["testStackFrames", 81, "stack.js", "stack.js:81:18"], | 105 ["testStackFrames", 99, "stack.js", "stack.js:99:18"], |
| 89 [ null, 91, "stack.js", "stack.js:91:3"] | 106 [ null, 115, "stack.js", "stack.js:115:3"] |
| 107 ]); |
| 108 verifyWasmStack(stack, [ |
| 109 // isWasm funcIndex byteOffset |
| 110 [ false, undefined, null], |
| 111 [ true, main_func.index, 1], |
| 112 [ false, undefined, null], |
| 113 [ false, undefined, null], |
| 90 ]); | 114 ]); |
| 91 })(); | 115 })(); |
| 92 | 116 |
| 93 (function testWasmUnreachable() { | 117 (function testWasmUnreachable() { |
| 94 try { | 118 try { |
| 95 module.exports.exec_unreachable(); | 119 module.exports.exec_unreachable(); |
| 96 fail("expected wasm exception"); | 120 fail("expected wasm exception"); |
| 97 } catch (e) { | 121 } catch (e) { |
| 98 assertContains("unreachable", e.message); | 122 assertContains("unreachable", e.message); |
| 99 verifyStack(e.stack, [ | 123 verifyStack(e.stack, [ |
| 100 // function line file toString | 124 // function line file toString |
| 101 [ "<WASM>", null, null, "<WASM>"], | 125 [ "exec_unreachable", null, null, "exec_unreachable (<WASM>:-1)"],
// TODO(clemensh): position should be 1 |
| 102 ["testWasmUnreachable", 95, "stack.js", "stack.js:95:20"], | 126 ["testWasmUnreachable", 119, "stack.js", "stack.js:119:20"], |
| 103 [ null, 106, "stack.js", "stack.js:106:3"] | 127 [ null, 136, "stack.js", "stack.js:136:3"] |
| 128 ]); |
| 129 verifyWasmStack(e.stack, [ |
| 130 // isWasm funcIndex byteOffset |
| 131 [ true, unreach_func.index, -1], // TODO(clemensh): position s
hould be 1 |
| 132 [ false, undefined, null], |
| 133 [ false, undefined, null], |
| 104 ]); | 134 ]); |
| 105 } | 135 } |
| 106 })(); | 136 })(); |
| 107 | 137 |
| 108 (function testWasmMemOutOfBounds() { | 138 (function testWasmMemOutOfBounds() { |
| 109 try { | 139 try { |
| 110 module.exports.call_mem_out_of_bounds(); | 140 module.exports.call_mem_out_of_bounds(); |
| 111 fail("expected wasm exception"); | 141 fail("expected wasm exception"); |
| 112 } catch (e) { | 142 } catch (e) { |
| 113 assertContains("out of bounds", e.message); | 143 assertContains("out of bounds", e.message); |
| 114 verifyStack(e.stack, [ | 144 verifyStack(e.stack, [ |
| 115 // function line file toString | 145 // function line file toString |
| 116 [ "<WASM>", null, null, "<WASM>"], | 146 [ "?", null, null, " (<WASM>:-1)"], // TOD
O(clemensh): position should be 1 |
| 117 [ "<WASM>", null, null, "<WASM>"], | 147 ["call_mem_out_of_bounds", null, null, "bounds (<WASM>:1)"], |
| 118 ["testWasmMemOutOfBounds", 110, "stack.js", "stack.js:110:20"], | 148 ["testWasmMemOutOfBounds", 140, "stack.js", "stack.js:140:20"], |
| 119 [ null, 122, "stack.js", "stack.js:122:3"] | 149 [ null, 160, "stack.js", "stack.js:160:3"] |
| 150 ]); |
| 151 assertTrue(call_mem_oob_func.index != mem_oob_func.index); |
| 152 verifyWasmStack(e.stack, [ |
| 153 // isWasm funcIndex byteOffset |
| 154 [ true, mem_oob_func.index, -1], // TODO(clemensh): positi
on should be 1 |
| 155 [ true, call_mem_oob_func.index, 1], |
| 156 [ false, undefined, 1], |
| 157 [ false, undefined, 1], |
| 120 ]); | 158 ]); |
| 121 } | 159 } |
| 122 })(); | 160 })(); |
| OLD | NEW |