Skip to content

Allocate block-exceeding tokens directly in the old generation#1219

Merged
Robertorosmaninho merged 5 commits into
developfrom
fix-large-token-young-gen
Jun 23, 2026
Merged

Allocate block-exceeding tokens directly in the old generation#1219
Robertorosmaninho merged 5 commits into
developfrom
fix-large-token-young-gen

Conversation

@Robertorosmaninho

Copy link
Copy Markdown
Collaborator

While running large MegaETH workloads under the LLVM backend we hit a crash in kore_collect / arena::evacuate while migrating a block with a corrupted header. The culprit is a String token larger than a block: init_with_len correctly flags it NOT_YOUNG, but kore_alloc_token was still allocating it in the young semispace. The collector never migrates a NOT_YOUNG object out of the young from-space, which is reclaimed on every collection, so the token dangled — a later allocation overwrote its bytes and the next collection walked a garbage header. It reproduces independently of the hyperblock size.

The fix routes tokens larger than BLOCK_SIZE to oldspace (matching what hook_BUFFER_concat_raw already does for large buffers) and sets AGE_MASK on the NOT_YOUNG header so is_in_old_gen_hdr() recognises the block as a live old-generation object. The oversized branch is kept in a cold, out-of-line helper (__builtin_expect) so the common small-token path of the always_inline kore_alloc_token isn't bloated at every call site.

I also added test-gc-large-token: it builds a single > 1 MiB token, keeps it live across forced collections that reuse the abandoned young region, then reads it back. The test crashes on the buggy version (the collector walks the dangling token) and passes with the fix; the rest of the GC and unit suites are unaffected.

This is safe for the hot path: small-token allocation is unchanged apart from one predicted-not-taken branch, and the oversized path is rare. Instruction counts on an allocation-heavy benchmark are flat versus before, and the full lit suite stays green.

@Robertorosmaninho Robertorosmaninho force-pushed the fix-large-token-young-gen branch from a9f1274 to 3b86377 Compare June 18, 2026 19:05
A token whose payload exceeds a block (`BLOCK_SIZE`) is flagged `NOT_YOUNG`
by `init_with_len`, but `kore_alloc_token` was still placing it in the young
semispace. The collector never migrates a `NOT_YOUNG` object out of the young
from-space, which is reclaimed on every collection, so any such token dangled:
a later allocation overwrote its bytes and a subsequent collection crashed
walking the corrupted header (we hit this in `kore_collect` -> `arena::evacuate`
-> `migrate` on large MegaETH workloads; it reproduces independently of the
hyperblock size).

We route those allocations to `oldspace`, matching the existing large-buffer
handling in `hook_BUFFER_concat_raw`, and add `AGE_MASK` to the `NOT_YOUNG`
header so `is_in_old_gen_hdr()` recognises the block as a live old-generation
object.

The oversized case is kept in a cold, out-of-line helper guarded by
`__builtin_expect` so the common small-token path of the `always_inline`
`kore_alloc_token` is not bloated at every call site.
`test-gc-large-token` builds a single > 1 MiB `String` token, keeps it live in
the `<keep>` cell across collections that reuse the abandoned young region, and
reads it back. Without the previous commit the run crashes while the collector
walks the dangling token's corrupted header; with it the token lives in the old
generation and its length survives intact.
@Robertorosmaninho Robertorosmaninho force-pushed the fix-large-token-young-gen branch from 3b86377 to 57a861a Compare June 18, 2026 19:12

@gtrepta gtrepta left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Comment thread runtime/lto/alloc.cpp Outdated
Comment thread include/runtime/types.h Outdated
Comment thread runtime/lto/alloc.cpp Outdated
Simplified comment regarding allocation size handling in init_with_len function.
Updated comments to clarify allocation behavior for oversized tokens.
@Robertorosmaninho Robertorosmaninho merged commit a32cc6a into develop Jun 23, 2026
10 checks passed
@Robertorosmaninho Robertorosmaninho deleted the fix-large-token-young-gen branch June 23, 2026 23:36
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.

2 participants