1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-08 19:48: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

@ -78,6 +78,33 @@ namespace System
[AlwaysInclude] [AlwaysInclude]
static class Internal static class Internal
{ {
enum BfObjectFlags : uint8
{
None = 0,
Mark1 = 0x01,
Mark2 = 0x02,
Mark3 = 0x03,
Allocated = 0x04,
StackAlloc = 0x08,
AppendAlloc = 0x10,
AllocInfo = 0x20,
AllocInfo_Short = 0x40,
Deleted = 0x80
};
struct AppendAllocEntry
{
public enum Kind
{
case None;
case Object(Object obj);
case Raw(void* ptr, DbgRawAllocData* allocData);
}
public Kind mKind;
public AppendAllocEntry* mNext;
}
[Intrinsic("cast")] [Intrinsic("cast")]
public static extern Object UnsafeCastToObject(void* ptr); public static extern Object UnsafeCastToObject(void* ptr);
[Intrinsic("cast")] [Intrinsic("cast")]
@ -273,11 +300,11 @@ namespace System
[CallingConvention(.Cdecl)] [CallingConvention(.Cdecl)]
public static extern int Dbg_PrepareStackTrace(int baseAllocSize, int maxStackTraceDepth); public static extern int Dbg_PrepareStackTrace(int baseAllocSize, int maxStackTraceDepth);
[CallingConvention(.Cdecl)] [CallingConvention(.Cdecl)]
public static extern void Dbg_ObjectStackInit(Object object, ClassVData* classVData); public static extern void Dbg_ObjectStackInit(Object object, ClassVData* classVData, int size, uint8 allocFlags);
[CallingConvention(.Cdecl)] [CallingConvention(.Cdecl)]
public static extern Object Dbg_ObjectAlloc(TypeInstance typeInst, int size); public static extern Object Dbg_ObjectAlloc(TypeInstance typeInst, int size);
[CallingConvention(.Cdecl)] [CallingConvention(.Cdecl)]
public static extern Object Dbg_ObjectAlloc(ClassVData* classVData, int size, int align, int maxStackTraceDepth); public static extern Object Dbg_ObjectAlloc(ClassVData* classVData, int size, int align, int maxStackTraceDepth, uint8 flags);
[CallingConvention(.Cdecl)] [CallingConvention(.Cdecl)]
public static extern void Dbg_ObjectPreDelete(Object obj); public static extern void Dbg_ObjectPreDelete(Object obj);
[CallingConvention(.Cdecl)] [CallingConvention(.Cdecl)]
@ -293,6 +320,183 @@ namespace System
[CallingConvention(.Cdecl)] [CallingConvention(.Cdecl)]
public static extern void Dbg_RawFree(void* ptr); public static extern void Dbg_RawFree(void* ptr);
#if BF_ENABLE_OBJECT_DEBUG_FLAGS
static void AddAppendInfo(Object rootObj, AppendAllocEntry.Kind kind)
{
Compiler.Assert(sizeof(AppendAllocEntry) <= sizeof(int)*4);
void Handle(AppendAllocEntry* headAllocEntry)
{
if (headAllocEntry.mKind case .None)
{
headAllocEntry.mKind = kind;
}
else
{
AppendAllocEntry* newAppendAllocEntry = (.)new uint8[sizeof(AppendAllocEntry)]*;
newAppendAllocEntry.mKind = kind;
newAppendAllocEntry.mNext = headAllocEntry.mNext;
headAllocEntry.mNext = newAppendAllocEntry;
}
}
if (rootObj.[Friend]mClassVData & (int)BfObjectFlags.AllocInfo_Short != 0)
{
var dbgAllocInfo = rootObj.[DisableObjectAccessChecks, Friend]mDbgAllocInfo;
uint8 allocFlag = (.)(dbgAllocInfo >> 8);
Debug.Assert(allocFlag == 1);
if ((allocFlag & 1) != 0)
{
int allocSize = (.)(dbgAllocInfo >> 16);
int capturedTraceCount = (uint8)(dbgAllocInfo);
uint8* ptr = (.)Internal.UnsafeCastToPtr(rootObj);
ptr += allocSize + capturedTraceCount * sizeof(int);
Handle((.)ptr);
}
}
else if (rootObj.[Friend]mClassVData & (int)BfObjectFlags.AllocInfo != 0)
{
var dbgAllocInfo = rootObj.[DisableObjectAccessChecks, Friend]mDbgAllocInfo;
int allocSize = dbgAllocInfo;
uint8* ptr = (.)Internal.UnsafeCastToPtr(rootObj);
int info = *(int*)(ptr + allocSize);
int capturedTraceCount = info >> 8;
uint8 allocFlag = (.)info;
Debug.Assert(allocFlag == 1);
if ((allocFlag & 1) != 0)
{
ptr += allocSize + capturedTraceCount * sizeof(int) + sizeof(int);
Handle((.)ptr);
}
}
}
#endif
public static void Dbg_ObjectAppended(Object rootObj, Object appendObj)
{
#if BF_ENABLE_OBJECT_DEBUG_FLAGS
AddAppendInfo(rootObj, .Object(appendObj));
#endif
}
public static void Dbg_RawAppended(Object rootObj, void* ptr, DbgRawAllocData* rawAllocData)
{
#if BF_ENABLE_OBJECT_DEBUG_FLAGS
AddAppendInfo(rootObj, .Raw(ptr, rawAllocData));
#endif
}
public static void Dbg_MarkAppended(Object rootObj)
{
#if BF_ENABLE_OBJECT_DEBUG_FLAGS
void Handle(AppendAllocEntry* checkAllocEntry)
{
var checkAllocEntry;
while (checkAllocEntry != null)
{
switch (checkAllocEntry.mKind)
{
case .Object(let obj):
obj.[Friend]GCMarkMembers();
case .Raw(let rawPtr, let allocData):
((function void(void*))allocData.mMarkFunc)(rawPtr);
default:
}
checkAllocEntry = checkAllocEntry.mNext;
}
}
if (rootObj.[DisableObjectAccessChecks, Friend]mClassVData & (int)BfObjectFlags.AllocInfo_Short != 0)
{
var dbgAllocInfo = rootObj.[DisableObjectAccessChecks, Friend]mDbgAllocInfo;
uint8 allocFlag = (.)(dbgAllocInfo >> 8);
if ((allocFlag & 1) != 0)
{
int allocSize = (.)(dbgAllocInfo >> 16);
int capturedTraceCount = (uint8)(dbgAllocInfo);
uint8* ptr = (.)Internal.UnsafeCastToPtr(rootObj);
ptr += allocSize + capturedTraceCount * sizeof(int);
Handle((.)ptr);
}
}
else if (rootObj.[DisableObjectAccessChecks, Friend]mClassVData & (int)BfObjectFlags.AllocInfo != 0)
{
var dbgAllocInfo = rootObj.[DisableObjectAccessChecks, Friend]mDbgAllocInfo;
int allocSize = dbgAllocInfo;
uint8* ptr = (.)Internal.UnsafeCastToPtr(rootObj);
int info = *(int*)(ptr + allocSize);
int capturedTraceCount = info >> 8;
uint8 allocFlag = (.)info;
if ((allocFlag & 1) != 0)
{
ptr += allocSize + capturedTraceCount * sizeof(int) + sizeof(int);
Handle((.)ptr);
}
}
#endif
}
public static void Dbg_AppendDeleted(Object rootObj)
{
#if BF_ENABLE_OBJECT_DEBUG_FLAGS
void Handle(AppendAllocEntry* headAllocEntry)
{
AppendAllocEntry* checkAllocEntry = headAllocEntry;
while (checkAllocEntry != null)
{
switch (checkAllocEntry.mKind)
{
case .Object(let obj):
#unwarn
if (!obj.[DisableObjectAccessChecks]IsDeleted())
{
if (obj.GetType().HasDestructor)
Debug.FatalError("Appended object not deleted with 'delete:append'");
}
case .Raw(let rawPtr, let allocData):
default:
}
var nextAllocEntry = checkAllocEntry.mNext;
if (checkAllocEntry == headAllocEntry)
*checkAllocEntry = default;
else
delete (uint8*)checkAllocEntry;
checkAllocEntry = nextAllocEntry;
}
}
if (rootObj.[DisableObjectAccessChecks, Friend]mClassVData & (int)BfObjectFlags.AllocInfo_Short != 0)
{
var dbgAllocInfo = rootObj.[DisableObjectAccessChecks, Friend]mDbgAllocInfo;
uint8 allocFlag = (.)(dbgAllocInfo >> 8);
if ((allocFlag & 1) != 0)
{
int allocSize = (.)(dbgAllocInfo >> 16);
int capturedTraceCount = (uint8)(dbgAllocInfo);
uint8* ptr = (.)Internal.UnsafeCastToPtr(rootObj);
ptr += allocSize + capturedTraceCount * sizeof(int);
Handle((.)ptr);
}
}
else if (rootObj.[DisableObjectAccessChecks, Friend]mClassVData & (int)BfObjectFlags.AllocInfo != 0)
{
var dbgAllocInfo = rootObj.[DisableObjectAccessChecks, Friend]mDbgAllocInfo;
int allocSize = dbgAllocInfo;
uint8* ptr = (.)Internal.UnsafeCastToPtr(rootObj);
int info = *(int*)(ptr + allocSize);
int capturedTraceCount = info >> 8;
uint8 allocFlag = (.)info;
if ((allocFlag & 1) != 0)
{
ptr += allocSize + capturedTraceCount * sizeof(int) + sizeof(int);
Handle((.)ptr);
}
}
#endif
}
[CallingConvention(.Cdecl)] [CallingConvention(.Cdecl)]
static extern void Shutdown_Internal(); static extern void Shutdown_Internal();
@ -304,19 +508,7 @@ namespace System
} }
#else #else
enum BfObjectFlags : uint8
{
None = 0,
Mark1 = 0x01,
Mark2 = 0x02,
Mark3 = 0x03,
Allocated = 0x04,
StackAlloc = 0x08,
AppendAlloc = 0x10,
AllocInfo = 0x20,
AllocInfo_Short = 0x40,
Deleted = 0x80
};
[NoReturn] [NoReturn]
static void Crash() static void Crash()

