Skip to content

Align the objects that jitted cppia code allocates in the nursery - #1411

Open
Tutez64 wants to merge 1 commit into
HaxeFoundation:masterfrom
Tutez64:bugfix/cppia-jit-nursery-align
Open

Tutez64 wants to merge 1 commit into
HaxeFoundation:masterfrom
Tutez64:bugfix/cppia-jit-nursery-align

Conversation

@Tutez64

@Tutez64 Tutez64 commented Oct 3, 2026

Copy link
Copy Markdown

With HXCPP_GC_GENERATIONAL and the cppia JIT, an object referenced only from the stack can be freed by the next collection.

With a generational GC, new objects go into the nursery. ImmixAllocator::alloc skips 4 bytes when it needs to, so that each nursery object is 8-byte aligned (HXCPP_ALIGN_ALLOC, always defined). The scan that finds objects referenced conservatively from the stack (GetEnclosingNurseryType) relies on that alignment when it walks a hole from header to header.

For a new of a script class, the JIT emits its own inline nursery allocation (NewExpr::genCode, under HXCPP_GC_NURSERY), which did not align. After an object the JIT placed off alignment, the scan reads a wrong header and misses the objects that follow in that hole. Any of them referenced only from the stack, script or host, is then freed while still in use. Without the JIT, createInstance allocates through the aligned path, so only -jit was affected.

The fix aligns the JIT's inline allocation the same way as ImmixAllocator::alloc. Builds without a generational GC do not emit this path, so they are unchanged.

The cppia host in test/cppia now builds with HXCPP_GC_GENERATIONAL, so the suite runs with the nursery. The existing tests pass with it in both modes, but none of them forces a collection. The new test calls ClientNursery.allocate, whose two new are jitted with -jit, then keeps an array only on the stack across a generational collection. On master, the -jit run crashes every time (5/5): host objects that only the stack references are freed, and utest crashes on one of them right after the test. With the fix, both modes pass (5/5 each).

With HXCPP_GC_GENERATIONAL, ImmixAllocator::alloc skips 4 bytes when
needed so that each nursery object is 8-byte aligned, and the nursery
scan that finds conservatively referenced objects (GetEnclosingNurseryType)
walks the holes with that alignment. The inline allocation that the JIT
emits for a new did not align. After an object it placed off alignment,
the scan read a wrong header and missed the objects that follow, so an
object referenced only from the stack was freed by the next collection.

The cppia host now builds with HXCPP_GC_GENERATIONAL. The new test has
jitted code allocate two objects, then keeps an array only on the stack
across a generational collection. Without the fix, the -jit run crashes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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