mirror of
https://github.com/beefytech/Beef.git
synced 2025-06-08 11:38:21 +02:00
Fixed large allocation issues
This commit is contained in:
parent
9ad57895e2
commit
c531ade968
5 changed files with 59 additions and 35 deletions
|
@ -28,8 +28,13 @@ namespace System.Collections.Generic
|
||||||
{
|
{
|
||||||
private const int_cosize cDefaultCapacity = 4;
|
private const int_cosize cDefaultCapacity = 4;
|
||||||
|
|
||||||
|
#if BF_LARGE_COLLECTIONS
|
||||||
|
const int_cosize SizeFlags = 0x7FFFFFFF'FFFFFFFF;
|
||||||
|
const int_cosize DynAllocFlag = (int_cosize)0x80000000'00000000;
|
||||||
|
#else
|
||||||
const int_cosize SizeFlags = 0x7FFFFFFF;
|
const int_cosize SizeFlags = 0x7FFFFFFF;
|
||||||
const int_cosize DynAllocFlag = (int_cosize)0x80000000;
|
const int_cosize DynAllocFlag = (int_cosize)0x80000000;
|
||||||
|
#endif
|
||||||
|
|
||||||
#if BF_ENABLE_REALTIME_LEAK_CHECK
|
#if BF_ENABLE_REALTIME_LEAK_CHECK
|
||||||
static DbgRawAllocData sRawAllocData;
|
static DbgRawAllocData sRawAllocData;
|
||||||
|
@ -393,11 +398,13 @@ namespace System.Collections.Generic
|
||||||
int allocSize = AllocSize;
|
int allocSize = AllocSize;
|
||||||
if (allocSize < min)
|
if (allocSize < min)
|
||||||
{
|
{
|
||||||
int_cosize newCapacity = (int_cosize)(allocSize == 0 ? cDefaultCapacity : allocSize * 2);
|
int newCapacity = allocSize == 0 ? cDefaultCapacity : allocSize + allocSize / 2;
|
||||||
// Allow the list to grow to maximum possible capacity (~2G elements) before encountering overflow.
|
// If we overflow, try to set to max. The "< min" check after still still bump us up
|
||||||
// Note that this check works even when mItems.Length overflowed thanks to the (uint) cast
|
// if necessary
|
||||||
//if ((uint)newCapacity > Array.MaxArrayLength) newCapacity = Array.MaxArrayLength;
|
if (newCapacity > SizeFlags)
|
||||||
if (newCapacity < min) newCapacity = (int_cosize)min;
|
newCapacity = SizeFlags;
|
||||||
|
if (newCapacity < min)
|
||||||
|
newCapacity = min;
|
||||||
Capacity = newCapacity;
|
Capacity = newCapacity;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -459,6 +466,23 @@ namespace System.Collections.Generic
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Insert(int index, Span<T> items)
|
||||||
|
{
|
||||||
|
if (items.Length == 0)
|
||||||
|
return;
|
||||||
|
int addCount = items.Length;
|
||||||
|
if (mSize + addCount > AllocSize) EnsureCapacity(mSize + addCount);
|
||||||
|
if (index < mSize)
|
||||||
|
{
|
||||||
|
Internal.MemCpy(mItems + index + addCount, mItems + index, (mSize - index) * strideof(T), alignof(T));
|
||||||
|
}
|
||||||
|
Internal.MemCpy(mItems + index, items.Ptr, addCount * strideof(T));
|
||||||
|
mSize += (int_cosize)addCount;
|
||||||
|
#if VERSION_LIST
|
||||||
|
mVersion++;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
public void RemoveAt(int index)
|
public void RemoveAt(int index)
|
||||||
{
|
{
|
||||||
Debug.Assert((uint)index < (uint)mSize);
|
Debug.Assert((uint)index < (uint)mSize);
|
||||||
|
|
|
@ -685,7 +685,7 @@ namespace System
|
||||||
void Realloc(int newSize)
|
void Realloc(int newSize)
|
||||||
{
|
{
|
||||||
Debug.Assert(AllocSize > 0, "String has been frozen");
|
Debug.Assert(AllocSize > 0, "String has been frozen");
|
||||||
Debug.Assert((uint_strsize)newSize < 0x40000000);
|
Debug.Assert((uint_strsize)newSize <= cSizeFlags);
|
||||||
char8* newPtr = new:this char8[newSize]*;
|
char8* newPtr = new:this char8[newSize]*;
|
||||||
Internal.MemCpy(newPtr, Ptr, mLength);
|
Internal.MemCpy(newPtr, Ptr, mLength);
|
||||||
if (IsDynAlloc)
|
if (IsDynAlloc)
|
||||||
|
@ -703,7 +703,7 @@ namespace System
|
||||||
void Realloc(char8* newPtr, int newSize)
|
void Realloc(char8* newPtr, int newSize)
|
||||||
{
|
{
|
||||||
Debug.Assert(AllocSize > 0, "String has been frozen");
|
Debug.Assert(AllocSize > 0, "String has been frozen");
|
||||||
Debug.Assert((uint_strsize)newSize < 0x40000000);
|
Debug.Assert((uint_strsize)newSize <= cSizeFlags);
|
||||||
Internal.MemCpy(newPtr, Ptr, mLength);
|
Internal.MemCpy(newPtr, Ptr, mLength);
|
||||||
if (IsDynAlloc)
|
if (IsDynAlloc)
|
||||||
delete:this mPtr;
|
delete:this mPtr;
|
||||||
|
|
|
@ -268,7 +268,7 @@ void* Internal::Dbg_GetMetadata(bf::System::Object* obj)
|
||||||
|
|
||||||
intptr Internal::Dbg_PrepareStackTrace(intptr baseAllocSize, intptr maxStackTraceDepth)
|
intptr Internal::Dbg_PrepareStackTrace(intptr baseAllocSize, intptr maxStackTraceDepth)
|
||||||
{
|
{
|
||||||
int allocSize = 0;
|
intptr allocSize = 0;
|
||||||
if (maxStackTraceDepth > 1)
|
if (maxStackTraceDepth > 1)
|
||||||
{
|
{
|
||||||
int capturedTraceCount = BF_CAPTURE_STACK(1, (intptr*)gPendingAllocState.mStackTrace, min((int)maxStackTraceDepth, 1024));
|
int capturedTraceCount = BF_CAPTURE_STACK(1, (intptr*)gPendingAllocState.mStackTrace, min((int)maxStackTraceDepth, 1024));
|
||||||
|
@ -292,7 +292,7 @@ bf::System::Object* Internal::Dbg_ObjectAlloc(bf::System::Reflection::TypeInstan
|
||||||
{
|
{
|
||||||
BF_ASSERT((BFRTFLAGS & BfRtFlags_ObjectHasDebugFlags) != 0);
|
BF_ASSERT((BFRTFLAGS & BfRtFlags_ObjectHasDebugFlags) != 0);
|
||||||
Object* result;
|
Object* result;
|
||||||
int allocSize = BF_ALIGN(size, typeInst->mInstAlign);
|
intptr allocSize = BF_ALIGN(size, typeInst->mInstAlign);
|
||||||
uint8* allocBytes = (uint8*)BfObjectAllocate(allocSize, typeInst->_GetType());
|
uint8* allocBytes = (uint8*)BfObjectAllocate(allocSize, typeInst->_GetType());
|
||||||
// int dataOffset = (int)(sizeof(intptr) * 2);
|
// int dataOffset = (int)(sizeof(intptr) * 2);
|
||||||
// memset(allocBytes + dataOffset, 0, size - dataOffset);
|
// memset(allocBytes + dataOffset, 0, size - dataOffset);
|
||||||
|
|
|
@ -900,14 +900,14 @@ void BFGC::SweepSpan(tcmalloc_obj::Span* span, int expectedStartPage)
|
||||||
}
|
}
|
||||||
|
|
||||||
intptr pageSize = (intptr)1<<kPageShift;
|
intptr pageSize = (intptr)1<<kPageShift;
|
||||||
int spanSize = pageSize * span->length;
|
intptr spanSize = pageSize * span->length;
|
||||||
void* spanStart = (void*)((intptr)span->start << kPageShift);
|
void* spanStart = (void*)((intptr)span->start << kPageShift);
|
||||||
void* spanEnd = (void*)((intptr)spanStart + spanSize);
|
void* spanEnd = (void*)((intptr)spanStart + spanSize);
|
||||||
void* spanPtr = spanStart;
|
void* spanPtr = spanStart;
|
||||||
|
|
||||||
BF_LOGASSERT((spanStart >= tcmalloc_obj::PageHeap::sAddressStart) && (spanEnd <= tcmalloc_obj::PageHeap::sAddressEnd));
|
BF_LOGASSERT((spanStart >= tcmalloc_obj::PageHeap::sAddressStart) && (spanEnd <= tcmalloc_obj::PageHeap::sAddressEnd));
|
||||||
|
|
||||||
int elementSize = Static::sizemap()->ByteSizeForClass(span->sizeclass);
|
intptr elementSize = Static::sizemap()->ByteSizeForClass(span->sizeclass);
|
||||||
if (elementSize == 0)
|
if (elementSize == 0)
|
||||||
elementSize = spanSize;
|
elementSize = spanSize;
|
||||||
BF_LOGASSERT(elementSize >= sizeof(bf::System::Object));
|
BF_LOGASSERT(elementSize >= sizeof(bf::System::Object));
|
||||||
|
@ -2040,14 +2040,14 @@ void BFGC::ObjReportHandleSpan(tcmalloc_obj::Span* span, int expectedStartPage,
|
||||||
}
|
}
|
||||||
|
|
||||||
intptr pageSize = (intptr)1<<kPageShift;
|
intptr pageSize = (intptr)1<<kPageShift;
|
||||||
int spanSize = pageSize * span->length;
|
intptr spanSize = pageSize * span->length;
|
||||||
void* spanStart = (void*)((intptr)span->start << kPageShift);
|
void* spanStart = (void*)((intptr)span->start << kPageShift);
|
||||||
void* spanEnd = (void*)((intptr)spanStart + spanSize);
|
void* spanEnd = (void*)((intptr)spanStart + spanSize);
|
||||||
void* spanPtr = spanStart;
|
void* spanPtr = spanStart;
|
||||||
|
|
||||||
BF_LOGASSERT((spanStart >= tcmalloc_obj::PageHeap::sAddressStart) && (spanEnd <= tcmalloc_obj::PageHeap::sAddressEnd));
|
BF_LOGASSERT((spanStart >= tcmalloc_obj::PageHeap::sAddressStart) && (spanEnd <= tcmalloc_obj::PageHeap::sAddressEnd));
|
||||||
|
|
||||||
int elementSize = Static::sizemap()->ByteSizeForClass(span->sizeclass);
|
intptr elementSize = Static::sizemap()->ByteSizeForClass(span->sizeclass);
|
||||||
if (elementSize == 0)
|
if (elementSize == 0)
|
||||||
elementSize = spanSize;
|
elementSize = spanSize;
|
||||||
BF_LOGASSERT(elementSize >= sizeof(bf::System::Object));
|
BF_LOGASSERT(elementSize >= sizeof(bf::System::Object));
|
||||||
|
@ -2519,7 +2519,7 @@ void BFGC::MarkFromGCThread(bf::System::Object* obj)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
intptr pageSize = (intptr) 1 << kPageShift;
|
intptr pageSize = (intptr) 1 << kPageShift;
|
||||||
int spanSize = pageSize * span->length;
|
intptr spanSize = pageSize * span->length;
|
||||||
void* spanStart = (void*)((intptr)span->start << kPageShift);
|
void* spanStart = (void*)((intptr)span->start << kPageShift);
|
||||||
void* spanEnd = (void*)((intptr)spanStart + spanSize);
|
void* spanEnd = (void*)((intptr)spanStart + spanSize);
|
||||||
|
|
||||||
|
@ -2546,7 +2546,7 @@ void BFGC::MarkFromGCThread(bf::System::Object* obj)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int elementSize = Static::sizemap()->ByteSizeForClass(span->sizeclass);
|
intptr elementSize = Static::sizemap()->ByteSizeForClass(span->sizeclass);
|
||||||
// Large alloc
|
// Large alloc
|
||||||
if (elementSize == 0)
|
if (elementSize == 0)
|
||||||
{
|
{
|
||||||
|
|
|
@ -55,13 +55,13 @@ using namespace Beefy;
|
||||||
struct DeferredFreeEntry
|
struct DeferredFreeEntry
|
||||||
{
|
{
|
||||||
bf::System::Object* mObject;
|
bf::System::Object* mObject;
|
||||||
int mAllocSize;
|
intptr mAllocSize;
|
||||||
};
|
};
|
||||||
|
|
||||||
static Beefy::Deque<DeferredFreeEntry> gDeferredFrees;
|
static Beefy::Deque<DeferredFreeEntry> gDeferredFrees;
|
||||||
static int gRawAllocSize = 0;
|
static intptr gRawAllocSize = 0;
|
||||||
static int gMaxRawAllocSize = 0;
|
static intptr gMaxRawAllocSize = 0;
|
||||||
static int gDeferredObjectFreeSize = 0;
|
static intptr gDeferredObjectFreeSize = 0;
|
||||||
|
|
||||||
void BFGC::RawInit()
|
void BFGC::RawInit()
|
||||||
{
|
{
|
||||||
|
@ -97,14 +97,14 @@ void BFGC::RawMarkSpan(tcmalloc_raw::Span* span, int expectedStartPage)
|
||||||
}
|
}
|
||||||
|
|
||||||
intptr pageSize = (intptr)1 << kPageShift;
|
intptr pageSize = (intptr)1 << kPageShift;
|
||||||
int spanSize = pageSize * span->length;
|
intptr spanSize = pageSize * span->length;
|
||||||
void* spanStart = (void*)((intptr)span->start << kPageShift);
|
void* spanStart = (void*)((intptr)span->start << kPageShift);
|
||||||
void* spanEnd = (void*)((intptr)spanStart + spanSize);
|
void* spanEnd = (void*)((intptr)spanStart + spanSize);
|
||||||
void* spanPtr = spanStart;
|
void* spanPtr = spanStart;
|
||||||
|
|
||||||
BF_LOGASSERT((spanStart >= tcmalloc_raw::PageHeap::sAddressStart) && (spanEnd <= tcmalloc_raw::PageHeap::sAddressEnd));
|
BF_LOGASSERT((spanStart >= tcmalloc_raw::PageHeap::sAddressStart) && (spanEnd <= tcmalloc_raw::PageHeap::sAddressEnd));
|
||||||
|
|
||||||
int elementSize = Static::sizemap()->ByteSizeForClass(span->sizeclass);
|
intptr elementSize = Static::sizemap()->ByteSizeForClass(span->sizeclass);
|
||||||
if (elementSize == 0)
|
if (elementSize == 0)
|
||||||
elementSize = spanSize;
|
elementSize = spanSize;
|
||||||
BF_LOGASSERT(elementSize >= sizeof(bf::System::Object));
|
BF_LOGASSERT(elementSize >= sizeof(bf::System::Object));
|
||||||
|
@ -116,14 +116,14 @@ void BFGC::RawMarkSpan(tcmalloc_raw::Span* span, int expectedStartPage)
|
||||||
{
|
{
|
||||||
if (rawAllocData->mMarkFunc != NULL)
|
if (rawAllocData->mMarkFunc != NULL)
|
||||||
{
|
{
|
||||||
int extraDataSize = sizeof(intptr);
|
intptr extraDataSize = sizeof(intptr);
|
||||||
if (rawAllocData->mMaxStackTrace == 1)
|
if (rawAllocData->mMaxStackTrace == 1)
|
||||||
{
|
{
|
||||||
extraDataSize += sizeof(intptr);
|
extraDataSize += sizeof(intptr);
|
||||||
}
|
}
|
||||||
else if (rawAllocData->mMaxStackTrace > 1)
|
else if (rawAllocData->mMaxStackTrace > 1)
|
||||||
{
|
{
|
||||||
int stackTraceCount = *(intptr*)((uint8*)spanPtr + elementSize - sizeof(intptr) - sizeof(intptr));
|
intptr stackTraceCount = *(intptr*)((uint8*)spanPtr + elementSize - sizeof(intptr) - sizeof(intptr));
|
||||||
extraDataSize += (1 + stackTraceCount) * sizeof(intptr);
|
extraDataSize += (1 + stackTraceCount) * sizeof(intptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -132,10 +132,10 @@ void BFGC::RawMarkSpan(tcmalloc_raw::Span* span, int expectedStartPage)
|
||||||
|
|
||||||
// It's possible we can overestimate elemCount, particularly for large allocations. This doesn't cause a problem
|
// It's possible we can overestimate elemCount, particularly for large allocations. This doesn't cause a problem
|
||||||
// because we can safely mark on complete random memory -- pointer values are always validated before being followed
|
// because we can safely mark on complete random memory -- pointer values are always validated before being followed
|
||||||
int elemStride = BF_ALIGN(rawAllocData->mType->mSize, rawAllocData->mType->mAlign);
|
intptr elemStride = BF_ALIGN(rawAllocData->mType->mSize, rawAllocData->mType->mAlign);
|
||||||
int dataSize = elementSize - extraDataSize;
|
intptr dataSize = elementSize - extraDataSize;
|
||||||
int elemCount = dataSize / elemStride;
|
intptr elemCount = dataSize / elemStride;
|
||||||
for (int elemIdx = 0; elemIdx < elemCount; elemIdx++)
|
for (intptr elemIdx = 0; elemIdx < elemCount; elemIdx++)
|
||||||
{
|
{
|
||||||
markFunc((uint8*)spanPtr + elemIdx * elemStride);
|
markFunc((uint8*)spanPtr + elemIdx * elemStride);
|
||||||
}
|
}
|
||||||
|
@ -161,7 +161,7 @@ void BFGC::RawMarkAll()
|
||||||
if (pageHeap == NULL)
|
if (pageHeap == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
int leafCheckCount = 0;
|
intptr leafCheckCount = 0;
|
||||||
|
|
||||||
#ifdef BF32
|
#ifdef BF32
|
||||||
for (int rootIdx = 0; rootIdx < PageHeap::PageMap::ROOT_LENGTH; rootIdx++)
|
for (int rootIdx = 0; rootIdx < PageHeap::PageMap::ROOT_LENGTH; rootIdx++)
|
||||||
|
@ -228,14 +228,14 @@ void BFGC::RawReportHandleSpan(tcmalloc_raw::Span* span, int expectedStartPage,
|
||||||
}
|
}
|
||||||
|
|
||||||
intptr pageSize = (intptr)1 << kPageShift;
|
intptr pageSize = (intptr)1 << kPageShift;
|
||||||
int spanSize = pageSize * span->length;
|
intptr spanSize = pageSize * span->length;
|
||||||
void* spanStart = (void*)((intptr)span->start << kPageShift);
|
void* spanStart = (void*)((intptr)span->start << kPageShift);
|
||||||
void* spanEnd = (void*)((intptr)spanStart + spanSize);
|
void* spanEnd = (void*)((intptr)spanStart + spanSize);
|
||||||
void* spanPtr = spanStart;
|
void* spanPtr = spanStart;
|
||||||
|
|
||||||
BF_LOGASSERT((spanStart >= tcmalloc_raw::PageHeap::sAddressStart) && (spanEnd <= tcmalloc_raw::PageHeap::sAddressEnd));
|
BF_LOGASSERT((spanStart >= tcmalloc_raw::PageHeap::sAddressStart) && (spanEnd <= tcmalloc_raw::PageHeap::sAddressEnd));
|
||||||
|
|
||||||
int elementSize = Static::sizemap()->ByteSizeForClass(span->sizeclass);
|
intptr elementSize = Static::sizemap()->ByteSizeForClass(span->sizeclass);
|
||||||
if (elementSize == 0)
|
if (elementSize == 0)
|
||||||
elementSize = spanSize;
|
elementSize = spanSize;
|
||||||
|
|
||||||
|
@ -250,7 +250,7 @@ void BFGC::RawReportHandleSpan(tcmalloc_raw::Span* span, int expectedStartPage,
|
||||||
|
|
||||||
if (sizeMap == NULL)
|
if (sizeMap == NULL)
|
||||||
{
|
{
|
||||||
int extraDataSize = sizeof(intptr);
|
intptr extraDataSize = sizeof(intptr);
|
||||||
|
|
||||||
RawLeakInfo rawLeakInfo;
|
RawLeakInfo rawLeakInfo;
|
||||||
rawLeakInfo.mRawAllocData = rawAllocData;
|
rawLeakInfo.mRawAllocData = rawAllocData;
|
||||||
|
@ -276,7 +276,7 @@ void BFGC::RawReportHandleSpan(tcmalloc_raw::Span* span, int expectedStartPage,
|
||||||
|
|
||||||
if (rawAllocData->mType != NULL)
|
if (rawAllocData->mType != NULL)
|
||||||
{
|
{
|
||||||
int typeSize;
|
intptr typeSize;
|
||||||
if ((gBfRtDbgFlags & BfRtFlags_ObjectHasDebugFlags) != 0)
|
if ((gBfRtDbgFlags & BfRtFlags_ObjectHasDebugFlags) != 0)
|
||||||
typeSize = rawAllocData->mType->mSize;
|
typeSize = rawAllocData->mType->mSize;
|
||||||
else
|
else
|
||||||
|
@ -374,7 +374,7 @@ void BFGC::RawReport(String& msg, intptr& freeSize, std::multimap<AllocInfo, bf:
|
||||||
allocIdSet.clear();
|
allocIdSet.clear();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int leafCheckCount = 0;
|
intptr leafCheckCount = 0;
|
||||||
bool overflowed = false;
|
bool overflowed = false;
|
||||||
|
|
||||||
Beefy::Dictionary<bf::System::Type*, AllocInfo> sizeMap;
|
Beefy::Dictionary<bf::System::Type*, AllocInfo> sizeMap;
|
||||||
|
@ -556,7 +556,7 @@ void BfRawFree(void* ptr)
|
||||||
{
|
{
|
||||||
const PageID p = reinterpret_cast<uintptr_t>(ptr) >> kPageShift;
|
const PageID p = reinterpret_cast<uintptr_t>(ptr) >> kPageShift;
|
||||||
size_t cl = Static::pageheap()->GetSizeClassIfCached(p);
|
size_t cl = Static::pageheap()->GetSizeClassIfCached(p);
|
||||||
int allocSize = 0;
|
intptr allocSize = 0;
|
||||||
if (cl == 0)
|
if (cl == 0)
|
||||||
{
|
{
|
||||||
auto span = Static::pageheap()->GetDescriptor(p);
|
auto span = Static::pageheap()->GetDescriptor(p);
|
||||||
|
@ -602,7 +602,7 @@ void BfRawFree(void* ptr)
|
||||||
entry.mAllocSize = allocSize;
|
entry.mAllocSize = allocSize;
|
||||||
gDeferredFrees.Add(entry);
|
gDeferredFrees.Add(entry);
|
||||||
|
|
||||||
int maxDeferredSize = gMaxRawAllocSize * gBFGC.mMaxRawDeferredObjectFreePercentage / 100;
|
intptr maxDeferredSize = gMaxRawAllocSize * gBFGC.mMaxRawDeferredObjectFreePercentage / 100;
|
||||||
while (gDeferredObjectFreeSize > maxDeferredSize)
|
while (gDeferredObjectFreeSize > maxDeferredSize)
|
||||||
{
|
{
|
||||||
DeferredFreeEntry entry = gDeferredFrees.PopBack();
|
DeferredFreeEntry entry = gDeferredFrees.PopBack();
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue