diff --git a/include/hx/QuickVec.h b/include/hx/QuickVec.h index 242790443..d8f51c5ca 100644 --- a/include/hx/QuickVec.h +++ b/include/hx/QuickVec.h @@ -10,8 +10,8 @@ namespace hx template struct QuickVec { - int mAlloc; - int mSize; + size_t mAlloc; + size_t mSize; T *mPtr; QuickVec() : mPtr(0), mAlloc(0), mSize(0) { } @@ -26,7 +26,7 @@ struct QuickVec if (mSize+1>mAlloc) { mAlloc = 10 + (mSize*3/2); - mPtr = (T *)realloc(mPtr,sizeof(T)*mAlloc); + mPtr = static_cast(realloc(mPtr,sizeof(T)*mAlloc)); } mPtr[mSize]=inT; mSize++; @@ -37,31 +37,31 @@ struct QuickVec std::swap(mSize, inOther.mSize); std::swap(mPtr, inOther.mPtr); } - T *setSize(int inSize) + T *setSize(size_t inSize) { if (inSize>mAlloc) { mAlloc = inSize; - mPtr = (T *)realloc(mPtr,sizeof(T)*mAlloc); + mPtr = static_cast(realloc(mPtr,sizeof(T)*mAlloc)); } mSize = inSize; return mPtr; } // Can push this many without realloc - bool hasExtraCapacity(int inN) + bool hasExtraCapacity(size_t inN) { return mSize+inN<=mAlloc; } - bool safeReserveExtra(int inN) + bool safeReserveExtra(size_t inN) { - int want = mSize + inN; + size_t want{ mSize + inN }; if (want>mAlloc) { - int wantAlloc = 10 + (mSize*3/2); + size_t wantAlloc{ 10 + (mSize * 3 / 2) }; if (wantAlloc(malloc( sizeof(T)*wantAlloc )); if (!newBuffer) return false; mAlloc = wantAlloc; @@ -80,12 +80,12 @@ struct QuickVec { return mPtr[--mSize]; } - inline void qerase(int inPos) + inline void qerase(size_t inPos) { --mSize; mPtr[inPos] = mPtr[mSize]; } - inline void erase(int inPos) + inline void erase(size_t inPos) { --mSize; if (mSize>inPos) @@ -95,31 +95,33 @@ struct QuickVec inline bool qerase_val(T inVal) { - for(int i=0;i=mAlloc) { mAlloc = 10 + (mSize*3/2); - mPtr = (T *)realloc(mPtr,sizeof(T)*mAlloc); + mPtr = static_cast(realloc(mPtr,sizeof(T)*mAlloc)); } return mSize++; } - inline int size() const { return mSize; } - inline T &operator[](int inIndex) { return mPtr[inIndex]; } - inline const T &operator[](int inIndex) const { return mPtr[inIndex]; } + inline size_t size() const { return mSize; } + inline T &operator[](size_t inIndex) { return mPtr[inIndex]; } + inline const T &operator[](size_t inIndex) const { return mPtr[inIndex]; } private: QuickVec(const QuickVec &); @@ -138,8 +140,8 @@ class QuickDeque QuickVec mSpare; QuickVec mActive; - int mHeadPos; - int mTailPos; + size_t mHeadPos; + size_t mTailPos; Slab *mHead; Slab *mTail; @@ -153,9 +155,9 @@ class QuickDeque } ~QuickDeque() { - for(int i=0;i #include +namespace +{ + // It took until C++26 for them to add saturating arithmetic! + // So lets have some very basic saturating maths helpers. + // Funky branchless saturating from https://web.archive.org/web/20190213215419/https://locklessinc.com/articles/sat_arithmetic/ + + template + T saturating_add(T x, T delta) + { + T res = x + delta; + res |= -(res < x); + + return res; + } + + template + T saturating_sub(T x, T delta) + { + T res = x - delta; + res &= -(res <= x); + + return res; + } +} static bool sgIsCollecting = false; @@ -648,12 +672,12 @@ struct BlockDataStats fraggedRows += inOther.fraggedRows; } - int rowsInUse; + size_t rowsInUse; size_t bytesInUse; - int emptyBlocks; - int fragScore; - int fraggedBlocks; - int fraggedRows; + size_t emptyBlocks; + size_t fragScore; + size_t fraggedBlocks; + size_t fraggedRows; }; static BlockDataStats sThreadBlockDataStats[MAX_GC_THREADS]; @@ -728,13 +752,13 @@ struct BlockDataInfo unsigned int allocStart[IMMIX_LINES]; HoleRange mRanges[MAX_HOLES]; - int mHoles; + uint8_t mHoles; - int mUsedRows; - int mMaxHoleSize; + uint8_t mUsedRows; + uint16_t mMaxHoleSize; int mMoveScore; - int mUsedBytes; - int mFraggedRows; + uint16_t mUsedBytes; + uint8_t mFraggedRows; bool mPinned; unsigned char mZeroed; bool mReclaimed; @@ -800,7 +824,7 @@ struct BlockDataInfo void makeFull() { mUsedRows = IMMIX_USEFUL_LINES; - mUsedBytes = mUsedRows<mRowMarked+IMMIX_HEADER_LINES, 1,IMMIX_USEFUL_LINES); mRanges[0].start = 0; @@ -841,7 +865,7 @@ struct BlockDataInfo if (!mReclaimed) reclaim(0); - for(int i=0;i>8) & 0xff) + ((total>>16)&0xff) + ((total>>24)&0xff); - mUsedBytes = mUsedRows<((IMMIX_USEFUL_LINES - mUsedRows) << IMMIX_LINE_BITS) }; if (left(IMMIX_USEFUL_LINES << IMMIX_LINE_BITS); mUsedRows = 0; mHoles = 1; mMoveScore = 0; @@ -1101,15 +1125,15 @@ struct BlockDataInfo mMaxHoleSize = 0; for(int h=0;hstart; - int l = ranges->length; + uint16_t s{ ranges->start }; + uint16_t l{ ranges->length }; freeLines += l; ZERO_MEM(allocStart+s, l*sizeof(int)); - int sBytes = s<(s << IMMIX_LINE_BITS) }; ranges->start = sBytes; - int lBytes = l<(l << IMMIX_LINE_BITS) }; ranges->length = lBytes; if (lBytes>mMaxHoleSize) @@ -1121,7 +1145,7 @@ struct BlockDataInfo mHoles = hole; } - mUsedBytes = FULL ? usedBytes : (mUsedRows<3 ? mHoles-3 : 0) + 8 * (mUsedRows<(mHoles, 3) + 8 * (mUsedRows<getUsedRows() > inB->getUsedRows(); -} - -bool BiggestFreeFirst(BlockDataInfo *inA, BlockDataInfo *inB) -{ - return inA->mMaxHoleSize > inB->mMaxHoleSize; -} -bool SmallestFreeFirst(BlockDataInfo *inA, BlockDataInfo *inB) +static bool SmallestFreeFirst(BlockDataInfo *inA, BlockDataInfo *inB) { return inA->mMaxHoleSize < inB->mMaxHoleSize; } - -bool LeastUsedFirst(BlockDataInfo *inA, BlockDataInfo *inB) -{ - return inA->getUsedRows() < inB->getUsedRows(); -} - - - -bool SortMoveOrder(BlockDataInfo *inA, BlockDataInfo *inB) +static bool SortMoveOrder(BlockDataInfo *inA, BlockDataInfo *inB) { return inA->mMoveScore > inB->mMoveScore; } - namespace hx { @@ -3955,7 +3957,7 @@ class GlobalAllocator unsigned int *srcStart = from->allocStart; // Scan nursery for survivors - for(int hole = 0; holemHoles; hole++) + for (uint8_t hole{ 0 }; hole < from->mHoles; hole++) { int start = from->mRanges[hole].start; int len = from->mRanges[hole].length; @@ -5443,7 +5445,7 @@ class GlobalAllocator } } - int extra = std::max( mAllBlocks.size(), 8<(8 << IMMIX_BLOCK_GROUP_BITS)) }; mFreeBlocks.safeReserveExtra(extra); std::sort(&mFreeBlocks[0], &mFreeBlocks[0] + mFreeBlocks.size(), SmallestFreeFirst ); @@ -5763,10 +5765,10 @@ static int sFragIgnore=0; class LocalAllocator : public hx::StackContext { - int mCurrentHole; - int mCurrentHoles; + uint8_t mCurrentHole; + uint8_t mCurrentHoles; HoleRange *mCurrentRange; - int *mFraggedRows; + uint8_t *mFraggedRows; bool mMoreHoles; @@ -6257,7 +6259,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 += (s - spaceFirst)>>IMMIX_LINE_BITS; + *mFraggedRows += static_cast((s - spaceFirst) >> IMMIX_LINE_BITS); #else #ifdef HXCPP_ALIGN_ALLOC if (!(size_t{ spaceStart } & 0x4)) @@ -6294,7 +6296,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 @@ -6308,7 +6310,7 @@ class LocalAllocator : public hx::StackContext spaceStart = mCurrentRange[mCurrentHole].start; spaceEnd = spaceStart + mCurrentRange[mCurrentHole].length; #endif - mCurrentHole++; + mCurrentHole = saturating_add(mCurrentHole, 1); mMoreHoles = mCurrentHole