v8/test/mjsunit/wasm/stringrefs-regressions.js
Jakob Kummerow 0661a0dd8f [stringrefs] Fix inlining, and some corner case bugs
1) Inlining functions that contain stringref operations require builtin
   calls to be marked as kNoThrow appropriately (or have exception
   handling support in the graph).
2) Some overly-large inputs for string creation hit DCHECKs before
   getting to the places where they would have thrown an orderly
   exception.
3) We still had a known issue that some exceptions thrown by JS-focused
   code were erroneously catchable by Wasm.
4) When string.concat attempted to create a too-long string, it ran into
   a DCHECK because we didn't clear the "thread in wasm" flag.
5) The builtin call for string.concat was erroneously marked as
   kEliminatable, which could cause the trap get eliminated.

Bug: v8:12868
Change-Id: Iad3ada0e2465bfd8f3d00bb064c32049d6b19d87
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3902522
Auto-Submit: Jakob Kummerow <jkummerow@chromium.org>
Commit-Queue: Andy Wingo <wingo@igalia.com>
Reviewed-by: Andy Wingo <wingo@igalia.com>
Cr-Commit-Position: refs/heads/main@{#83292}
2022-09-19 07:52:41 +00:00

99 lines
3.3 KiB
JavaScript

// Copyright 2022 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: --experimental-wasm-stringref --allow-natives-syntax
// We just want speculative inlining, but the "stress" variant doesn't like
// that flag for some reason, so use the GC flag which implies it.
// Flags: --experimental-wasm-gc
d8.file.execute("test/mjsunit/wasm/wasm-module-builder.js");
let kSig_w_v = makeSig([], [kWasmStringRef]);
let kSig_w_i = makeSig([kWasmI32], [kWasmStringRef]);
let kSig_v_w = makeSig([kWasmStringRef], []);
(function () {
let huge_builder = new WasmModuleBuilder();
huge_builder.addMemory(65001, undefined, false, false);
huge_builder.addFunction("huge", kSig_w_v).exportFunc().addBody([
kExprI32Const, 0, // address
...wasmI32Const(65000 * 65536), // bytes
...GCInstr(kExprStringNewUtf8), 0 // memory index
]);
let callee = huge_builder.addFunction("callee", kSig_w_i).addBody([
kExprI32Const, 0, // address
kExprLocalGet, 0, // bytes
...GCInstr(kExprStringNewUtf8), 0 // memory index
]);
let caller = huge_builder.addFunction("caller", kSig_i_i).exportFunc()
.addBody([
kExprTry, kWasmI32,
kExprLocalGet, 0,
kExprCallFunction, callee.index,
kExprDrop,
kExprI32Const, 1,
kExprCatchAll,
kExprI32Const, 0,
kExprEnd
]);
let instance;
try {
instance = huge_builder.instantiate();
// On 64-bit platforms, expect to see this message.
console.log("Instantiation successful, proceeding.");
} catch (e) {
// 32-bit builds don't have enough virtual memory, that's OK.
assertInstanceof(e, RangeError);
assertMatches(/Cannot allocate Wasm memory for new instance/, e.message,
'Error message');
return;
}
// Bug 1: The Utf8Decoder can't handle more than kMaxInt bytes as input.
assertThrows(() => instance.exports.huge(), RangeError);
// Bug 2: Exceptions created by the JS-focused strings infrastructure must
// be marked as uncatchable by Wasm.
let f1 = instance.exports.caller;
assertThrows(() => f1(2147483647), RangeError);
// Bug 3: Builtin calls that have neither a kNoThrow annotation nor exception-
// handling support make the Wasm inliner sad.
for (let i = 0; i < 20; i++) f1(10);
%WasmTierUpFunction(instance, caller.index);
f1(10);
})();
let builder = new WasmModuleBuilder();
let concat_body = [];
// This doubles the string 26 times, i.e. multiplies its length with a factor
// of ~65 million.
for (let i = 0; i < 26; i++) {
concat_body.push(...[
kExprLocalGet, 0, kExprLocalGet, 0,
...GCInstr(kExprStringConcat),
kExprLocalSet, 0
]);
}
let concat =
builder.addFunction('concat', kSig_v_w).exportFunc().addBody(concat_body);
let instance = builder.instantiate();
// Bug 4: Throwing in StringAdd must clear the "thread in wasm" bit.
let f2 = instance.exports.concat;
assertThrows(() => f2("1234567890")); // 650M characters is too much.
// Bug 5: Operations that can trap must not be marked as kEliminatable,
// otherwise the trap may be eliminated.
for (let i = 0; i < 3; i++) f2("a"); // 65M characters is okay.
%WasmTierUpFunction(instance, concat.index);
assertThrows(() => f2("1234567890")); // Optimized code still traps.