View file

@ -178,7 +178,7 @@ namespace System.Reflection
int32 stackCount = Compiler.Options.AllocStackCount; int32 stackCount = Compiler.Options.AllocStackCount;
if (mAllocStackCountOverride != 0) if (mAllocStackCountOverride != 0)
stackCount = mAllocStackCountOverride; stackCount = mAllocStackCountOverride;
obj = Internal.Dbg_ObjectAlloc(mTypeClassVData, allocSize, mInstAlign, stackCount); obj = Internal.Dbg_ObjectAlloc(mTypeClassVData, allocSize, mInstAlign, stackCount, 0);
#else #else
void* mem = new [Align(16)] uint8[allocSize]* (?); void* mem = new [Align(16)] uint8[allocSize]* (?);
obj = Internal.UnsafeCastToObject(mem); obj = Internal.UnsafeCastToObject(mem);

View file

@ -111,7 +111,7 @@ namespace System
function void* (int size) mAlloc; function void* (int size) mAlloc;
function void (void* ptr) mFree; function void (void* ptr) mFree;
function void (Object obj) mObject_Delete; function void (Object obj) mObject_Delete;
void* mUnused0; function void* (ClassVData* vdataPtr) mClassVData_GetTypeData;
function Type (Object obj) mObject_GetType; function Type (Object obj) mObject_GetType;
function void (Object obj) mObject_GCMarkMembers; function void (Object obj) mObject_GCMarkMembers;
function Object (Object obj, int32 typeId) mObject_DynamicCastToTypeId; function Object (Object obj, int32 typeId) mObject_DynamicCastToTypeId;
@ -152,6 +152,16 @@ namespace System
delete obj; delete obj;
} }
static void* ClassVData_GetTypeData(ClassVData* classVData)
{
#if BF_32_BIT
Type type = Type.[Friend]GetType_(classVData.mType2);
#else
Type type = Type.[Friend]GetType_((.)(classVData.mType >> 32));
#endif
return &type.[Friend]mSize;
}
static Type Object_GetType(Object obj) static Type Object_GetType(Object obj)
{ {
#if BF_DBG_RUNTIME #if BF_DBG_RUNTIME
@ -259,6 +269,7 @@ namespace System
mAlloc = => Alloc; mAlloc = => Alloc;
mFree = => Free; mFree = => Free;
mObject_Delete = => Object_Delete; mObject_Delete = => Object_Delete;
mClassVData_GetTypeData = => ClassVData_GetTypeData;
mObject_GetType = => Object_GetType; mObject_GetType = => Object_GetType;
mObject_GCMarkMembers = => Object_GCMarkMembers; mObject_GCMarkMembers = => Object_GCMarkMembers;
mObject_DynamicCastToTypeId = => Object_DynamicCastToTypeId; mObject_DynamicCastToTypeId = => Object_DynamicCastToTypeId;

View file

@ -1660,7 +1660,7 @@ namespace System.Reflection
int32 stackCount = Compiler.Options.AllocStackCount; int32 stackCount = Compiler.Options.AllocStackCount;
if (mAllocStackCountOverride != 0) if (mAllocStackCountOverride != 0)
stackCount = mAllocStackCountOverride; stackCount = mAllocStackCountOverride;
obj = Internal.Dbg_ObjectAlloc([Friend]mTypeClassVData, arraySize, [Friend]mInstAlign, stackCount); obj = Internal.Dbg_ObjectAlloc([Friend]mTypeClassVData, arraySize, [Friend]mInstAlign, stackCount, 0);
#else #else
void* mem = new [Align(16)] uint8[arraySize]* (?); void* mem = new [Align(16)] uint8[arraySize]* (?);
obj = Internal.UnsafeCastToObject(mem); obj = Internal.UnsafeCastToObject(mem);
@ -1720,6 +1720,7 @@ namespace System.Reflection
Static = 0x200000, Static = 0x200000,
Abstract = 0x400000, Abstract = 0x400000,
HasAppendWantMark = 0x800000,
} }
public enum FieldFlags : uint16 public enum FieldFlags : uint16

