diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 3eac4e98d..d303e9b82 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -40,6 +40,24 @@ jobs: - name: run run: bin${{ inputs.sep }}TestMain + big_blocks: + runs-on: ${{ inputs.os }} + name: haxe (big blocks) + defaults: + run: + working-directory: test/haxe + steps: + - name: checkout + uses: actions/checkout@v4 + - name: setup + uses: ./.github/workflows/setup + with: + haxe: ${{ inputs.haxe }} + - name: build + run: haxe compile.hxml --debug -D HXCPP_GC_BIG_BLOCKS -D ${{ env.HXCPP_ARCH_FLAG }} + - name: run + run: bin${{ inputs.sep }}TestMain-debug + cffi: runs-on: ${{ inputs.os }} name: cffi diff --git a/src/hx/gc/Immix.cpp b/src/hx/gc/Immix.cpp index 4cfefb4ea..7de470b6b 100644 --- a/src/hx/gc/Immix.cpp +++ b/src/hx/gc/Immix.cpp @@ -12,6 +12,7 @@ #include #include #include +#include #ifdef __EMSCRIPTEN__ #include @@ -494,13 +495,13 @@ extern void scriptMarkStack(hx::MarkContext *); using BlockIdType = unsigned short; #endif -constexpr uint16_t IMMIX_BLOCK_SIZE{ 1 << IMMIX_BLOCK_BITS }; +constexpr uint32_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 uint16_t IMMIX_USEFUL_LINES{ IMMIX_LINES - IMMIX_HEADER_LINES }; constexpr uint8_t IMMIX_MAX_ALLOC_GROUPS_SIZE{ 1 << IMMIX_BLOCK_GROUP_BITS }; // Every second line used @@ -750,11 +751,11 @@ struct BlockDataInfo HoleRange mRanges[MAX_HOLES]; uint8_t mHoles; - uint8_t mUsedRows; + uint16_t mUsedRows; uint16_t mMaxHoleSize; int mMoveScore; uint16_t mUsedBytes; - uint8_t mFraggedRows; + uint16_t mFraggedRows; bool mPinned; unsigned char mZeroed; bool mReclaimed; @@ -894,8 +895,22 @@ struct BlockDataInfo bool isEmpty() const { return mUsedRows == 0; } int getUsedRows() const { return mUsedRows; } + // A row count above the block's useful lines is corrupted GC state, about to be + // added into the heap stats that size working memory. + void checkRowCounts() const + { + #ifdef HXCPP_DEBUG + if (mUsedRows>IMMIX_USEFUL_LINES || mFraggedRows>IMMIX_USEFUL_LINES) + { + GCLOG("Bad block row counts: used %d, fragged %d, max %d\n", (int)mUsedRows, (int)mFraggedRows, (int)IMMIX_USEFUL_LINES); + DebuggerTrap(); + } + #endif + } + void getStats(BlockDataStats &outStats) { + checkRowCounts(); outStats.rowsInUse += mUsedRows; outStats.bytesInUse += mUsedBytes; outStats.fraggedRows += mFraggedRows; @@ -976,6 +991,7 @@ struct BlockDataInfo mZeroLock = 0; mOwned = false; + checkRowCounts(); outStats.rowsInUse += mUsedRows; outStats.bytesInUse += mUsedBytes; outStats.fraggedRows += mFraggedRows; @@ -1145,6 +1161,7 @@ struct BlockDataInfo mMoveScore = calcFragScore(); mReclaimed = true; + checkRowCounts(); if (outStats) { outStats->rowsInUse += mUsedRows; @@ -1414,6 +1431,11 @@ struct BlockDataInfo #endif }; +static_assert(IMMIX_USEFUL_LINES <= std::numeric_limits::max(), + "BlockDataInfo::mUsedRows must hold IMMIX_USEFUL_LINES"); +static_assert(IMMIX_USEFUL_LINES <= std::numeric_limits::max(), + "BlockDataInfo::mFraggedRows must hold IMMIX_USEFUL_LINES"); + static bool SmallestFreeFirst(BlockDataInfo *inA, BlockDataInfo *inB) { return inA->mMaxHoleSize < inB->mMaxHoleSize; @@ -5764,7 +5786,7 @@ class LocalAllocator : public hx::StackContext uint8_t mCurrentHole; uint8_t mCurrentHoles; HoleRange *mCurrentRange; - uint8_t *mFraggedRows; + uint16_t *mFraggedRows; bool mMoreHoles; @@ -6255,7 +6277,7 @@ class LocalAllocator : public hx::StackContext // spaceOversize might have been set to zero for quick-termination of alloc. unsigned char* s{ spaceOversize }; if (s>spaceFirst && mFraggedRows) - *mFraggedRows += static_cast((s - spaceFirst) >> IMMIX_LINE_BITS); + *mFraggedRows += static_cast((s - spaceFirst) >> IMMIX_LINE_BITS); #else #ifdef HXCPP_ALIGN_ALLOC if (!(size_t{ spaceStart } & 0x4)) @@ -6292,7 +6314,7 @@ class LocalAllocator : public hx::StackContext } if (mFraggedRows && spaceEnd > spaceStart) { - *mFraggedRows += static_cast((spaceEnd - spaceStart) >> IMMIX_LINE_BITS); + *mFraggedRows += static_cast((spaceEnd - spaceStart) >> IMMIX_LINE_BITS); } #endif