diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 14:29:10 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 14:29:10 +0000 |
commit | 2aa4a82499d4becd2284cdb482213d541b8804dd (patch) | |
tree | b80bf8bf13c3766139fbacc530efd0dd9d54394c /js/src/jit-test/tests/saved-stacks/async-max-frame-count.js | |
parent | Initial commit. (diff) | |
download | firefox-upstream.tar.xz firefox-upstream.zip |
Adding upstream version 86.0.1.upstream/86.0.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'js/src/jit-test/tests/saved-stacks/async-max-frame-count.js')
-rw-r--r-- | js/src/jit-test/tests/saved-stacks/async-max-frame-count.js | 99 |
1 files changed, 99 insertions, 0 deletions
diff --git a/js/src/jit-test/tests/saved-stacks/async-max-frame-count.js b/js/src/jit-test/tests/saved-stacks/async-max-frame-count.js new file mode 100644 index 0000000000..bada5b1ac9 --- /dev/null +++ b/js/src/jit-test/tests/saved-stacks/async-max-frame-count.js @@ -0,0 +1,99 @@ +// Test that async stacks are limited on recursion. + +const defaultAsyncStackLimit = 60; + +function recur(n, limit) { + if (n > 0) { + return callFunctionWithAsyncStack(function recur() {return recur(n - 1, limit)}, + saveStack(limit), "Recurse"); + } + return saveStack(limit); +} + +function checkRecursion(n, limit) { + print("checkRecursion(" + String(n) + ", " + String(limit) + ")"); + + try { + var stack = recur(n, limit); + } catch (e) { + // Some platforms, like ASAN builds, can end up overrecursing. Tolerate + // these failures. + assertEq(/too much recursion/.test("" + e), true); + return; + } + + // Async stacks are limited even if we didn't ask for a limit. There is a + // default limit on frames attached on top of any synchronous frames, and + // every time the limit is reached when capturing, half of the frames are + // truncated from the old end of the async stack. + if (limit == 0) { + // Always add one synchronous frame that is the last call to `recur`. + if (n + 1 < defaultAsyncStackLimit) { + limit = defaultAsyncStackLimit + 1; + } else { + limit = n + 2 - (defaultAsyncStackLimit / 2); + } + } + + // The first `n` or `limit` frames should have `recur` as their `asyncParent`. + for (var i = 0; i < Math.min(n, limit); i++) { + assertEq(stack.functionDisplayName, "recur"); + assertEq(stack.parent, null); + stack = stack.asyncParent; + } + + // This frame should be the first call to `recur`. + if (limit > n) { + assertEq(stack.functionDisplayName, "recur"); + assertEq(stack.asyncParent, null); + stack = stack.parent; + } else { + assertEq(stack, null); + } + + // This frame should be the call to `checkRecursion`. + if (limit > n + 1) { + assertEq(stack.functionDisplayName, "checkRecursion"); + assertEq(stack.asyncParent, null); + stack = stack.parent; + } else { + assertEq(stack, null); + } + + // We should be at the top frame, which is the test script itself. + if (limit > n + 2) { + assertEq(stack.functionDisplayName, null); + assertEq(stack.asyncParent, null); + assertEq(stack.parent, null); + } else { + assertEq(stack, null); + } +} + +// Check capturing with no limit, which should still apply a default limit. +checkRecursion(0, 0); +checkRecursion(1, 0); +checkRecursion(2, 0); +checkRecursion(defaultAsyncStackLimit - 10, 0); +checkRecursion(defaultAsyncStackLimit, 0); +checkRecursion(defaultAsyncStackLimit + 10, 0); + +// Limit of 1 frame. +checkRecursion(0, 1); +checkRecursion(1, 1); +checkRecursion(2, 1); + +// Limit of 2 frames. +checkRecursion(0, 2); +checkRecursion(1, 2); +checkRecursion(2, 2); + +// Limit of 3 frames. +checkRecursion(0, 3); +checkRecursion(1, 3); +checkRecursion(2, 3); + +// Limit higher than the default limit. +checkRecursion(defaultAsyncStackLimit + 10, defaultAsyncStackLimit + 10); +checkRecursion(defaultAsyncStackLimit + 11, defaultAsyncStackLimit + 10); +checkRecursion(defaultAsyncStackLimit + 12, defaultAsyncStackLimit + 10); |