1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-08 03:28:20 +02:00

Support for marking append-allocated objects (mHasAppendWantMark)

This commit is contained in:
Brian Fiete 2025-01-28 14:49:15 -08:00
parent 9ae172c43f
commit 9baf0ead21
18 changed files with 475 additions and 103 deletions

View file

@ -49,10 +49,10 @@ namespace bf
BFRT_EXPORT static void Dbg_ObjectCreatedEx(bf::System::Object* result, intptr size, bf::System::ClassVData* classVData);
BFRT_EXPORT static void Dbg_ObjectAllocated(bf::System::Object* result, intptr size, bf::System::ClassVData* classVData);
BFRT_EXPORT static void Dbg_ObjectAllocatedEx(bf::System::Object* result, intptr size, bf::System::ClassVData* classVData);
BFRT_EXPORT static Object* Dbg_ObjectAlloc(bf::System::Reflection::TypeInstance* typeInst, intptr size);
BFRT_EXPORT static Object* Dbg_ObjectAlloc(bf::System::ClassVData* classVData, intptr size, intptr align, intptr maxStackTraceDept);
BFRT_EXPORT static Object* Dbg_ObjectAlloc(bf::System::Reflection::TypeInstance* typeInst, intptr size);
BFRT_EXPORT static Object* Dbg_ObjectAlloc(bf::System::ClassVData* classVData, intptr size, intptr align, intptr maxStackTraceDept, uint8 allocFlags);
BFRT_EXPORT static void Dbg_MarkObjectDeleted(bf::System::Object* obj);
BFRT_EXPORT static void Dbg_ObjectStackInit(bf::System::Object* result, bf::System::ClassVData* classVData);
BFRT_EXPORT static void Dbg_ObjectStackInit(bf::System::Object* result, bf::System::ClassVData* classVData, intptr size, uint8 allocFlags);
BFRT_EXPORT static void Dbg_ObjectPreDelete(bf::System::Object* obj);
BFRT_EXPORT static void Dbg_ObjectPreCustomDelete(bf::System::Object* obj);
@ -315,20 +315,28 @@ bf::System::Object* Internal::Dbg_ObjectAlloc(bf::System::Reflection::TypeInstan
//#define DBG_OBJECTEND
bf::System::Object* Internal::Dbg_ObjectAlloc(bf::System::ClassVData* classVData, intptr size, intptr align, intptr maxStackTraceDepth)
bf::System::Object* Internal::Dbg_ObjectAlloc(bf::System::ClassVData* classVData, intptr size, intptr align, intptr maxStackTraceDepth, uint8 allocFlags)
{
void* stackTrace[1024];
int capturedTraceCount = 0;
intptr allocSize = size;
bool largeAllocInfo = false;
if ((BFRTFLAGS & BfRtFlags_ObjectHasDebugFlags) != 0)
{
if (maxStackTraceDepth > 1)
{
capturedTraceCount = BF_CAPTURE_STACK(1, (intptr*)stackTrace, min((int)maxStackTraceDepth, 1024));
const intptr maxSmallObjectSize = ((intptr)1 << ((sizeof(intptr) - 2) * 8)) - 1;
if ((capturedTraceCount > 255) || (size >= maxSmallObjectSize))
bool forceLarge = false;
auto typeData = BFRTCALLBACKS.ClassVData_GetTypeDataPtr(classVData);
if ((typeData->mTypeFlags & BfTypeFlag_HasAppendWantMark) != 0)
{
forceLarge = true;
}
if ((capturedTraceCount > 255) || (size >= maxSmallObjectSize) || (forceLarge))
{
largeAllocInfo = true;
allocSize += (1 + capturedTraceCount) * sizeof(intptr);
@ -336,6 +344,12 @@ bf::System::Object* Internal::Dbg_ObjectAlloc(bf::System::ClassVData* classVData
else
allocSize += capturedTraceCount * sizeof(intptr);
}
// Append want mark
if ((allocFlags & 1) != 0)
{
allocSize += 4 * sizeof(intptr);
}
}
#ifdef DBG_OBJECTEND
@ -385,7 +399,7 @@ bf::System::Object* Internal::Dbg_ObjectAlloc(bf::System::ClassVData* classVData
intptr dbgAllocInfo;
auto classVDataVal = (intptr)classVData | (intptr)BfObjectFlag_Allocated;
if (maxStackTraceDepth <= 1)
if ((maxStackTraceDepth <= 1) && (allocFlags == 0))
dbgAllocInfo = (intptr)BF_RETURN_ADDRESS;
else
{
@ -393,13 +407,13 @@ bf::System::Object* Internal::Dbg_ObjectAlloc(bf::System::ClassVData* classVData
{
classVDataVal |= (intptr)BfObjectFlag_AllocInfo;
dbgAllocInfo = size;
*(intptr*)((uint8*)result + size) = capturedTraceCount;
*(intptr*)((uint8*)result + size) = (capturedTraceCount << 8) | allocFlags;
memcpy((uint8*)result + size + sizeof(intptr), stackTrace, capturedTraceCount * sizeof(intptr));
}
else
{
classVDataVal |= (intptr)BfObjectFlag_AllocInfo_Short;
dbgAllocInfo = (size << 16) | capturedTraceCount;
dbgAllocInfo = (size << 16) | (((intptr)allocFlags) << 8) | capturedTraceCount;
memcpy((uint8*)result + size, stackTrace, capturedTraceCount * sizeof(intptr));
}
}
@ -424,13 +438,27 @@ bf::System::Object* Internal::Dbg_ObjectAlloc(bf::System::ClassVData* classVData
return result;
}
void Internal::Dbg_ObjectStackInit(bf::System::Object* result, bf::System::ClassVData* classVData)
void Internal::Dbg_ObjectStackInit(bf::System::Object* result, bf::System::ClassVData* classVData, intptr totalSize, uint8 allocFlags)
{
BF_ASSERT((BFRTFLAGS & BfRtFlags_ObjectHasDebugFlags) != 0);
result->mClassVData = (intptr)classVData | (intptr)BfObjectFlag_StackAlloc;
#ifndef BFRT_NODBGFLAGS
result->mDbgAllocInfo = (intptr)BF_RETURN_ADDRESS;
if ((allocFlags & 1) == 0)
{
result->mDbgAllocInfo = (intptr)BF_RETURN_ADDRESS;
}
else
{
int size = (int)(totalSize - sizeof(intptr) - sizeof(intptr) * 4);
int capturedTraceCount = 1;
*(intptr*)((uint8*)result + size) = (intptr)BF_RETURN_ADDRESS;
memset((uint8*)result + size + sizeof(intptr), 0, sizeof(intptr) * 4);
result->mDbgAllocInfo = (size << 16) | (((intptr)allocFlags) << 8) | capturedTraceCount;
BF_FULL_MEMORY_FENCE();
result->mClassVData |= (intptr)BfObjectFlag_AllocInfo_Short;
}
#endif
}

View file

@ -2670,10 +2670,13 @@ void BFGC::WriteDebugDumpState()
{
//const bf::System::Type* bfTypeRootData = ((bf::System::Type*)obj->GetTypeSafe())->mTypeRootData;
bf::System::Type* bfType = obj->GetTypeSafe();
while ((int) debugInfoVector.size() <= bfType->mTypeId)
auto typeData = bfType->GetTypeData();
while ((int) debugInfoVector.size() <= typeData->mTypeId)
debugInfoVector.push_back(DebugInfo());
DebugInfo* debugInfo = &debugInfoVector[bfType->mTypeId];
DebugInfo* debugInfo = &debugInfoVector[typeData->mTypeId];
debugInfo->mType = obj->GetTypeSafe();
debugInfo->mCount++;
int objSize = BFGetObjectSize(obj);

View file

@ -115,16 +115,18 @@ void BFGC::RawMarkSpan(tcmalloc_raw::Span* span, int expectedStartPage)
if (rawAllocData != NULL)
{
if (rawAllocData->mMarkFunc != NULL)
{
{
intptr extraDataSize = sizeof(intptr);
if (rawAllocData->mMaxStackTrace == 1)
{
extraDataSize += sizeof(intptr);
extraDataSize += sizeof(intptr) + 2;
extraDataSize += *(uint16*)((uint8*)spanPtr + elementSize - sizeof(intptr) - sizeof(intptr) - 2);
}
else if (rawAllocData->mMaxStackTrace > 1)
{
intptr stackTraceCount = *(intptr*)((uint8*)spanPtr + elementSize - sizeof(intptr) - sizeof(intptr));
extraDataSize += (1 + stackTraceCount) * sizeof(intptr);
extraDataSize += (1 + stackTraceCount) * sizeof(intptr) + 2;
extraDataSize += *(uint16*)((uint8*)spanPtr + elementSize - sizeof(intptr) - sizeof(intptr) - stackTraceCount * sizeof(intptr) - 2);
}
struct MarkTarget
@ -132,17 +134,21 @@ void BFGC::RawMarkSpan(tcmalloc_raw::Span* span, int expectedStartPage)
};
typedef void(MarkTarget::*MarkFunc)();
MarkFunc markFunc = *(MarkFunc*)&rawAllocData->mMarkFunc;
// 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
intptr elemStride = BF_ALIGN(rawAllocData->mType->mSize, rawAllocData->mType->mAlign);
if (elemStride > 0)
auto typeData = rawAllocData->mType->GetTypeData();
if (typeData != NULL)
{
intptr dataSize = elementSize - extraDataSize;
intptr elemCount = dataSize / elemStride;
for (intptr elemIdx = 0; elemIdx < elemCount; elemIdx++)
// 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
intptr elemStride = BF_ALIGN(typeData->mSize, typeData->mAlign);
if (elemStride > 0)
{
(((MarkTarget*)((uint8*)spanPtr + elemIdx * elemStride))->*markFunc)();
intptr dataSize = elementSize - extraDataSize;
intptr elemCount = dataSize / elemStride;
for (intptr elemIdx = 0; elemIdx < elemCount; elemIdx++)
{
(((MarkTarget*)((uint8*)spanPtr + elemIdx * elemStride))->*markFunc)();
}
}
}
}
@ -282,13 +288,13 @@ void BFGC::RawReportHandleSpan(tcmalloc_raw::Span* span, int expectedStartPage,
if (rawAllocData->mType != NULL)
{
intptr typeSize;
if ((gBfRtDbgFlags & BfRtFlags_ObjectHasDebugFlags) != 0)
typeSize = rawAllocData->mType->mSize;
else
typeSize = ((bf::System::Type_NOFLAGS*)rawAllocData->mType)->mSize;
if (typeSize > 0)
rawLeakInfo.mDataCount = (elementSize - extraDataSize) / typeSize;
bf::System::Type_NOFLAGS* typeData = rawAllocData->mType->GetTypeData();
if (typeData != NULL)
{
intptr typeSize = typeData->mSize;
if (typeSize > 0)
rawLeakInfo.mDataCount = (elementSize - extraDataSize) / typeSize;
}
}
else
rawLeakInfo.mDataCount = 1;
@ -558,8 +564,8 @@ void* BfRawAllocate(intptr size, bf::System::DbgRawAllocData* rawAllocData, void
markOffsetPtr = (uint16*)((uint8*)result + totalSize - sizeof(intptr) - sizeof(intptr) - 2);
}
else if (rawAllocData->mMaxStackTrace > 1)
{
memcpy((uint8*)result + totalSize - sizeof(intptr) - sizeof(intptr), &stackTraceCount, sizeof(intptr));
{
*(intptr*)((uint8*)result + totalSize - sizeof(intptr) - sizeof(intptr)) = stackTraceCount;
memcpy((uint8*)result + totalSize - sizeof(intptr) - sizeof(intptr) - stackTraceCount*sizeof(intptr), stackTraceInfo, stackTraceCount*sizeof(intptr));
markOffsetPtr = (uint16*)((uint8*)result + totalSize - sizeof(intptr) - sizeof(intptr) - stackTraceCount * sizeof(intptr) - 2);
}

View file

@ -59,6 +59,8 @@ namespace bf
{
namespace System
{
class Type_NOFLAGS;
struct DbgRawAllocData
{
Type* mType;
@ -84,7 +86,7 @@ namespace bf
void*(*Alloc)(intptr size);
void(*Free)(void* ptr);
void(*Object_Delete)(bf::System::Object* obj);
void* mUnused0;
Type_NOFLAGS*(*ClassVData_GetTypeDataPtr)(bf::System::ClassVData* classVData);
bf::System::Type* (*Object_GetType)(bf::System::Object* obj);
void(*Object_GCMarkMembers)(bf::System::Object* obj);
bf::System::Object* (*Object_DynamicCastToTypeId)(bf::System::Object* obj, int typeId);
@ -196,28 +198,25 @@ namespace bf
typedef int32 TypeId;
enum BfTypeFlags : uint32
{
BfTypeFlag_HasAppendWantMark = 0x800000
};
class Type : public Object
{
public:
int32 mSize;
TypeId mTypeId;
TypeId mBoxedId;
uint16 mTypeFlags;
int32 mMemberDataOffset;
uint8 mTypeCode;
uint8 mAlign;
public:
Beefy::String GetFullName();
Type_NOFLAGS* GetTypeData();
};
class Type_NOFLAGS
{
public:
intptr mClassVData;
public:
int32 mSize;
TypeId mTypeId;
TypeId mBoxedId;
uint16 mTypeFlags;
BfTypeFlags mTypeFlags;
int32 mMemberDataOffset;
uint8 mTypeCode;
uint8 mAlign;

View file

@ -20,3 +20,11 @@ Beefy::String bf::System::Type::GetFullName()
BFRTCALLBACKS.Object_Delete(strObj);
return str;
}
bf::System::Type_NOFLAGS* bf::System::Type::GetTypeData()
{
if ((BFRTFLAGS & BfRtFlags_ObjectHasDebugFlags) != 0)
return BFRTCALLBACKS.ClassVData_GetTypeDataPtr((bf::System::ClassVData*)(mClassVData & ~0xFF));
else
return BFRTCALLBACKS.ClassVData_GetTypeDataPtr((bf::System::ClassVData*)(mClassVData));
}