Skip to content

fix(interp): make recursive trace boundary explicit - #185

Open
siyul-park wants to merge 2 commits into
mainfrom
fix/issue-184-fannkuch-jit
Open

fix(interp): make recursive trace boundary explicit#185
siyul-park wants to merge 2 commits into
mainfrom
fix/issue-184-fannkuch-jit

Conversation

@siyul-park

@siyul-park siyul-park commented Aug 10, 2026

Copy link
Copy Markdown
Owner

Summary

Fixes #184.

The Fannkuch compare benchmark could produce incorrect results in default and jit modes while threaded remained correct.

Root cause

The trace recorder used skipCall when it encountered a recursive CALL. That is only sound when the recorder can model the call's effects. skipCall supplies placeholder return values and does not reproduce the callee's heap mutations.

A recursive call encountered inside a non-entry loop trace could therefore leave the recorder with a speculative VM/heap state that never existed. Fannkuch exposes this because its recursive permutation routine mutates a shared array and continues execution after the call.

Fix

Treat recursive calls in non-entry loop traces as a trace boundary. The native prefix is retained, the real recursive call executes through the threaded path, and the post-call continuation can be captured from the actual frame and heap state.

Function-entry self-recursion keeps the existing native selfCall path, so the fix does not disable native recursive-call lowering globally or reject heap mutation from JIT plans.

The JIT trace contract documentation is updated to describe the boundary explicitly.

Validation

  • go test -race ./...
  • go vet ./...
  • go test -tags=compare -run='^$' -bench='^BenchmarkCall_Fannkuch$' -benchtime=1x -count=5
  • git diff --check

The Fannkuch compare benchmark passes for default, threaded, jit, native, gpython, and cpython on the ARM64 development machine.

Summary by CodeRabbit

  • Bug Fixes

    • Improved tracing for recursive calls within loop-based execution paths.
    • Calls to non-entry instructions now terminate the current trace cleanly and resume through standard execution, enabling subsequent continuation tracing.
    • Function-entry recursive calls continue to use native handling.
  • Documentation

    • Updated JIT internals documentation to describe the different handling of recursive calls in loop and function-entry traces.

@coderabbitai

coderabbitai Bot commented Aug 10, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 50dc5748-8074-4c47-a2f0-9dececd6f72c

📥 Commits

Reviewing files that changed from the base of the PR and between 8d3dc21 and 4dc7a9c.

📒 Files selected for processing (2)
  • docs/jit-internals.md
  • interp/trace.go

📝 Walkthrough

Walkthrough

The tracer now terminates non-entry recursive calls as partial trace cuts. Function-entry self-calls retain native lowering. The JIT internals documentation describes both behaviors.

Changes

Recursive call trace cuts

Layer / File(s) Summary
Publish partial traces for non-entry calls
interp/trace.go, docs/jit-internals.md
Non-entry recursive calls record a terminal cut and publish a partial trace. Entry-anchor calls retain the existing inline path. The documentation describes continuation compilation from the real callee state and native function-entry self-calls.

Estimated code review effort: 2 (Simple) | ~10 minutes

Possibly related PRs

  • siyul-park/minivm#137: Both changes modify terminal cuts and partial trace recording in interp/trace.go.
  • siyul-park/minivm#160: Both changes address loop-trace call and continuation handling and document JIT control flow.
  • siyul-park/minivm#161: Both changes modify recursive call capture and related JIT documentation.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Linked Issues check ⚠️ Warning The fix addresses the Fannkuch correctness failure and recursive trace handling [#184], but no focused regression test was added. Add a focused regression test that fails before the fix and verifies consistent Fannkuch results across supported execution modes.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly identifies the interpreter fix that makes recursive trace boundaries explicit, matching the main changes.
Description check ✅ Passed The description explains the failure, root cause, fix, validation, and linked issue, although it uses different section headings.
Out of Scope Changes check ✅ Passed The interpreter change and JIT documentation update directly support the recursive trace-boundary fix and Fannkuch correctness objective [#184].
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/issue-184-fannkuch-jit

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@siyul-park siyul-park changed the title fix(interp): preserve recursive loop trace correctness fix(interp): make recursive trace boundary explicit Aug 10, 2026
@siyul-park
siyul-park marked this pull request as ready for review August 10, 2026 14:40
@siyul-park siyul-park self-assigned this Aug 10, 2026
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.

test(benchmarks): Fannkuch default and JIT fail correctness under compare

1 participant