summaryrefslogtreecommitdiff
path: root/deps/v8/test/mjsunit/wasm/inlining.js
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/test/mjsunit/wasm/inlining.js')
-rw-r--r--deps/v8/test/mjsunit/wasm/inlining.js166
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);
+ }
+})();