Skip to content

fix(gc): preserve young logs across promotion rollback - #9924

Closed
proggeramlug wants to merge 2 commits into
PerryTS:mainfrom
proggeramlug:fix/9907-set-full-program
Closed

fix(gc): preserve young logs across promotion rollback#9924
proggeramlug wants to merge 2 commits into
PerryTS:mainfrom
proggeramlug:fix/9907-set-full-program

Conversation

@proggeramlug

@proggeramlug proggeramlug commented Sep 6, 2026

Copy link
Copy Markdown
Contributor

The first copying minor can speculatively retag nursery blocks as PromotedYoung, trace them, then roll back when measured survival is low. Young-entry side-table scanners treated that temporary space as ordinary old generation and drained their remembered keys during the speculative trace. The evacuation retry then skipped roots reachable only through those tables, causing nondeterministic corruption such as Set.prototype.add is not a function during Claude-of-Duty world construction.

Keep PromotedYoung addresses minor-relevant until the promotion commits, using the existing cached heap-space classifier. This preserves the logs across rollback while allowing the next ordinary minor to discard entries after a successful promotion. The regression test forces a traced first-cycle rollback with a young value reachable only through a closure side table; it fails before the fix because the retry leaves the stale from-space address.

Validation:

  • full Claude-of-Duty compile and default-policy boot through world, weapons, and FX initialization
  • diagnostic boot with first-cycle rollback at 265 permille survival; retry copied 39,875 objects and retained descriptor, transition, and closure log entries
  • cargo test -p perry-runtime --profile perry-dev -- --test-threads=1 (3,243 passed, 4 ignored; 8 doc tests ignored)
  • cargo test -p perry-stdlib --profile perry-dev -- --test-threads=1 (132 passed)
  • ./scripts/run_lint_gates.sh (all 64 gates passed; 2 CI-only expressions skipped locally)

Fixes #9907

Summary by CodeRabbit

  • Bug Fixes

    • Preserved young-object tracking when speculative in-place promotion is rolled back.
    • Prevented live objects from being lost or corrupted during evacuation retries, including during application startup.
  • Tests

    • Added end-to-end coverage for retrying evacuation after a failed speculative promotion.

@coderabbitai

coderabbitai Bot commented Sep 6, 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: Team

Run ID: 1e2b2e58-f6c3-4c23-a0ce-44cfddebdb76

📥 Commits

Reviewing files that changed from the base of the PR and between 87dc334 and ab2e651.

📒 Files selected for processing (3)
  • changelog.d/9924-gc-promotion-rollback-young-logs.md
  • crates/perry-runtime/src/gc/tests/promote_in_place.rs
  • crates/perry-runtime/src/gc/young_log.rs

Included review availability: Your plan provides up to 8 included reviews per hour; 7 remain after this review.


📝 Walkthrough

Walkthrough

The GC now retains young side-table roots when speculative in-place promotion rolls back. A new integration test verifies retry evacuation of a value reachable only through a young log.

Changes

Promotion rollback handling

Layer / File(s) Summary
Promoted-young classification
crates/perry-runtime/src/gc/young_log.rs
addr_is_minor_relevant uses HeapSpace classification and keeps PromotedYoung addresses minor-relevant during speculative promotion.
Rollback and retry validation
crates/perry-runtime/src/gc/tests/promote_in_place.rs, changelog.d/9924-gc-promotion-rollback-young-logs.md
An end-to-end test verifies that a young side-table root survives rollback and is evacuated during retry. The changelog records the fix.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Merge Risk: ⚪ Minimal · up to ab2e6

This preserves closure side-table roots across failed speculative promotion and verifies that evacuation retry retains the live young value. No merge-blocking risk remains.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely describes the primary change: preserving young logs across garbage-collection promotion rollback.
Description check ✅ Passed The description explains the failure, root cause, implementation, regression test, linked issue, and validation results. It does not use the template headings or complete the checklist, but the requir…
Linked Issues check ✅ Passed The changes directly address issue [#9907] by preserving young-generation roots during speculative promotion rollback. The regression test and reported validation support the fix for the Claude-of-Dut…
Out of Scope Changes check ✅ Passed The changed runtime logic, regression test, and changelog entry all relate to the linked garbage-collection failure. No unrelated code changes are identified.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 3 functions across 2 files. (1 skipped: 1 …
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

@proggeramlug

Copy link
Copy Markdown
Contributor Author

Landed on main via merge train #9939. Validated as a tree: 66/66 lint gates, and perry-runtime/codegen/hir/stdlib all green (5,966 tests, 0 failures). Thanks!

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.

main no longer boots Claude-of-Duty: "Set.prototype.add is not a function" in world construction

1 participant