@@ -2815,14 +2815,17 @@ void *InternalCreateConstBuffer(const void *inData,int inSize,bool inAddStringHa
28152815 {
28162816 memcpy (result,inData,inSize);
28172817 }
2818- else
2818+ else if (inSize)
28192819 {
28202820 ZERO_MEM (result,inSize);
28212821 }
28222822
28232823 return result;
28242824}
28252825
2826+ // Used when the allocation size is zero for a non-null pointer
2827+ void *emptyAlloc = InternalCreateConstBuffer(0 ,0 ,false );
2828+
28262829
28272830} // namespace hx
28282831
@@ -3116,6 +3119,31 @@ class GlobalAllocator
31163119 }
31173120 }
31183121
3122+ void FreeLarge (void *inLarge)
3123+ {
3124+ ((unsigned char *)inLarge)[HX_ENDIAN_MARK_ID_BYTE] = 0 ;
3125+ // AllocLarge will not lock this list unless it decides there is a suitable
3126+ // value, so we can't doa realloc without potentially crashing it.
3127+ if (largeObjectRecycle.hasExtraCapacity (1 ))
3128+ {
3129+ unsigned int *blob = ((unsigned int *)inLarge) - 2 ;
3130+ unsigned int size = *blob;
3131+ mLargeListLock .Lock ();
3132+ mLargeAllocated -= size;
3133+ // Could somehow keep it in the list, but mark as recycled?
3134+ mLargeList .qerase_val (blob);
3135+ // We could maybe free anyhow?
3136+ if (!largeObjectRecycle.hasExtraCapacity (1 ))
3137+ {
3138+ mLargeListLock .Unlock ();
3139+ HxFree (blob);
3140+ return ;
3141+ }
3142+ largeObjectRecycle.push (blob);
3143+ mLargeListLock .Unlock ();
3144+ }
3145+ }
3146+
31193147 void *AllocLarge (int inSize, bool inClear)
31203148 {
31213149 if (hx::gPauseForCollect )
@@ -6027,6 +6055,9 @@ class LocalAllocator : public hx::StackContext
60276055 PauseForCollect ();
60286056 #endif
60296057
6058+ if (inSize==0 )
6059+ return hx::emptyAlloc;
6060+
60306061 #if defined(HXCPP_VISIT_ALLOCS) && defined(HXCPP_M64)
60316062 // Make sure we can fit a relocation pointer
60326063 int allocSize = sizeof (int ) + std::max (8 ,inSize);
@@ -6485,6 +6516,9 @@ inline unsigned int ObjectSize(void *inData)
64856516unsigned int ObjectSizeSafe (void *inData)
64866517{
64876518 unsigned int header = ((unsigned int *)(inData))[-1 ];
6519+ if (header & HX_GC_CONST_ALLOC_BIT)
6520+ return 0 ;
6521+
64886522 #ifdef HXCPP_GC_NURSERY
64896523 if (!(header & 0xff000000 ))
64906524 {
@@ -6495,6 +6529,7 @@ unsigned int ObjectSizeSafe(void *inData)
64956529 }
64966530 #endif
64976531
6532+
64986533 return (header & IMMIX_ALLOC_ROW_COUNT) ?
64996534 ( (header & IMMIX_ALLOC_SIZE_MASK) >> IMMIX_ALLOC_SIZE_SHIFT) :
65006535 ((unsigned int *)(inData))[-2 ];
@@ -6505,11 +6540,29 @@ void GCChangeManagedMemory(int inDelta, const char *inWhy)
65056540 sGlobalAlloc ->onMemoryChange (inDelta, inWhy);
65066541}
65076542
6543+ void InternalReleaseMem (void *inMem)
6544+ {
6545+ if (inMem)
6546+ {
6547+ unsigned int s = ObjectSizeSafe (inMem);
6548+ if (s>=IMMIX_LARGE_OBJ_SIZE)
6549+ {
6550+ // Can release asap
6551+ sGlobalAlloc ->FreeLarge (inMem);
6552+ }
6553+ }
6554+ }
6555+
6556+
65086557
6509- void *InternalRealloc (void *inData,int inSize, bool inExpand)
6558+ void *InternalRealloc (int inFromSize, void *inData,int inSize, bool inExpand)
65106559{
6511- if (inData==0 )
6560+ if (inData==0 || inFromSize==0 )
6561+ {
6562+ if (inData)
6563+ InternalReleaseMem (inData);
65126564 return hx::InternalNew (inSize,false );
6565+ }
65136566
65146567 HX_STACK_FRAME (" GC" , " realloc" , 0 , " GC::relloc" , __FILE__ , __LINE__, 0 )
65156568
@@ -6522,15 +6575,16 @@ void *InternalRealloc(void *inData,int inSize, bool inExpand)
65226575 sgAllocsSinceLastSpam++;
65236576 #endif
65246577
6525- unsigned int s = ObjectSizeSafe (inData);
6526-
65276578 void *new_data = 0 ;
6528-
6529- if (inSize>=IMMIX_LARGE_OBJ_SIZE)
6579+ if (inSize==0 )
6580+ {
6581+ new_data = hx::emptyAlloc;
6582+ }
6583+ else if (inSize>=IMMIX_LARGE_OBJ_SIZE)
65306584 {
65316585 new_data = sGlobalAlloc ->AllocLarge (inSize, false );
6532- if (inSize>s )
6533- ZERO_MEM ((char *)new_data + s ,inSize-s );
6586+ if (inSize>inFromSize )
6587+ ZERO_MEM ((char *)new_data + inFromSize ,inSize-inFromSize );
65346588 }
65356589 else
65366590 {
@@ -6541,12 +6595,13 @@ void *InternalRealloc(void *inData,int inSize, bool inExpand)
65416595 new_data = tla->CallAlloc (8 ,0 );
65426596 else
65436597 #endif
6598+ {
6599+ inSize = (inSize+3 ) & ~3 ;
6600+ if (inExpand)
6601+ tla->ExpandAlloc (inSize);
65446602
6545- inSize = (inSize+3 ) & ~3 ;
6546- if (inExpand)
6547- tla->ExpandAlloc (inSize);
6548-
6549- new_data = tla->CallAlloc (inSize,0 );
6603+ new_data = tla->CallAlloc (inSize,0 );
6604+ }
65506605 }
65516606
65526607
@@ -6555,17 +6610,12 @@ void *InternalRealloc(void *inData,int inSize, bool inExpand)
65556610 __hxt_gc_realloc (inData, new_data, inSize);
65566611#endif
65576612
6558- int min_size = s < inSize ? s : inSize;
6613+ int min_size = inFromSize < inSize ? inFromSize : inSize;
65596614
6560- memcpy (new_data, inData, min_size );
6615+ if (min_size)
6616+ memcpy (new_data, inData, min_size );
65616617
6562- #ifdef HXCPP_GC_GENERATIONAL
6563- if (s>=IMMIX_LARGE_OBJ_SIZE && sGcMode ==gcmGenerational)
6564- {
6565- // Can release asap
6566- ((unsigned char *)inData)[HX_ENDIAN_MARK_ID_BYTE] = 0 ;
6567- }
6568- #endif
6618+ InternalReleaseMem (inData);
65696619
65706620 return new_data;
65716621}
0 commit comments