Skip to content

Fix fragged rows signed-ness regression - #1392

Merged
Aidan63 merged 1 commit into
HaxeFoundation:masterfrom
tobil4sk:fix/fragged-rows-regression
Sep 8, 2026
Merged

Aidan63 merged 1 commit into
HaxeFoundation:masterfrom
tobil4sk:fix/fragged-rows-regression

Conversation

@tobil4sk

@tobil4sk tobil4sk commented Sep 8, 2026

Copy link
Copy Markdown
Member

Fixes a behavioural regression in 952b6ac, which caused the GC to continue allocating more blocks due to sWorkingMemorySize becoming corrupted.

The problem is that if spaceStart is greater than spaceEnd, spaceEnd - spaceStart would give a very large size_t instead of a negative int, and therefore frag > 0 was true and mFraggedRows got updated to a random value. This had a domino effect on various variables before corrupting sWorkingMemorySize.

hxcpp/src/hx/gc/Immix.cpp

Lines 6293 to 6296 in f05b21c

size_t frag{ spaceEnd - spaceStart };
if (frag>0)
*mFraggedRows += int{ static_cast<int>(frag >> IMMIX_LINE_BITS) };
}

outStats.fraggedRows += mFraggedRows;

mRowsInUse = stats.rowsInUse + stats.fraggedRows + freeFraggedRows;

size_t mem = mRowsInUse<<IMMIX_LINE_BITS;

sWorkingMemorySize = std::max( mem + targetFree, (size_t)hx::sgMinimumWorkingMemory);

hxcpp/src/hx/gc/Immix.cpp

Lines 3607 to 3611 in f05b21c

if (!result && allowMoreBlocks() && (!sgInternalEnable || GetWorkingMemory()<sWorkingMemorySize))
{
if (AllocMoreBlocks(forceCompact,false))
result = GetNextFree(inRequiredBytes);
}

I haven't looked into whether it even makes sense for spaceStart to be bigger than spaceEnd, but for now this brings back the old logic by skipping the update in that case.

@Aidan63
Aidan63 merged commit 022466f into HaxeFoundation:master Sep 8, 2026
289 of 290 checks passed
@tobil4sk
tobil4sk deleted the fix/fragged-rows-regression branch September 8, 2026 18:22
dimensionscape added a commit to openfl/libhxcpp that referenced this pull request Oct 15, 2026
When a collection starts, the collecting thread zeroes every other
allocator's spaceEnd (spaceOversize with the nursery) without a lock,
in WaitForSafe. CallAlloc read spaceEnd twice when adding an abandoned
hole to the block's mFraggedRows, once to check it was above spaceStart
and again to subtract, so a collection landing in between gave a
negative difference that wrapped the uint16 count. It reads each of
them once now.

test/gc_stress hit it on Linux in debug builds, where the row-count
check traps: 4 of 8 seeds before, none of 8 after.

Related: HaxeFoundation/hxcpp#1392, HaxeFoundation/hxcpp#1409

Fixes #92
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