View file

@ -50,9 +50,9 @@ namespace bf
BFRT_EXPORT static void Dbg_ObjectAllocated(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 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::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::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_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_ObjectPreDelete(bf::System::Object* obj);
BFRT_EXPORT static void Dbg_ObjectPreCustomDelete(bf::System::Object* obj); BFRT_EXPORT static void Dbg_ObjectPreCustomDelete(bf::System::Object* obj);
@ -315,7 +315,7 @@ bf::System::Object* Internal::Dbg_ObjectAlloc(bf::System::Reflection::TypeInstan
//#define DBG_OBJECTEND //#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]; void* stackTrace[1024];
int capturedTraceCount = 0; int capturedTraceCount = 0;
@ -328,7 +328,15 @@ bf::System::Object* Internal::Dbg_ObjectAlloc(bf::System::ClassVData* classVData
{ {
capturedTraceCount = BF_CAPTURE_STACK(1, (intptr*)stackTrace, min((int)maxStackTraceDepth, 1024)); capturedTraceCount = BF_CAPTURE_STACK(1, (intptr*)stackTrace, min((int)maxStackTraceDepth, 1024));
const intptr maxSmallObjectSize = ((intptr)1 << ((sizeof(intptr) - 2) * 8)) - 1; 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; largeAllocInfo = true;
allocSize += (1 + capturedTraceCount) * sizeof(intptr); allocSize += (1 + capturedTraceCount) * sizeof(intptr);
@ -336,6 +344,12 @@ bf::System::Object* Internal::Dbg_ObjectAlloc(bf::System::ClassVData* classVData
else else
allocSize += capturedTraceCount * sizeof(intptr); allocSize += capturedTraceCount * sizeof(intptr);
} }
// Append want mark
if ((allocFlags & 1) != 0)
{
allocSize += 4 * sizeof(intptr);
}
} }
#ifdef DBG_OBJECTEND #ifdef DBG_OBJECTEND
@ -385,7 +399,7 @@ bf::System::Object* Internal::Dbg_ObjectAlloc(bf::System::ClassVData* classVData
intptr dbgAllocInfo; intptr dbgAllocInfo;
auto classVDataVal = (intptr)classVData | (intptr)BfObjectFlag_Allocated; auto classVDataVal = (intptr)classVData | (intptr)BfObjectFlag_Allocated;
if (maxStackTraceDepth <= 1) if ((maxStackTraceDepth <= 1) && (allocFlags == 0))
dbgAllocInfo = (intptr)BF_RETURN_ADDRESS; dbgAllocInfo = (intptr)BF_RETURN_ADDRESS;
else else
{ {
@ -393,13 +407,13 @@ bf::System::Object* Internal::Dbg_ObjectAlloc(bf::System::ClassVData* classVData
{ {
classVDataVal |= (intptr)BfObjectFlag_AllocInfo; classVDataVal |= (intptr)BfObjectFlag_AllocInfo;
dbgAllocInfo = size; dbgAllocInfo = size;
*(intptr*)((uint8*)result + size) = capturedTraceCount; *(intptr*)((uint8*)result + size) = (capturedTraceCount << 8) | allocFlags;
memcpy((uint8*)result + size + sizeof(intptr), stackTrace, capturedTraceCount * sizeof(intptr)); memcpy((uint8*)result + size + sizeof(intptr), stackTrace, capturedTraceCount * sizeof(intptr));
} }
else else
{ {
classVDataVal |= (intptr)BfObjectFlag_AllocInfo_Short; classVDataVal |= (intptr)BfObjectFlag_AllocInfo_Short;
dbgAllocInfo = (size << 16) | capturedTraceCount; dbgAllocInfo = (size << 16) | (((intptr)allocFlags) << 8) | capturedTraceCount;
memcpy((uint8*)result + size, stackTrace, capturedTraceCount * sizeof(intptr)); memcpy((uint8*)result + size, stackTrace, capturedTraceCount * sizeof(intptr));
} }
} }
@ -424,13 +438,27 @@ bf::System::Object* Internal::Dbg_ObjectAlloc(bf::System::ClassVData* classVData
return result; 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); BF_ASSERT((BFRTFLAGS & BfRtFlags_ObjectHasDebugFlags) != 0);
result->mClassVData = (intptr)classVData | (intptr)BfObjectFlag_StackAlloc; result->mClassVData = (intptr)classVData | (intptr)BfObjectFlag_StackAlloc;
#ifndef BFRT_NODBGFLAGS #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 #endif
} }

View file

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

View file

@ -119,12 +119,14 @@ void BFGC::RawMarkSpan(tcmalloc_raw::Span* span, int expectedStartPage)
intptr extraDataSize = sizeof(intptr); intptr extraDataSize = sizeof(intptr);
if (rawAllocData->mMaxStackTrace == 1) 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) else if (rawAllocData->mMaxStackTrace > 1)
{ {
intptr 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) + 2;
extraDataSize += *(uint16*)((uint8*)spanPtr + elementSize - sizeof(intptr) - sizeof(intptr) - stackTraceCount * sizeof(intptr) - 2);
} }
struct MarkTarget struct MarkTarget
@ -133,16 +135,20 @@ void BFGC::RawMarkSpan(tcmalloc_raw::Span* span, int expectedStartPage)
typedef void(MarkTarget::*MarkFunc)(); typedef void(MarkTarget::*MarkFunc)();
MarkFunc markFunc = *(MarkFunc*)&rawAllocData->mMarkFunc; MarkFunc markFunc = *(MarkFunc*)&rawAllocData->mMarkFunc;
// It's possible we can overestimate elemCount, particularly for large allocations. This doesn't cause a problem auto typeData = rawAllocData->mType->GetTypeData();
// because we can safely mark on complete random memory -- pointer values are always validated before being followed if (typeData != NULL)
intptr elemStride = BF_ALIGN(rawAllocData->mType->mSize, rawAllocData->mType->mAlign);
if (elemStride > 0)
{ {
intptr dataSize = elementSize - extraDataSize; // It's possible we can overestimate elemCount, particularly for large allocations. This doesn't cause a problem
intptr elemCount = dataSize / elemStride; // because we can safely mark on complete random memory -- pointer values are always validated before being followed
for (intptr elemIdx = 0; elemIdx < elemCount; elemIdx++) 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) if (rawAllocData->mType != NULL)
{ {
intptr typeSize; bf::System::Type_NOFLAGS* typeData = rawAllocData->mType->GetTypeData();
if ((gBfRtDbgFlags & BfRtFlags_ObjectHasDebugFlags) != 0) if (typeData != NULL)
typeSize = rawAllocData->mType->mSize; {
else intptr typeSize = typeData->mSize;
typeSize = ((bf::System::Type_NOFLAGS*)rawAllocData->mType)->mSize; if (typeSize > 0)
if (typeSize > 0) rawLeakInfo.mDataCount = (elementSize - extraDataSize) / typeSize;
rawLeakInfo.mDataCount = (elementSize - extraDataSize) / typeSize; }
} }
else else
rawLeakInfo.mDataCount = 1; rawLeakInfo.mDataCount = 1;
@ -559,7 +565,7 @@ void* BfRawAllocate(intptr size, bf::System::DbgRawAllocData* rawAllocData, void
} }
else if (rawAllocData->mMaxStackTrace > 1) 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)); 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); markOffsetPtr = (uint16*)((uint8*)result + totalSize - sizeof(intptr) - sizeof(intptr) - stackTraceCount * sizeof(intptr) - 2);
} }

