From ae7f11536b3dcd00c6c967e2a89f4596762da75b Mon Sep 17 00:00:00 2001 From: Aidan Lee Date: Sat, 10 Oct 2026 21:27:27 +0100 Subject: [PATCH 1/2] Use an appropriately sized type for block row indexing --- src/hx/gc/Immix.cpp | 85 ++++++++++++++++++++++++--------------------- 1 file changed, 46 insertions(+), 39 deletions(-) diff --git a/src/hx/gc/Immix.cpp b/src/hx/gc/Immix.cpp index 4cfefb4ea..005151efc 100644 --- a/src/hx/gc/Immix.cpp +++ b/src/hx/gc/Immix.cpp @@ -489,19 +489,21 @@ extern void scriptMarkStack(hx::MarkContext *); #ifdef HXCPP_GC_BIG_BLOCKS constexpr uint8_t IMMIX_BLOCK_BITS{ 16 }; using BlockIdType = unsigned int; + using BlockRowType = uint16_t; #else constexpr uint8_t IMMIX_BLOCK_BITS{ 15 }; using BlockIdType = unsigned short; + using BlockRowType = uint8_t; #endif -constexpr uint16_t IMMIX_BLOCK_SIZE{ 1 << IMMIX_BLOCK_BITS }; -constexpr uint16_t IMMIX_BLOCK_OFFSET_MASK{ IMMIX_BLOCK_SIZE - 1 }; -constexpr uint8_t IMMIX_LINE_COUNT_BITS{ IMMIX_BLOCK_BITS - IMMIX_LINE_BITS }; -constexpr uint16_t IMMIX_LINES{ 1 << IMMIX_LINE_COUNT_BITS }; -constexpr uintptr_t IMMIX_BLOCK_BASE_MASK{ ~uintptr_t{ IMMIX_BLOCK_OFFSET_MASK } }; -constexpr uint8_t IMMIX_HEADER_LINES{ IMMIX_LINES >> IMMIX_LINE_BITS }; -constexpr uint8_t IMMIX_USEFUL_LINES{ IMMIX_LINES - IMMIX_HEADER_LINES }; -constexpr uint8_t IMMIX_MAX_ALLOC_GROUPS_SIZE{ 1 << IMMIX_BLOCK_GROUP_BITS }; +constexpr uint8_t IMMIX_LINE_COUNT_BITS{ IMMIX_BLOCK_BITS - IMMIX_LINE_BITS }; +constexpr size_t IMMIX_BLOCK_BYTE_COUNT{ 1 << IMMIX_BLOCK_BITS }; +constexpr size_t IMMIX_BLOCK_LINE_COUNT{ 1 << IMMIX_LINE_COUNT_BITS }; +constexpr uintptr_t IMMIX_BLOCK_OFFSET_MASK{ IMMIX_BLOCK_BYTE_COUNT - 1 }; +constexpr uintptr_t IMMIX_BLOCK_BASE_MASK{ ~IMMIX_BLOCK_OFFSET_MASK }; +constexpr uint8_t IMMIX_HEADER_LINES{ IMMIX_BLOCK_LINE_COUNT >> IMMIX_LINE_BITS }; +constexpr BlockRowType IMMIX_USEFUL_LINES{ IMMIX_BLOCK_LINE_COUNT - IMMIX_HEADER_LINES }; +constexpr uint8_t IMMIX_MAX_ALLOC_GROUPS_SIZE{ 1 << IMMIX_BLOCK_GROUP_BITS }; // Every second line used constexpr uint8_t MAX_HOLES{ IMMIX_USEFUL_LINES >> 1 }; @@ -645,13 +647,13 @@ union BlockData BlockIdType mId; // First 2/4 rows contain a byte-flag-per-row - unsigned char mRowMarked[IMMIX_LINES]; + unsigned char mRowMarked[IMMIX_BLOCK_LINE_COUNT]; // Row data as union - don't use first 2/4 rows - unsigned char mData[IMMIX_LINES * IMMIX_LINE_LEN]; + unsigned char mData[IMMIX_BLOCK_LINE_COUNT * IMMIX_LINE_LEN]; - inline unsigned char* row(size_t r) + inline unsigned char* row(BlockRowType r) { - return mData + (r * IMMIX_LINE_LEN); + return mData + (size_t{ r } * IMMIX_LINE_LEN); } }; @@ -745,16 +747,16 @@ struct BlockDataInfo int mGroupId; BlockData *mPtr; - unsigned int allocStart[IMMIX_LINES]; + unsigned int allocStart[IMMIX_BLOCK_LINE_COUNT]; HoleRange mRanges[MAX_HOLES]; uint8_t mHoles; - uint8_t mUsedRows; + BlockRowType mUsedRows; uint16_t mMaxHoleSize; int mMoveScore; uint16_t mUsedBytes; - uint8_t mFraggedRows; + BlockRowType mFraggedRows; bool mPinned; unsigned char mZeroed; bool mReclaimed; @@ -804,7 +806,7 @@ struct BlockDataInfo mUsedBytes = 0; mFraggedRows = 0; mPinned = false; - ZERO_MEM(allocStart,sizeof(int)*IMMIX_LINES); + ZERO_MEM(allocStart,sizeof(int)*IMMIX_BLOCK_LINE_COUNT); ZERO_MEM(mPtr->mRowMarked+IMMIX_HEADER_LINES, IMMIX_USEFUL_LINES); mRanges[0].start = IMMIX_HEADER_LINES << IMMIX_LINE_BITS; mRanges[0].length = IMMIX_USEFUL_LINES << IMMIX_LINE_BITS; @@ -913,8 +915,10 @@ struct BlockDataInfo { unsigned char *rowMarked = mPtr->mRowMarked; - for(int r = IMMIX_HEADER_LINES; r> IMMIX_LINE_BITS }; // Out of bounds - can't be a new object start - if (r < IMMIX_HEADER_LINES || r >= IMMIX_LINES) + if (r < IMMIX_HEADER_LINES || r >= IMMIX_BLOCK_LINE_COUNT) { return allocNone; } @@ -1304,7 +1308,7 @@ struct BlockDataInfo if (blockOffset >= 0) { uintptr_t r{ blockOffset >> IMMIX_LINE_BITS }; - if (r >= IMMIX_HEADER_LINES && r < IMMIX_LINES) + if (r >= IMMIX_HEADER_LINES && r < IMMIX_BLOCK_LINE_COUNT) { // Normal, good alloc unsigned int rowPos{ hx::gImmixStartFlag[blockOffset & 127] }; @@ -1355,14 +1359,15 @@ struct BlockDataInfo return; unsigned char *rowMarked = mPtr->mRowMarked; - for(int r=IMMIX_HEADER_LINES;rrow(static_cast(r)) }; + unsigned char* row{ mPtr->row(r) }; for(int i=0;i<32;i++) { int pos = i<<2; @@ -1386,8 +1391,10 @@ struct BlockDataInfo #ifdef HXCPP_GC_VERIFY void verify(const char *inWhere) { - for(int i=IMMIX_HEADER_LINES;imPtr->mRowMarked; - for(int r=IMMIX_HEADER_LINES;r(from->mPtr->row(static_cast(r))) }; + unsigned int* row{ reinterpret_cast(from->mPtr->row(r)) }; unsigned int &header{ row[i] }; if ((header&IMMIX_ALLOC_MARK_ID) == hx::gMarkID) @@ -3785,7 +3792,7 @@ class GlobalAllocator } while(destInfo->mHoles==0); - ioStats.rowsInUse += IMMIX_USEFUL_LINES - destInfo->mUsedRows; + ioStats.rowsInUse += saturating_sub(IMMIX_USEFUL_LINES, destInfo->mUsedRows); //destInfo->zero(); dest = destInfo->mPtr; destStarts = destInfo->allocStart; @@ -5139,7 +5146,7 @@ class GlobalAllocator if ( allMem > sWorkingMemorySize + allowExtra ) { #if defined(SHOW_FRAGMENTATION) || defined(SHOW_MEM_EVENTS) - int releaseGroups = (int)((allMem - sWorkingMemorySize) / (IMMIX_BLOCK_SIZE<spaceFirst && mFraggedRows) - *mFraggedRows += static_cast((s - spaceFirst) >> IMMIX_LINE_BITS); + *mFraggedRows = saturating_add(*mFraggedRows, static_cast((s - spaceFirst) >> IMMIX_LINE_BITS)); #else #ifdef HXCPP_ALIGN_ALLOC if (!(size_t{ spaceStart } & 0x4)) @@ -6292,7 +6299,7 @@ class LocalAllocator : public hx::StackContext } if (mFraggedRows && spaceEnd > spaceStart) { - *mFraggedRows += static_cast((spaceEnd - spaceStart) >> IMMIX_LINE_BITS); + *mFraggedRows = saturating_add(*mFraggedRows, static_cast((spaceEnd - spaceStart) >> IMMIX_LINE_BITS)); } #endif From 404fa2ad6d55b7d8ec2886d86635a76cbc7bbd9c Mon Sep 17 00:00:00 2001 From: Aidan Lee Date: Mon, 12 Oct 2026 12:03:34 +0100 Subject: [PATCH 2/2] Fix compilation with HX_GC_VERIFY_ALLOC_START --- src/hx/gc/Immix.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hx/gc/Immix.cpp b/src/hx/gc/Immix.cpp index 005151efc..6415bc7c2 100644 --- a/src/hx/gc/Immix.cpp +++ b/src/hx/gc/Immix.cpp @@ -917,7 +917,7 @@ struct BlockDataInfo for (BlockRowType i{ 0 }; i < IMMIX_USEFUL_LINES; i++) { - BlockRowType r{ saturating_add(i, IMMIX_HEADER_LINES) }; + BlockRowType r{ saturating_add(i, BlockRowType{ IMMIX_HEADER_LINES }) }; if (!rowMarked[r] && allocStart[r]) {