diff options
Diffstat (limited to 'deps/v8/test/mjsunit/wasm/inlining.js')
-rw-r--r-- | deps/v8/test/mjsunit/wasm/inlining.js | 166 |
1 files changed, 165 insertions, 1 deletions
diff --git a/deps/v8/test/mjsunit/wasm/inlining.js b/deps/v8/test/mjsunit/wasm/inlining.js index 602eae974a..7045b6a99a 100644 --- a/deps/v8/test/mjsunit/wasm/inlining.js +++ b/deps/v8/test/mjsunit/wasm/inlining.js @@ -3,7 +3,7 @@ // found in the LICENSE file. // Flags: --wasm-inlining --no-liftoff --experimental-wasm-return-call -// Flags: --experimental-wasm-gc +// Flags: --experimental-wasm-gc --allow-natives-syntax d8.file.execute("test/mjsunit/wasm/wasm-module-builder.js"); @@ -295,6 +295,68 @@ d8.file.execute("test/mjsunit/wasm/wasm-module-builder.js"); assertEquals(20, instance.exports.main(10, 20)); })(); +// Inlining should behave correctly when there are no throwing nodes in the +// callee. +(function NoThrowInHandledTest() { + print(arguments.callee.name); + let builder = new WasmModuleBuilder(); + let tag = builder.addTag(kSig_v_i); + + let callee = builder.addFunction("callee", kSig_i_i) + .addBody([ + kExprLocalGet, 0, kExprI32Const, 0, kExprI32GeS, + kExprIf, kWasmI32, + kExprLocalGet, 0, kExprI32Const, 1, kExprI32Add, + kExprElse, + kExprLocalGet, 0, kExprI32Const, 2, kExprI32Sub, + kExprEnd]); + + builder.addFunction("main", kSig_i_ii) + .addBody([kExprTry, kWasmI32, + kExprLocalGet, 0, + kExprCallFunction, callee.index, + kExprCatchAll, + kExprLocalGet, 1, + kExprEnd]) + .exportAs("main"); + + let instance = builder.instantiate(); + assertEquals(11, instance.exports.main(10, 20)); +})(); + +// Things get more complex if we also need to reload the memory context. +(function UnandledInHandledWithMemoryTest() { + print(arguments.callee.name); + let builder = new WasmModuleBuilder(); + + let sig = builder.addType(kSig_i_i); + + builder.addMemory(10, 100); + + let inner_callee = builder.addFunction("inner_callee", kSig_i_i) + .addBody([kExprLocalGet, 0]).exportFunc(); + + // f(x, y) = { do { y += 1; x -= 1; } while (x > 0); return y; } + let callee = builder.addFunction("callee", kSig_i_ii) + .addBody([ + kExprLocalGet, 0, kExprLocalGet, 1, kExprI32Add, + kExprRefFunc, inner_callee.index, kExprCallRef, sig]); + // g(x) = f(5, x) + x + builder.addFunction("main", kSig_i_i) + .addBody([kExprTry, kWasmI32, + kExprI32Const, 5, kExprLocalGet, 0, + kExprCallFunction, callee.index, + kExprCatchAll, + kExprI32Const, 0, + kExprEnd, + kExprLocalGet, 0, kExprI32Add, + kExprI32Const, 10, kExprI32LoadMem, 0, 0, kExprI32Add]) + .exportAs("main"); + + let instance = builder.instantiate(); + assertEquals(25, instance.exports.main(10)); +})(); + (function LoopUnrollingTest() { print(arguments.callee.name); let builder = new WasmModuleBuilder(); @@ -469,3 +531,105 @@ d8.file.execute("test/mjsunit/wasm/wasm-module-builder.js"); builder.instantiate({}); })(); + +(function InliningTrapFromCallee() { + print(arguments.callee.name); + let builder = new WasmModuleBuilder(); + + // Add some types to have an index offset. + for (let i = 0; i < 10; ++i) { + builder.addFunction(null, makeSig([], [])).addBody([]); + } + + let callee = builder.addFunction('callee', kSig_i_ii) + .addBody([ + kExprLocalGet, 0, + kExprLocalGet, 1, + kExprI32DivU, + ]); + + let intermediate = builder.addFunction('intermediate', kSig_i_ii) + .addBody([ + // Some nops, so that the call doesn't have the same offset as the div + // in the callee. + kExprNop, kExprNop, + kExprLocalGet, 0, + kExprLocalGet, 1, + kExprCallFunction, callee.index, + ]) + .exportFunc(); + + let caller = builder.addFunction('main', kSig_ii_ii) + .addBody([ + // Some nops, so that the call doesn't have the same offset as the div + // in the callee. + kExprNop, kExprNop, kExprNop, kExprNop, kExprNop, + kExprLocalGet, 0, + kExprLocalGet, 1, + kExprCallFunction, intermediate.index, + // If it didn't trap, call it again without intermediate function and with + // swapped arguments. + kExprLocalGet, 1, + kExprLocalGet, 0, + kExprCallFunction, callee.index, + ]) + .exportFunc(); + + let wire_bytes = builder.toBuffer(); + let module = new WebAssembly.Module(wire_bytes); + let instance = new WebAssembly.Instance(module, {}); + TestStackTrace(instance.exports.main); + // Serialize and deserialize the module to verify that the inlining positions + // are properly "transformed" here. + print("Repeat test with serialized module.") + module = %DeserializeWasmModule(%SerializeWasmModule(module), wire_bytes); + instance = new WebAssembly.Instance(module, {}); + TestStackTrace(instance.exports.main); + + function TestStackTrace(main) { + assertEquals([7, 0], main(21, 3)); + assertTraps(kTrapDivByZero, () => main(1, 0)); + // Test stack trace for trap. + try { + main(1, 0); + assertUnreachable(); + } catch(e) { + assertMatches(/RuntimeError: divide by zero/, e.stack); + let expected_entries = [ + // [name, index, offset] + ['callee', '' + callee.index, '0x8c'], + ['intermediate', '' + intermediate.index, '0x96'], + ['main', '' + caller.index, '0xa4'], + ]; + CheckCallStack(e, expected_entries); + } + + try { + main(0, 1); + assertUnreachable(); + } catch(e) { + assertMatches(/RuntimeError: divide by zero/, e.stack); + let expected_entries = [ + // [name, index, offset] + ['callee', '' + callee.index, '0x8c'], + ['main', '' + caller.index, '0xaa'], + ]; + CheckCallStack(e, expected_entries); + } + } + + function CheckCallStack(error, expected_entries) { + print(error.stack); + let regex = /at ([^ ]+) \(wasm[^\[]+\[([0-9]+)\]:(0x[0-9a-f]+)\)/g; + let entries = [...error.stack.matchAll(regex)]; + for (let i = 0; i < expected_entries.length; ++i) { + let actual = entries[i]; + print(`match = ${actual[0]}`); + let expected = expected_entries[i]; + assertEquals(expected[0], actual[1]); + assertEquals(expected[1], actual[2]); + assertEquals(expected[2], actual[3]); + } + assertEquals(expected_entries.length, entries.length); + } +})(); |