Skip to content

Warm the stack-guard recovery test before it measures depth - #3080

Merged
lahma merged 1 commit into
sebastienros:mainfrom
lahma:fix/stack-guard-depth-test-warmup
Aug 20, 2026
Merged

lahma merged 1 commit into
sebastienros:mainfrom
lahma:fix/stack-guard-depth-test-warmup

Conversation

@lahma

@lahma lahma commented Aug 20, 2026 •

Copy link
Copy Markdown
Collaborator

StackOverflowGuardTests.TheEngineIsUnchangedAfterTheGuardFires fails intermittently on CI. Four unrelated branches, four different shapes:

543 / 533 / 533
613 / 533 / 533
705 / 571 / 571
533 / 713 / 696

The test is right about what it wants to detect, and right that a shorter later run is the signal — a frame the unwind failed to release would shorten the next one. But depth here is a count of native stack frames, and that count also moves whenever the JIT re-compiles an interpreter method the recursion runs through, because the promoted code has a different frame size.

The fourth line above is the one that settles the diagnosis: it rises before it falls, and no leaked frame can make a later run go deeper. So this is the runtime, not the engine — but a fall on its own is indistinguishable from the defect the test exists to catch, which is why it cannot simply be given a tolerance.

This discards two rounds before measuring. Two rather than one because the fib(20) recovery check inside each round promotes code of its own, so a single warm-up still left the second measured round moving (533 → 713 → 696). By the third round everything the measurement touches is at its final tier, and the three compared numbers are about the unwind alone. The assertions themselves are unchanged — same equality across three runs, same > 100 floor.

Found while landing the #3021 staging PRs, where it failed on four unrelated branches and cost a CI re-run each time.

🤖 Generated with Claude Code

TheEngineIsUnchangedAfterTheGuardFires asserts that the guard fires at the same
depth on three successive runs, because a frame the unwind failed to release
would shorten a later run. Depth is a count of native stack frames, so it also
moves whenever the JIT re-compiles an interpreter method the recursion runs
through, and the promoted code has a different frame size.

CI produced 543/533/533, 613/533/533, 705/571/571 and 533/713/696 on four
unrelated branches. The last of those rises before it falls, which no leaked
frame can do; a fall on its own is indistinguishable from the defect the test
exists to catch.

Discard two rounds before measuring. Two rather than one because the fib(20)
recovery check inside each round promotes code of its own, so a single warm-up
still left the second measured round moving. The assertions are unchanged.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@lahma
lahma force-pushed the fix/stack-guard-depth-test-warmup branch from 3846ff3 to e120031 Compare August 20, 2026 08:48
@lahma
lahma merged commit e73c0ab into sebastienros:main Aug 20, 2026
5 checks passed
@lahma
lahma deleted the fix/stack-guard-depth-test-warmup branch August 20, 2026 19:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant