From 8e19a0926f3fcc7e1d5bd1fec6e96de32274619f Mon Sep 17 00:00:00 2001 From: Hugh Sanderson Date: Tue, 17 Sep 2024 16:01:43 +0800 Subject: [PATCH] Fix HXCPP_GC_GENERATIONAL in combination with HXCPP_ALIGN_ALLOC --- include/hx/GC.h | 81 ++++++++++--------- include/hxcpp.h | 2 +- src/hx/gc/Immix.cpp | 148 +++++++++++++++++++++-------------- test/haxe/compile.hxml | 2 +- toolchain/common-defines.xml | 2 + 5 files changed, 140 insertions(+), 95 deletions(-) diff --git a/include/hx/GC.h b/include/hx/GC.h index 5370c142e..a9148c505 100644 --- a/include/hx/GC.h +++ b/include/hx/GC.h @@ -363,7 +363,12 @@ class ImmixAllocator { #ifdef HXCPP_GC_NURSERY + #ifdef HXCPP_ALIGN_ALLOC + // make sure buffer is 8-byte aligned + unsigned char *buffer = alloc->spaceFirst + ( (size_t)alloc->spaceFirst & 4 ); + #else unsigned char *buffer = alloc->spaceFirst; + #endif unsigned char *end = buffer + (inSize + 4); if ( end > alloc->spaceOversize ) @@ -381,6 +386,10 @@ class ImmixAllocator ((unsigned int *)buffer)[-1] = inSize; } + #if defined(HXCPP_GC_CHECK_POINTER) && defined(HXCPP_GC_DEBUG_ALWAYS_MOVE) + hx::GCOnNewPointer(buffer); + #endif + #ifdef HXCPP_TELEMETRY __hxt_gc_new((hx::StackContext *)alloc,buffer, inSize, inName); #endif @@ -388,41 +397,43 @@ class ImmixAllocator return buffer; #else - #ifndef HXCPP_ALIGN_ALLOC - // Inline the fast-path if we can - // We know the object can hold a pointer (vtable) and that the size is int-aligned - int start = alloc->spaceStart; - int end = start + sizeof(int) + inSize; - - if ( end <= alloc->spaceEnd ) - { - alloc->spaceStart = end; - - unsigned int *buffer = (unsigned int *)(alloc->allocBase + start); - - int startRow = start>>IMMIX_LINE_BITS; - - alloc->allocStartFlags[ startRow ] |= gImmixStartFlag[start&127]; - - if (inContainer) - *buffer++ = (( (end+(IMMIX_LINE_LEN-1))>>IMMIX_LINE_BITS) -startRow) | - (inSize<>IMMIX_LINE_BITS) -startRow) | - (inSize<spaceStart; + #ifdef HXCPP_ALIGN_ALLOC + // Ensure odd alignment in 8 bytes + start += 4 - (start & 4); + #endif + int end = start + sizeof(int) + inSize; + + if ( end <= alloc->spaceEnd ) + { + alloc->spaceStart = end; + + unsigned int *buffer = (unsigned int *)(alloc->allocBase + start); + + int startRow = start>>IMMIX_LINE_BITS; + + alloc->allocStartFlags[ startRow ] |= gImmixStartFlag[start&127]; + + if (inContainer) + *buffer++ = (( (end+(IMMIX_LINE_LEN-1))>>IMMIX_LINE_BITS) -startRow) | + (inSize<>IMMIX_LINE_BITS) -startRow) | + (inSize<CallAlloc(inSize, inContainer ? IMMIX_ALLOC_IS_CONTAINER : 0); diff --git a/include/hxcpp.h b/include/hxcpp.h index b2568d142..faa1b4db2 100755 --- a/include/hxcpp.h +++ b/include/hxcpp.h @@ -70,7 +70,7 @@ // Must allign allocs to 8 bytes to match floating point requirement? // Ints must br read on 4-byte boundary -#if defined(EMSCRIPTEN) || defined(GCW0) +#if (!defined(HXCPP_ALIGN_FLOAT) && (defined(EMSCRIPTEN) || defined(GCW0)) ) #define HXCPP_ALIGN_ALLOC #endif diff --git a/src/hx/gc/Immix.cpp b/src/hx/gc/Immix.cpp index 253199c53..05d0ac842 100644 --- a/src/hx/gc/Immix.cpp +++ b/src/hx/gc/Immix.cpp @@ -140,7 +140,7 @@ static size_t sgMaximumFreeSpace = 1024*1024*1024; //#define HXCPP_GC_SUMMARY //#define PROFILE_COLLECT //#define PROFILE_THREAD_USAGE -//#define HX_GC_VERIFY +//#define HXCPP_GC_VERIFY //#define HX_GC_VERIFY_ALLOC_START //#define SHOW_MEM_EVENTS //#define SHOW_MEM_EVENTS_VERBOSE @@ -158,7 +158,7 @@ static size_t sgMaximumFreeSpace = 1024*1024*1024; // every collect so you can see where it goes wrong (usually requires HX_GC_FIXED_BLOCKS) //#define HX_WATCH -#if defined(HX_GC_VERIFY) && defined(HXCPP_GC_GENERATIONAL) +#if defined(HXCPP_GC_VERIFY) && defined(HXCPP_GC_GENERATIONAL) #define HX_GC_VERIFY_GENERATIONAL #endif @@ -192,7 +192,7 @@ static bool sGcVerifyGenerational = false; #endif -#if HX_HAS_ATOMIC && (HXCPP_GC_DEBUG_LEVEL==0) && !defined(HX_GC_VERIFY) && !defined(EMSCRIPTEN) +#if HX_HAS_ATOMIC && (HXCPP_GC_DEBUG_LEVEL==0) && !defined(HXCPP_GC_VERIFY) && !defined(EMSCRIPTEN) #if defined(HX_MACOS) || defined(HX_WINDOWS) || defined(HX_LINUX) enum { MAX_GC_THREADS = 4 }; #else @@ -728,6 +728,13 @@ static int gBlockInfoEmptySlots = 0; #define ZEROED_THREAD 1 #define ZEROED_AUTO 2 +// Align padding based on block offset +#ifdef HXCPP_ALIGN_ALLOC + #define ALIGN_PADDING(x) (4-(x&4)) +#else + #define ALIGN_PADDING(x) 0 +#endif + struct BlockDataInfo { int mId; @@ -1202,6 +1209,13 @@ struct BlockDataInfo int last = scan + mRanges[h].length; if (inOffset> IMMIX_ALLOC_SIZE_SHIFT); int allocSize = size + sizeof(int); - while(allocSize>destLen) + while(allocSize + ALIGN_PADDING(destPos)>destLen) { hole++; if (hole>IMMIX_LINE_BITS; destStarts[ startRow ] |= hx::gImmixStartFlag[destPos&127]; @@ -3897,6 +3929,8 @@ class GlobalAllocator return 0; } + + int MoveSurvivors(hx::QuickVec *inRemembered) { int sourceScan = 0; @@ -3951,7 +3985,7 @@ class GlobalAllocator int allocSize = size + sizeof(int); // Find dest reqion ... - while(destHole==0 || destLen=destInfo->mHoles) @@ -3981,6 +4015,11 @@ class GlobalAllocator // TODO - not copy + paste + printf("Move!\n"); + #ifdef HXCPP_ALIGN_ALLOC + destPos += ALIGN_PADDING(destPos); + #endif + int startRow = destPos>>IMMIX_LINE_BITS; destStarts[ startRow ] |= hx::gImmixStartFlag[destPos&127]; @@ -4060,7 +4099,7 @@ class GlobalAllocator gAllocGroups[mAllBlocks[i]->mGroupId].isEmpty=false; } - #ifdef HX_GC_VERIFY + #ifdef HXCPP_GC_VERIFY typedef std::pair< void *, void * > ReleasedRange; std::vector releasedRange; std::vector releasedGids; @@ -4076,7 +4115,7 @@ class GlobalAllocator #ifdef SHOW_MEM_EVENTS_VERBOSE GCLOG("Release group %d: %p -> %p\n", i, g.alloc, g.alloc+groupBytes); #endif - #ifdef HX_GC_VERIFY + #ifdef HXCPP_GC_VERIFY releasedRange.push_back( ReleasedRange(g.alloc, g.alloc+groupBytes) ); releasedGids.push_back(i); #endif @@ -4105,7 +4144,7 @@ class GlobalAllocator } else { - #ifdef HX_GC_VERIFY + #ifdef HXCPP_GC_VERIFY for(int g=0;gmGroupId == releasedGids[g]) { @@ -4117,7 +4156,7 @@ class GlobalAllocator } } - #ifdef HX_GC_VERIFY + #ifdef HXCPP_GC_VERIFY for(int i=0;iverify("After mark"); #endif @@ -4793,7 +4832,7 @@ class GlobalAllocator } #endif - #ifdef HX_GC_VERIFY + #ifdef HXCPP_GC_VERIFY void VerifyBlockOrder() { for(int i=1;ispaceEnd || !(spaceStart & 7)) - size += 4; + // Do nothing here - aligning to the end of the row will bump the + // next allocation, so it's not clear if its a good idea. + #else + #ifdef HXCPP_GC_NURSERY + int spaceStart = spaceFirst - allocBase - 4; + int spaceEnd = spaceOversize - allocBase - 4; + #endif + + int size = ioSize + sizeof(int); + int end = spaceStart + size; + if (end <= spaceEnd) + { + int linePad = IMMIX_LINE_LEN - (end & (IMMIX_LINE_LEN-1)); + if (linePad>0 && linePad<=64) + ioSize += linePad; + } #endif - int end = spaceStart + size; - if (end <= spaceEnd) - { - int linePad = IMMIX_LINE_LEN - (end & (IMMIX_LINE_LEN-1)); - if (linePad>0 && linePad<=64) - ioSize += linePad; - } } @@ -6226,20 +6260,13 @@ class LocalAllocator : public hx::StackContext if (inSize==0) return hx::emptyAlloc; - #if defined(HXCPP_VISIT_ALLOCS) && defined(HXCPP_M64) + #if defined(HXCPP_VISIT_ALLOCS) && (defined(HXCPP_M64)||defined(HXCPP_ARM64)) // Make sure we can fit a relocation pointer int allocSize = sizeof(int) + std::max(8,inSize); #else int allocSize = sizeof(int) + inSize; #endif - #ifdef HXCPP_ALIGN_ALLOC - // If we start in even-int offset, we need to skip 8 bytes to get alloc on even-int - int skip4 = allocSize+spaceStart>spaceEnd || !(spaceStart & 7) ? 4 : 0; - #else - enum { skip4 = 0 }; - #endif - #if HXCPP_GC_DEBUG_LEVEL>0 if (inSize & 3) DebuggerTrap(); #endif @@ -6248,6 +6275,10 @@ class LocalAllocator : public hx::StackContext { #ifdef HXCPP_GC_NURSERY unsigned char *buffer = spaceFirst; + #ifdef HXCPP_ALIGN_ALLOC + if ((size_t)buffer & 0x4 ) + buffer += 4; + #endif unsigned char *end = buffer + allocSize; if ( end <= spaceOversize ) @@ -6268,13 +6299,14 @@ class LocalAllocator : public hx::StackContext if (s>spaceFirst && mFraggedRows) *mFraggedRows += (s - spaceFirst)>>IMMIX_LINE_BITS; #else - int end = spaceStart + allocSize + skip4; + #ifdef HXCPP_ALIGN_ALLOC + if (!((size_t)spaceStart & 0x4 )) + spaceStart += 4; + #endif + + int end = spaceStart + allocSize; if (end <= spaceEnd) { - #ifdef HXCPP_ALIGN_ALLOC - spaceStart += skip4; - #endif - unsigned int *buffer = (unsigned int *)(allocBase + spaceStart); int startRow = spaceStart>>IMMIX_LINE_BITS; diff --git a/test/haxe/compile.hxml b/test/haxe/compile.hxml index 2a23d789e..eedd52a3d 100644 --- a/test/haxe/compile.hxml +++ b/test/haxe/compile.hxml @@ -2,4 +2,4 @@ -r TestMain.hx -D HXCPP_GC_GENERATIONAL -L utest ---cpp bin \ No newline at end of file +--cpp bin diff --git a/toolchain/common-defines.xml b/toolchain/common-defines.xml index 517d9b401..3f8c111a9 100644 --- a/toolchain/common-defines.xml +++ b/toolchain/common-defines.xml @@ -24,6 +24,7 @@ + @@ -36,6 +37,7 @@ +