View file

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

View file

@ -20,3 +20,11 @@ Beefy::String bf::System::Type::GetFullName()
BFRTCALLBACKS.Object_Delete(strObj); BFRTCALLBACKS.Object_Delete(strObj);
return str; 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));
}

View file

@ -1232,6 +1232,7 @@ void BfContext::RebuildType(BfType* type, bool deleteOnDemandTypes, bool rebuild
typeInst->mHasPackingHoles = false; typeInst->mHasPackingHoles = false;
typeInst->mWantsGCMarking = false; typeInst->mWantsGCMarking = false;
typeInst->mHasDeclError = false; typeInst->mHasDeclError = false;
typeInst->mHasAppendWantMark = false;
delete typeInst->mTypeInfoEx; delete typeInst->mTypeInfoEx;
typeInst->mTypeInfoEx = NULL; typeInst->mTypeInfoEx = NULL;

View file

@ -2067,6 +2067,15 @@ void BfDefBuilder::FinishTypeDef(bool wantsToString)
BfMethodDef* strictEqualsMethod = NULL; BfMethodDef* strictEqualsMethod = NULL;
bool needsStaticInit = false; bool needsStaticInit = false;
if (mCurTypeDef->IsExtension())
needsDefaultCtor = false;
bool needsDtor = false;
bool needsStaticDtor = false;
bool hasStaticField = false;
bool hasNonStaticField = false;
bool hasThreadStatics = false;
for (int methodIdx = 0; methodIdx < (int)mCurTypeDef->mMethods.size(); methodIdx++) for (int methodIdx = 0; methodIdx < (int)mCurTypeDef->mMethods.size(); methodIdx++)
{ {
auto method = mCurTypeDef->mMethods[methodIdx]; auto method = mCurTypeDef->mMethods[methodIdx];
@ -2080,6 +2089,9 @@ void BfDefBuilder::FinishTypeDef(bool wantsToString)
if (method->mMethodType == BfMethodType_Ctor) if (method->mMethodType == BfMethodType_Ctor)
{ {
if (method->HasAppend())
needsDtor = true;
if (method->mIsStatic) if (method->mIsStatic)
{ {
if ((staticCtor != NULL) && (staticCtor->mMethodDeclaration != NULL)) if ((staticCtor != NULL) && (staticCtor->mMethodDeclaration != NULL))
@ -2240,14 +2252,6 @@ void BfDefBuilder::FinishTypeDef(bool wantsToString)
needsStaticInit = true; needsStaticInit = true;
} }
if (mCurTypeDef->IsExtension())
needsDefaultCtor = false;
bool needsDtor = false;
bool needsStaticDtor = false;
bool hasStaticField = false;
bool hasNonStaticField = false;
bool hasThreadStatics = false;
for (auto field : mCurTypeDef->mFields) for (auto field : mCurTypeDef->mFields)
{ {
if (field->mIsStatic) if (field->mIsStatic)

View file

@ -7492,7 +7492,7 @@ void BfExprEvaluator::PushThis(BfAstNode* targetSrc, BfTypedValue argVal, BfMeth
else else
allowThisSplatting = methodInstance->AllowsSplatting(-1); allowThisSplatting = methodInstance->AllowsSplatting(-1);
if ((!allowThisSplatting) || (methodDef->mIsMutating)) if ((!allowThisSplatting) || (methodDef->mIsMutating) || (methodInstance->mCallingConvention == BfCallingConvention_Cdecl))
{ {
argVal = mModule->MakeAddressable(argVal); argVal = mModule->MakeAddressable(argVal);
irArgs.push_back(argVal.mValue); irArgs.push_back(argVal.mValue);
@ -16570,6 +16570,7 @@ void BfExprEvaluator::CreateObject(BfObjectCreateExpression* objCreateExpr, BfAs
if (typeInstance != NULL) if (typeInstance != NULL)
allocAlign = typeInstance->mInstAlign; allocAlign = typeInstance->mInstAlign;
int appendAllocAlign = 0; int appendAllocAlign = 0;
BfAllocFlags allocFlags = BfAllocFlags_None;
if ((bindResult.mMethodInstance != NULL) && (bindResult.mMethodInstance->mMethodDef->HasAppend())) if ((bindResult.mMethodInstance != NULL) && (bindResult.mMethodInstance->mMethodDef->HasAppend()))
{ {
@ -16605,6 +16606,9 @@ void BfExprEvaluator::CreateObject(BfObjectCreateExpression* objCreateExpr, BfAs
appendSizeValue = appendSizeTypedValue.mValue; appendSizeValue = appendSizeTypedValue.mValue;
allocAlign = BF_MAX(allocAlign, calcAppendMethodModule.mMethodInstance->mAppendAllocAlign); allocAlign = BF_MAX(allocAlign, calcAppendMethodModule.mMethodInstance->mAppendAllocAlign);
appendAllocAlign = calcAppendMethodModule.mMethodInstance->mAppendAllocAlign; appendAllocAlign = calcAppendMethodModule.mMethodInstance->mAppendAllocAlign;
if (calcAppendMethodModule.mMethodInstance->mHasAppendWantMark)
allocFlags = (BfAllocFlags)(allocFlags | BfAllocFlags_HasAppendWantMark);
} }
if (appendAllocAlign != 0) if (appendAllocAlign != 0)
@ -16616,6 +16620,12 @@ void BfExprEvaluator::CreateObject(BfObjectCreateExpression* objCreateExpr, BfAs
appendSizeValue = mModule->mBfIRBuilder->CreateAdd(appendSizeValue, mModule->GetConstValue(extraSize)); appendSizeValue = mModule->mBfIRBuilder->CreateAdd(appendSizeValue, mModule->GetConstValue(extraSize));
} }
} }
if ((allocFlags & BfAllocFlags_HasAppendWantMark) != 0)
{
int markInfoSize = sizeof(intptr) + sizeof(intptr) * 4; // Stack trace, MarkAppendEntry
appendSizeValue = mModule->mBfIRBuilder->CreateAdd(appendSizeValue, mModule->GetConstValue(markInfoSize));
}
} }
// WTF? I'm not even sure this is correct - add more tests // WTF? I'm not even sure this is correct - add more tests
@ -16635,7 +16645,7 @@ void BfExprEvaluator::CreateObject(BfObjectCreateExpression* objCreateExpr, BfAs
} }
else else
{ {
allocValue = mModule->AllocFromType(resolvedTypeRef, allocTarget, appendSizeValue, BfIRValue(), 0, BfAllocFlags_None, allocAlign); allocValue = mModule->AllocFromType(resolvedTypeRef, allocTarget, appendSizeValue, BfIRValue(), 0, allocFlags, allocAlign);
} }
if (((mBfEvalExprFlags & BfEvalExprFlags_Comptime) != 0) && (mModule->mCompiler->mCeMachine != NULL)) if (((mBfEvalExprFlags & BfEvalExprFlags_Comptime) != 0) && (mModule->mCompiler->mCeMachine != NULL))
{ {
@ -16710,14 +16720,21 @@ void BfExprEvaluator::CreateObject(BfObjectCreateExpression* objCreateExpr, BfAs
{ {
auto impMethodInstance = (BfMethodInstance*)vtableEntry.mImplementingMethod; auto impMethodInstance = (BfMethodInstance*)vtableEntry.mImplementingMethod;
bool needsCall = false; bool needsCall = false;
if (impMethodInstance != NULL)
{ if (allocFlags & BfAllocFlags_HasAppendWantMark)
needsCall = impMethodInstance->mMethodDef->mBody != NULL;
}
else
{
needsCall = true; needsCall = true;
BF_ASSERT(vtableEntry.mImplementingMethod.mKind == BfMethodRefKind_AmbiguousRef);
if (!needsCall)
{
if (impMethodInstance != NULL)
{
needsCall = impMethodInstance->mMethodDef->mBody != NULL;
}
else
{
needsCall = true;
BF_ASSERT(vtableEntry.mImplementingMethod.mKind == BfMethodRefKind_AmbiguousRef);
}
} }
if (!needsCall) if (!needsCall)

View file

@ -475,6 +475,7 @@ public:
BfTypedValue mConstAccum; BfTypedValue mConstAccum;
bool mFailed; bool mFailed;
bool mIsFirstConstPass; bool mIsFirstConstPass;
bool mHasAppendWantMark;
int mCurAppendAlign; int mCurAppendAlign;
public: public:
@ -482,6 +483,7 @@ public:
{ {
mFailed = false; mFailed = false;
mIsFirstConstPass = false; mIsFirstConstPass = false;
mHasAppendWantMark = false;
mCurAppendAlign = 1; mCurAppendAlign = 1;
} }
@ -654,6 +656,9 @@ public:
return; return;
} }
if (origResolvedTypeRef->WantsGCMarking())
mHasAppendWantMark = true;
bool isGenericParam = origResolvedTypeRef->IsGenericParam(); bool isGenericParam = origResolvedTypeRef->IsGenericParam();
auto resolvedTypeRef = origResolvedTypeRef; auto resolvedTypeRef = origResolvedTypeRef;
auto resultType = resolvedTypeRef; auto resultType = resolvedTypeRef;
@ -6272,6 +6277,8 @@ BfIRValue BfModule::GetTypeTypeData(BfType* type, BfCreateTypeDataContext& ctx,
typeFlags |= BfTypeFlags_Static; typeFlags |= BfTypeFlags_Static;
if ((typeInstance != NULL) && (typeInstance->mTypeDef->mIsAbstract)) if ((typeInstance != NULL) && (typeInstance->mTypeDef->mIsAbstract))
typeFlags |= BfTypeFlags_Abstract; typeFlags |= BfTypeFlags_Abstract;
if ((typeInstance != NULL) && (typeInstance->mHasAppendWantMark))
typeFlags |= BfTypeFlags_HasAppendWantMark;
return typeTypeData; return typeTypeData;
} }
@ -9534,7 +9541,7 @@ BfTypedValue BfModule::GetOrCreateVarAddr(BfExpression* expr)
} }
// Clear memory, set classVData, call init. Actual ctor is called elsewhere. // Clear memory, set classVData, call init. Actual ctor is called elsewhere.
void BfModule::InitTypeInst(BfTypedValue typedValue, BfScopeData* scopeData, bool zeroMemory, BfIRValue sizeValue) void BfModule::InitTypeInst(BfTypedValue typedValue, BfScopeData* scopeData, bool zeroMemory, BfIRValue sizeValue, BfAllocFlags allocFlags)
{ {
auto typeInstance = typedValue.mType->ToTypeInstance(); auto typeInstance = typedValue.mType->ToTypeInstance();
if (zeroMemory) if (zeroMemory)
@ -9581,6 +9588,8 @@ void BfModule::InitTypeInst(BfTypedValue typedValue, BfScopeData* scopeData, boo
SizedArray<BfIRValue, 4> llvmArgs; SizedArray<BfIRValue, 4> llvmArgs;
llvmArgs.push_back(objectPtr); llvmArgs.push_back(objectPtr);
llvmArgs.push_back(vDataRef); llvmArgs.push_back(vDataRef);
llvmArgs.push_back(sizeValue);
llvmArgs.push_back(mBfIRBuilder->CreateConst(BfTypeCode_Int8, allocFlags));
auto objectStackInitMethod = GetInternalMethod("Dbg_ObjectStackInit"); auto objectStackInitMethod = GetInternalMethod("Dbg_ObjectStackInit");
if (objectStackInitMethod) if (objectStackInitMethod)
@ -10213,7 +10222,7 @@ BfIRValue BfModule::AllocFromType(BfType* type, const BfAllocTarget& allocTarget
doCondAlloca = !wasDynAlloc && isDynAlloc && mCurMethodState->mInConditionalBlock; doCondAlloca = !wasDynAlloc && isDynAlloc && mCurMethodState->mInConditionalBlock;
AddStackAlloc(typedVal, arraySize, NULL, scopeData, doCondAlloca, true); AddStackAlloc(typedVal, arraySize, NULL, scopeData, doCondAlloca, true);
} }
InitTypeInst(typedVal, scopeData, zeroMemory, sizeValue); InitTypeInst(typedVal, scopeData, zeroMemory, sizeValue, allocFlags);
return typedVal.mValue; return typedVal.mValue;
} }
@ -10443,7 +10452,8 @@ BfIRValue BfModule::AllocFromType(BfType* type, const BfAllocTarget& allocTarget
llvmArgs.push_back(sizeValue); llvmArgs.push_back(sizeValue);
llvmArgs.push_back(GetConstValue(typeInstance->mAlign)); llvmArgs.push_back(GetConstValue(typeInstance->mAlign));
llvmArgs.push_back(GetConstValue(stackCount)); llvmArgs.push_back(GetConstValue(stackCount));
auto moduleMethodInstance = GetInternalMethod("Dbg_ObjectAlloc", 4); llvmArgs.push_back(GetConstValue(allocFlags, GetPrimitiveType(BfTypeCode_Int8)));
auto moduleMethodInstance = GetInternalMethod("Dbg_ObjectAlloc", 5);
BfIRValue objectVal = mBfIRBuilder->CreateCall(moduleMethodInstance.mFunc, llvmArgs); BfIRValue objectVal = mBfIRBuilder->CreateCall(moduleMethodInstance.mFunc, llvmArgs);
result = mBfIRBuilder->CreateBitCast(objectVal, mBfIRBuilder->MapType(typeInstance)); result = mBfIRBuilder->CreateBitCast(objectVal, mBfIRBuilder->MapType(typeInstance));
} }
@ -10647,6 +10657,9 @@ BfIRValue BfModule::AppendAllocFromType(BfType* type, BfIRValue appendSizeValue,
BfIRType toType; BfIRType toType;
if (typeInst != NULL) if (typeInst != NULL)
{ {
mBfIRBuilder->PopulateType(typeInst);
if (typeInst->WantsGCMarking())
mCurTypeInstance->mHasAppendWantMark = true;
EmitAppendAlign(typeInst->mInstAlign, typeInst->mInstSize); EmitAppendAlign(typeInst->mInstAlign, typeInst->mInstSize);
sizeValue = GetConstValue(typeInst->mInstSize); sizeValue = GetConstValue(typeInst->mInstSize);
toType = mBfIRBuilder->MapTypeInstPtr(typeInst); toType = mBfIRBuilder->MapTypeInstPtr(typeInst);
@ -10665,6 +10678,35 @@ BfIRValue BfModule::AppendAllocFromType(BfType* type, BfIRValue appendSizeValue,
retTypeInstance = typeInst; retTypeInstance = typeInst;
retValue = mBfIRBuilder->CreateIntToPtr(curIdxVal, toType); retValue = mBfIRBuilder->CreateIntToPtr(curIdxVal, toType);
if ((typeInst != NULL) && (typeInst->WantsGCMarking()) && (mCompiler->mOptions.mDebugAlloc))
{
auto curThis = GetThis();
auto thisObj = Cast(mCurMethodInstance->mMethodDef->GetRefNode(), curThis, mContext->mBfObjectType);
if (typeInst->IsObject())
{
auto appendedObj = Cast(mCurMethodInstance->mMethodDef->GetRefNode(), BfTypedValue(retValue, typeInst), mContext->mBfObjectType);
BfModuleMethodInstance allocMethod = GetInternalMethod("Dbg_ObjectAppended", 2);
SizedArray<BfIRValue, 2> llvmArgs;
llvmArgs.push_back(thisObj.mValue);
llvmArgs.push_back(appendedObj.mValue);
mBfIRBuilder->CreateCall(allocMethod.mFunc, llvmArgs);
}
else
{
// Raw
BfIRValue allocPtr = mBfIRBuilder->CreateBitCast(retValue, mBfIRBuilder->MapType(voidPtrType));
BfIRValue allocData = GetDbgRawAllocData(type);
BfModuleMethodInstance allocMethod = GetInternalMethod("Dbg_RawAppended", 3);
SizedArray<BfIRValue, 3> llvmArgs;
llvmArgs.push_back(thisObj.mValue);
llvmArgs.push_back(allocPtr);
llvmArgs.push_back(allocData);
mBfIRBuilder->CreateCall(allocMethod.mFunc, llvmArgs);
}
}
} }
if ((retTypeInstance != NULL) && (retTypeInstance->IsObject())) if ((retTypeInstance != NULL) && (retTypeInstance->IsObject()))
@ -15871,7 +15913,7 @@ BfTypedValue BfModule::GetThis(bool markUsing)
auto curMethodOwner = mCurMethodInstance->mMethodInstanceGroup->mOwner; auto curMethodOwner = mCurMethodInstance->mMethodInstanceGroup->mOwner;
if ((curMethodOwner->IsStruct()) || (curMethodOwner->IsTypedPrimitive())) if ((curMethodOwner->IsStruct()) || (curMethodOwner->IsTypedPrimitive()))
{ {
if ((localDef->mResolvedType->IsTypedPrimitive()) && (!mCurMethodInstance->mMethodDef->mIsMutating)) if ((localDef->mResolvedType->IsTypedPrimitive()) && (!mCurMethodInstance->mMethodDef->mIsMutating) && (mCurMethodInstance->mCallingConvention != BfCallingConvention_Cdecl))
{ {
return BfTypedValue(thisValue, useMethodState->mLocals[0]->mResolvedType, BfTypedValueKind_ReadOnlyThisValue); return BfTypedValue(thisValue, useMethodState->mLocals[0]->mResolvedType, BfTypedValueKind_ReadOnlyThisValue);
} }
@ -17411,6 +17453,9 @@ BfTypedValue BfModule::TryConstCalcAppend(BfMethodInstance* methodInst, SizedArr
appendAllocVisitor.mFailed = true; appendAllocVisitor.mFailed = true;
if (!appendAllocVisitor.mFailed) if (!appendAllocVisitor.mFailed)
constValue = appendAllocVisitor.mConstAccum; constValue = appendAllocVisitor.mConstAccum;
if (appendAllocVisitor.mHasAppendWantMark)
methodInst->mHasAppendWantMark = true;
if (isFirstRun) if (isFirstRun)
{ {
mCurMethodInstance->mEndingAppendAllocAlign = appendAllocVisitor.mCurAppendAlign; mCurMethodInstance->mEndingAppendAllocAlign = appendAllocVisitor.mCurAppendAlign;
@ -18090,6 +18135,19 @@ void BfModule::EmitDtorBody()
} }
} }
} }
// If there are appends then we just need the rootmost append type to do the Dbg_AppendDeleted
if ((!mIsComptimeModule) && (!methodDef->mIsStatic) && (mCompiler->mOptions.mDebugAlloc) &&
(mCurTypeInstance->HasAppendCtor()) && (!mCurTypeInstance->BaseHasAppendCtor()))
{
auto thisValue = GetThis();
auto appendedObj = mBfIRBuilder->CreateBitCast(thisValue.mValue, mBfIRBuilder->MapType(mContext->mBfObjectType));
BfModuleMethodInstance allocMethod = GetInternalMethod("Dbg_AppendDeleted", 1);
SizedArray<BfIRValue, 1> llvmArgs;
llvmArgs.push_back(appendedObj);
if (allocMethod)
mBfIRBuilder->CreateCall(allocMethod.mFunc, llvmArgs);
}
} }
BfIRValue BfModule::CreateDllImportGlobalVar(BfMethodInstance* methodInstance, bool define) BfIRValue BfModule::CreateDllImportGlobalVar(BfMethodInstance* methodInstance, bool define)
@ -20534,6 +20592,19 @@ void BfModule::EmitGCMarkMembers()
CallChainedMethods(mCurMethodInstance, false); CallChainedMethods(mCurMethodInstance, false);
} }
} }
// If there are appends then we just need the rootmost append type to do the Dbg_MarkAppended
if ((!mIsComptimeModule) && (!methodDef->mIsStatic) && (mCompiler->mOptions.mDebugAlloc) &&
(mCurTypeInstance->HasAppendCtor()) && (!mCurTypeInstance->BaseHasAppendCtor()))
{
auto thisValue = GetThis();
auto appendedObj = mBfIRBuilder->CreateBitCast(thisValue.mValue, mBfIRBuilder->MapType(mContext->mBfObjectType));
BfModuleMethodInstance allocMethod = GetInternalMethod("Dbg_MarkAppended", 1);
SizedArray<BfIRValue, 1> llvmArgs;
llvmArgs.push_back(appendedObj);
if (allocMethod)
mBfIRBuilder->CreateCall(allocMethod.mFunc, llvmArgs);
}
} }
void BfModule::EmitGCFindTLSMembers() void BfModule::EmitGCFindTLSMembers()
@ -21452,7 +21523,8 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup,
else else
{ {
bool wantPtr = (thisType->IsComposite()) && (!paramVar->mIsLowered); bool wantPtr = (thisType->IsComposite()) && (!paramVar->mIsLowered);
if ((thisType->IsTypedPrimitive()) && (methodDef->HasNoThisSplat())) if ((thisType->IsTypedPrimitive()) &&
((methodDef->HasNoThisSplat()) || (methodInstance->mCallingConvention == BfCallingConvention_Cdecl)))
wantPtr = true; wantPtr = true;
if (wantPtr) if (wantPtr)
@ -21582,7 +21654,8 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup,
{ {
diType = mBfIRBuilder->DbgGetType(paramVar->mResolvedType); diType = mBfIRBuilder->DbgGetType(paramVar->mResolvedType);
bool wantRef = paramVar->mResolvedType->IsComposite(); bool wantRef = paramVar->mResolvedType->IsComposite();
if ((paramVar->mResolvedType->IsTypedPrimitive()) && (methodDef->HasNoThisSplat())) if ((paramVar->mResolvedType->IsTypedPrimitive()) &&
((methodDef->HasNoThisSplat()) || (methodInstance->mCallingConvention == BfCallingConvention_Cdecl)))
wantRef = true; wantRef = true;
if (wantRef) if (wantRef)
@ -23897,6 +23970,12 @@ void BfModule::GetMethodCustomAttributes(BfMethodInstance* methodInstance)
} }
methodInstance->mCallingConvention = methodDef->mCallingConvention; methodInstance->mCallingConvention = methodDef->mCallingConvention;
if ((typeInstance->IsValueType()) && (methodDef->mIsOverride) && (methodDef->mName == BF_METHODNAME_MARKMEMBERS))
{
// Make sure we we pass 'this' as a pointer into GCMarkMembers so it's compatible with the mark function pointer
methodInstance->mCallingConvention = BfCallingConvention_Cdecl;
}
if (customAttributes != NULL) if (customAttributes != NULL)
{ {
auto linkNameAttr = customAttributes->Get(mCompiler->mCallingConventionAttributeTypeDef); auto linkNameAttr = customAttributes->Get(mCompiler->mCallingConventionAttributeTypeDef);

View file

@ -128,10 +128,11 @@ enum BfCastResultFlags : int8
enum BfAllocFlags : int8 enum BfAllocFlags : int8
{ {
BfAllocFlags_None = 0, BfAllocFlags_None = 0,
BfAllocFlags_RawArray = 1, BfAllocFlags_HasAppendWantMark = 1,
BfAllocFlags_ZeroMemory = 2, BfAllocFlags_RawArray = 2,
BfAllocFlags_NoDtorCall = 4, BfAllocFlags_ZeroMemory = 4,
BfAllocFlags_NoDefaultToMalloc = 8 BfAllocFlags_NoDtorCall = 8,
BfAllocFlags_NoDefaultToMalloc = 0x10,
}; };
enum BfProtectionCheckFlags : int8 enum BfProtectionCheckFlags : int8
@ -1736,7 +1737,7 @@ public:
void CleanupFileInstances(); void CleanupFileInstances();
void AssertErrorState(); void AssertErrorState();
void AssertParseErrorState(); void AssertParseErrorState();
void InitTypeInst(BfTypedValue typedValue, BfScopeData* scope, bool zeroMemory, BfIRValue dataSize); void InitTypeInst(BfTypedValue typedValue, BfScopeData* scope, bool zeroMemory, BfIRValue dataSize, BfAllocFlags allocFlags = BfAllocFlags_None);
bool IsAllocatorAligned(); bool IsAllocatorAligned();
BfIRValue AllocBytes(BfAstNode* refNode, const BfAllocTarget& allocTarget, BfType* type, BfIRValue sizeValue, BfIRValue alignValue, BfAllocFlags allocFlags/*bool zeroMemory, bool defaultToMalloc*/); BfIRValue AllocBytes(BfAstNode* refNode, const BfAllocTarget& allocTarget, BfType* type, BfIRValue sizeValue, BfIRValue alignValue, BfAllocFlags allocFlags/*bool zeroMemory, bool defaultToMalloc*/);
BfIRValue GetMarkFuncPtr(BfType* type); BfIRValue GetMarkFuncPtr(BfType* type);

View file

@ -1381,11 +1381,6 @@ int BfMethodInstance::DbgGetVirtualMethodNum()
void BfMethodInstance::GetIRFunctionInfo(BfModule* module, BfIRType& returnType, SizedArrayImpl<BfIRType>& paramTypes, bool forceStatic) void BfMethodInstance::GetIRFunctionInfo(BfModule* module, BfIRType& returnType, SizedArrayImpl<BfIRType>& paramTypes, bool forceStatic)
{ {
if (mMethodDef->mName == "Test4")
{
NOP;
}
BfModule* resolveModule = module->mContext->mUnreifiedModule; BfModule* resolveModule = module->mContext->mUnreifiedModule;
resolveModule->PopulateType(mReturnType); resolveModule->PopulateType(mReturnType);
@ -1458,7 +1453,11 @@ void BfMethodInstance::GetIRFunctionInfo(BfModule* module, BfIRType& returnType,
bool doSplat = false; bool doSplat = false;
if (paramIdx == -1) if (paramIdx == -1)
{ {
if ((!mMethodDef->mIsMutating) && (checkType->IsTypedPrimitive())) if (mCallingConvention == BfCallingConvention_Cdecl)
{
// Pass by pointer even for typed primitives
}
else if ((!mMethodDef->mIsMutating) && (checkType->IsTypedPrimitive()))
{ {
checkType = checkType->GetUnderlyingType(); checkType = checkType->GetUnderlyingType();
} }
@ -2468,6 +2467,22 @@ bool BfTypeInstance::IsAnonymousInitializerType()
return (mTypeDef->mTypeDeclaration != NULL) && (mTypeDef->mTypeDeclaration->IsAnonymousInitializerType()); return (mTypeDef->mTypeDeclaration != NULL) && (mTypeDef->mTypeDeclaration->IsAnonymousInitializerType());
} }
bool BfTypeInstance::HasAppendCtor()
{
return mTypeDef->mHasAppendCtor;
}
bool BfTypeInstance::BaseHasAppendCtor()
{
if (mBaseType != NULL)
{
if (mBaseType->HasAppendCtor())
return true;
return mBaseType->BaseHasAppendCtor();
}
return false;
}
void BfTypeInstance::ReportMemory(MemReporter* memReporter) void BfTypeInstance::ReportMemory(MemReporter* memReporter)
{ {
if (mGenericTypeInfo != NULL) if (mGenericTypeInfo != NULL)

View file

@ -908,6 +908,7 @@ public:
bool mInCEMachine:1; bool mInCEMachine:1;
bool mCeCancelled:1; bool mCeCancelled:1;
bool mIsDisposed:1; bool mIsDisposed:1;
bool mHasAppendWantMark:1;
BfMethodChainType mChainType; BfMethodChainType mChainType;
BfComptimeFlags mComptimeFlags; BfComptimeFlags mComptimeFlags;
BfCallingConvention mCallingConvention; BfCallingConvention mCallingConvention;
@ -951,6 +952,7 @@ public:
mInCEMachine = false; mInCEMachine = false;
mCeCancelled = false; mCeCancelled = false;
mIsDisposed = false; mIsDisposed = false;
mHasAppendWantMark = false;
mChainType = BfMethodChainType_None; mChainType = BfMethodChainType_None;
mComptimeFlags = BfComptimeFlag_None; mComptimeFlags = BfComptimeFlag_None;
mCallingConvention = BfCallingConvention_Unspecified; mCallingConvention = BfCallingConvention_Unspecified;
@ -2064,6 +2066,7 @@ public:
bool mHasPackingHoles; bool mHasPackingHoles;
bool mWantsGCMarking; bool mWantsGCMarking;
bool mHasDeclError; bool mHasDeclError;
bool mHasAppendWantMark;
public: public:
BfTypeInstance() BfTypeInstance()
@ -2116,6 +2119,7 @@ public:
mWantsGCMarking = false; mWantsGCMarking = false;
mHasParameterizedBase = false; mHasParameterizedBase = false;
mHasDeclError = false; mHasDeclError = false;
mHasAppendWantMark = false;
mMergedFieldDataCount = 0; mMergedFieldDataCount = 0;
mConstHolder = NULL; mConstHolder = NULL;
} }
@ -2213,6 +2217,8 @@ public:
bool DefineStateAllowsStaticMethods() { return mDefineState >= BfTypeDefineState_HasInterfaces_Direct; } bool DefineStateAllowsStaticMethods() { return mDefineState >= BfTypeDefineState_HasInterfaces_Direct; }
bool IsAnonymous(); bool IsAnonymous();
bool IsAnonymousInitializerType(); bool IsAnonymousInitializerType();
bool HasAppendCtor();
bool BaseHasAppendCtor();
virtual void ReportMemory(MemReporter* memReporter) override; virtual void ReportMemory(MemReporter* memReporter) override;
}; };

View file

@ -239,6 +239,7 @@ enum BfTypeFlags
BfTypeFlags_Static = 0x200000, BfTypeFlags_Static = 0x200000,
BfTypeFlags_Abstract = 0x400000, BfTypeFlags_Abstract = 0x400000,
BfTypeFlags_HasAppendWantMark = 0x800000,
}; };
enum BfMethodFlags enum BfMethodFlags

View file

@ -8513,7 +8513,7 @@ String WinDebugger::DbgTypedValueToString(const DbgTypedValue& origTypedValue, c
{ {
addr_target objectSize = ReadMemory<addr_target>(ptrVal + sizeof(addr_target)); addr_target objectSize = ReadMemory<addr_target>(ptrVal + sizeof(addr_target));
addr_target largeAllocInfo = ReadMemory<addr_target>(ptrVal + objectSize); addr_target largeAllocInfo = ReadMemory<addr_target>(ptrVal + objectSize);
stackTraceLen = largeAllocInfo & 0xFFFF; stackTraceLen = (largeAllocInfo >> 8) & 0xFFFF;
stackTraceAddr = ptrVal + objectSize + sizeof(addr_target); stackTraceAddr = ptrVal + objectSize + sizeof(addr_target);
} }
else if ((bfObjectFlags & BfObjectFlag_AllocInfo_Short) != 0) else if ((bfObjectFlags & BfObjectFlag_AllocInfo_Short) != 0)