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:
parent
9ae172c43f
commit
9baf0ead21
18 changed files with 475 additions and 103 deletions
|
@ -78,6 +78,33 @@ namespace System
|
|||
[AlwaysInclude]
|
||||
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")]
|
||||
public static extern Object UnsafeCastToObject(void* ptr);
|
||||
[Intrinsic("cast")]
|
||||
|
@ -273,11 +300,11 @@ namespace System
|
|||
[CallingConvention(.Cdecl)]
|
||||
public static extern int Dbg_PrepareStackTrace(int baseAllocSize, int maxStackTraceDepth);
|
||||
[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)]
|
||||
public static extern Object Dbg_ObjectAlloc(TypeInstance typeInst, int size);
|
||||
[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)]
|
||||
public static extern void Dbg_ObjectPreDelete(Object obj);
|
||||
[CallingConvention(.Cdecl)]
|
||||
|
@ -293,6 +320,183 @@ namespace System
|
|||
[CallingConvention(.Cdecl)]
|
||||
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)]
|
||||
static extern void Shutdown_Internal();
|
||||
|
||||
|
@ -304,19 +508,7 @@ namespace System
|
|||
}
|
||||
#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]
|
||||
static void Crash()
|
||||
|
|
|
@ -178,7 +178,7 @@ namespace System.Reflection
|
|||
int32 stackCount = Compiler.Options.AllocStackCount;
|
||||
if (mAllocStackCountOverride != 0)
|
||||
stackCount = mAllocStackCountOverride;
|
||||
obj = Internal.Dbg_ObjectAlloc(mTypeClassVData, allocSize, mInstAlign, stackCount);
|
||||
obj = Internal.Dbg_ObjectAlloc(mTypeClassVData, allocSize, mInstAlign, stackCount, 0);
|
||||
#else
|
||||
void* mem = new [Align(16)] uint8[allocSize]* (?);
|
||||
obj = Internal.UnsafeCastToObject(mem);
|
||||
|
|
|
@ -111,7 +111,7 @@ namespace System
|
|||
function void* (int size) mAlloc;
|
||||
function void (void* ptr) mFree;
|
||||
function void (Object obj) mObject_Delete;
|
||||
void* mUnused0;
|
||||
function void* (ClassVData* vdataPtr) mClassVData_GetTypeData;
|
||||
function Type (Object obj) mObject_GetType;
|
||||
function void (Object obj) mObject_GCMarkMembers;
|
||||
function Object (Object obj, int32 typeId) mObject_DynamicCastToTypeId;
|
||||
|
@ -152,6 +152,16 @@ namespace System
|
|||
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)
|
||||
{
|
||||
#if BF_DBG_RUNTIME
|
||||
|
@ -259,6 +269,7 @@ namespace System
|
|||
mAlloc = => Alloc;
|
||||
mFree = => Free;
|
||||
mObject_Delete = => Object_Delete;
|
||||
mClassVData_GetTypeData = => ClassVData_GetTypeData;
|
||||
mObject_GetType = => Object_GetType;
|
||||
mObject_GCMarkMembers = => Object_GCMarkMembers;
|
||||
mObject_DynamicCastToTypeId = => Object_DynamicCastToTypeId;
|
||||
|
|
|
@ -1660,7 +1660,7 @@ namespace System.Reflection
|
|||
int32 stackCount = Compiler.Options.AllocStackCount;
|
||||
if (mAllocStackCountOverride != 0)
|
||||
stackCount = mAllocStackCountOverride;
|
||||
obj = Internal.Dbg_ObjectAlloc([Friend]mTypeClassVData, arraySize, [Friend]mInstAlign, stackCount);
|
||||
obj = Internal.Dbg_ObjectAlloc([Friend]mTypeClassVData, arraySize, [Friend]mInstAlign, stackCount, 0);
|
||||
#else
|
||||
void* mem = new [Align(16)] uint8[arraySize]* (?);
|
||||
obj = Internal.UnsafeCastToObject(mem);
|
||||
|
@ -1720,6 +1720,7 @@ namespace System.Reflection
|
|||
|
||||
Static = 0x200000,
|
||||
Abstract = 0x400000,
|
||||
HasAppendWantMark = 0x800000,
|
||||
}
|
||||
|
||||
public enum FieldFlags : uint16
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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));
|
||||
}
|
|
@ -1232,6 +1232,7 @@ void BfContext::RebuildType(BfType* type, bool deleteOnDemandTypes, bool rebuild
|
|||
typeInst->mHasPackingHoles = false;
|
||||
typeInst->mWantsGCMarking = false;
|
||||
typeInst->mHasDeclError = false;
|
||||
typeInst->mHasAppendWantMark = false;
|
||||
delete typeInst->mTypeInfoEx;
|
||||
typeInst->mTypeInfoEx = NULL;
|
||||
|
||||
|
|
|
@ -2067,6 +2067,15 @@ void BfDefBuilder::FinishTypeDef(bool wantsToString)
|
|||
BfMethodDef* strictEqualsMethod = NULL;
|
||||
|
||||
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++)
|
||||
{
|
||||
auto method = mCurTypeDef->mMethods[methodIdx];
|
||||
|
@ -2080,6 +2089,9 @@ void BfDefBuilder::FinishTypeDef(bool wantsToString)
|
|||
|
||||
if (method->mMethodType == BfMethodType_Ctor)
|
||||
{
|
||||
if (method->HasAppend())
|
||||
needsDtor = true;
|
||||
|
||||
if (method->mIsStatic)
|
||||
{
|
||||
if ((staticCtor != NULL) && (staticCtor->mMethodDeclaration != NULL))
|
||||
|
@ -2239,15 +2251,7 @@ void BfDefBuilder::FinishTypeDef(bool wantsToString)
|
|||
if ((method->mImportKind == BfImportKind_Import_Dynamic) || (method->mImportKind == BfImportKind_Import_Unknown))
|
||||
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)
|
||||
{
|
||||
if (field->mIsStatic)
|
||||
|
|
|
@ -7492,7 +7492,7 @@ void BfExprEvaluator::PushThis(BfAstNode* targetSrc, BfTypedValue argVal, BfMeth
|
|||
else
|
||||
allowThisSplatting = methodInstance->AllowsSplatting(-1);
|
||||
|
||||
if ((!allowThisSplatting) || (methodDef->mIsMutating))
|
||||
if ((!allowThisSplatting) || (methodDef->mIsMutating) || (methodInstance->mCallingConvention == BfCallingConvention_Cdecl))
|
||||
{
|
||||
argVal = mModule->MakeAddressable(argVal);
|
||||
irArgs.push_back(argVal.mValue);
|
||||
|
@ -16569,7 +16569,8 @@ void BfExprEvaluator::CreateObject(BfObjectCreateExpression* objCreateExpr, BfAs
|
|||
int allocAlign = resolvedTypeRef->mAlign;
|
||||
if (typeInstance != NULL)
|
||||
allocAlign = typeInstance->mInstAlign;
|
||||
int appendAllocAlign = 0;
|
||||
int appendAllocAlign = 0;
|
||||
BfAllocFlags allocFlags = BfAllocFlags_None;
|
||||
|
||||
if ((bindResult.mMethodInstance != NULL) && (bindResult.mMethodInstance->mMethodDef->HasAppend()))
|
||||
{
|
||||
|
@ -16605,6 +16606,9 @@ void BfExprEvaluator::CreateObject(BfObjectCreateExpression* objCreateExpr, BfAs
|
|||
appendSizeValue = appendSizeTypedValue.mValue;
|
||||
allocAlign = BF_MAX(allocAlign, calcAppendMethodModule.mMethodInstance->mAppendAllocAlign);
|
||||
appendAllocAlign = calcAppendMethodModule.mMethodInstance->mAppendAllocAlign;
|
||||
|
||||
if (calcAppendMethodModule.mMethodInstance->mHasAppendWantMark)
|
||||
allocFlags = (BfAllocFlags)(allocFlags | BfAllocFlags_HasAppendWantMark);
|
||||
}
|
||||
|
||||
if (appendAllocAlign != 0)
|
||||
|
@ -16616,6 +16620,12 @@ void BfExprEvaluator::CreateObject(BfObjectCreateExpression* objCreateExpr, BfAs
|
|||
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
|
||||
|
@ -16635,7 +16645,7 @@ void BfExprEvaluator::CreateObject(BfObjectCreateExpression* objCreateExpr, BfAs
|
|||
}
|
||||
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))
|
||||
{
|
||||
|
@ -16710,14 +16720,21 @@ void BfExprEvaluator::CreateObject(BfObjectCreateExpression* objCreateExpr, BfAs
|
|||
{
|
||||
auto impMethodInstance = (BfMethodInstance*)vtableEntry.mImplementingMethod;
|
||||
bool needsCall = false;
|
||||
if (impMethodInstance != NULL)
|
||||
{
|
||||
needsCall = impMethodInstance->mMethodDef->mBody != NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
if (allocFlags & BfAllocFlags_HasAppendWantMark)
|
||||
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)
|
||||
|
|
|
@ -475,6 +475,7 @@ public:
|
|||
BfTypedValue mConstAccum;
|
||||
bool mFailed;
|
||||
bool mIsFirstConstPass;
|
||||
bool mHasAppendWantMark;
|
||||
int mCurAppendAlign;
|
||||
|
||||
public:
|
||||
|
@ -482,6 +483,7 @@ public:
|
|||
{
|
||||
mFailed = false;
|
||||
mIsFirstConstPass = false;
|
||||
mHasAppendWantMark = false;
|
||||
mCurAppendAlign = 1;
|
||||
}
|
||||
|
||||
|
@ -654,6 +656,9 @@ public:
|
|||
return;
|
||||
}
|
||||
|
||||
if (origResolvedTypeRef->WantsGCMarking())
|
||||
mHasAppendWantMark = true;
|
||||
|
||||
bool isGenericParam = origResolvedTypeRef->IsGenericParam();
|
||||
auto resolvedTypeRef = origResolvedTypeRef;
|
||||
auto resultType = resolvedTypeRef;
|
||||
|
@ -6272,6 +6277,8 @@ BfIRValue BfModule::GetTypeTypeData(BfType* type, BfCreateTypeDataContext& ctx,
|
|||
typeFlags |= BfTypeFlags_Static;
|
||||
if ((typeInstance != NULL) && (typeInstance->mTypeDef->mIsAbstract))
|
||||
typeFlags |= BfTypeFlags_Abstract;
|
||||
if ((typeInstance != NULL) && (typeInstance->mHasAppendWantMark))
|
||||
typeFlags |= BfTypeFlags_HasAppendWantMark;
|
||||
|
||||
return typeTypeData;
|
||||
}
|
||||
|
@ -9534,7 +9541,7 @@ BfTypedValue BfModule::GetOrCreateVarAddr(BfExpression* expr)
|
|||
}
|
||||
|
||||
// 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();
|
||||
if (zeroMemory)
|
||||
|
@ -9581,6 +9588,8 @@ void BfModule::InitTypeInst(BfTypedValue typedValue, BfScopeData* scopeData, boo
|
|||
SizedArray<BfIRValue, 4> llvmArgs;
|
||||
llvmArgs.push_back(objectPtr);
|
||||
llvmArgs.push_back(vDataRef);
|
||||
llvmArgs.push_back(sizeValue);
|
||||
llvmArgs.push_back(mBfIRBuilder->CreateConst(BfTypeCode_Int8, allocFlags));
|
||||
|
||||
auto objectStackInitMethod = GetInternalMethod("Dbg_ObjectStackInit");
|
||||
if (objectStackInitMethod)
|
||||
|
@ -10213,7 +10222,7 @@ BfIRValue BfModule::AllocFromType(BfType* type, const BfAllocTarget& allocTarget
|
|||
doCondAlloca = !wasDynAlloc && isDynAlloc && mCurMethodState->mInConditionalBlock;
|
||||
AddStackAlloc(typedVal, arraySize, NULL, scopeData, doCondAlloca, true);
|
||||
}
|
||||
InitTypeInst(typedVal, scopeData, zeroMemory, sizeValue);
|
||||
InitTypeInst(typedVal, scopeData, zeroMemory, sizeValue, allocFlags);
|
||||
|
||||
return typedVal.mValue;
|
||||
}
|
||||
|
@ -10443,7 +10452,8 @@ BfIRValue BfModule::AllocFromType(BfType* type, const BfAllocTarget& allocTarget
|
|||
llvmArgs.push_back(sizeValue);
|
||||
llvmArgs.push_back(GetConstValue(typeInstance->mAlign));
|
||||
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);
|
||||
result = mBfIRBuilder->CreateBitCast(objectVal, mBfIRBuilder->MapType(typeInstance));
|
||||
}
|
||||
|
@ -10647,6 +10657,9 @@ BfIRValue BfModule::AppendAllocFromType(BfType* type, BfIRValue appendSizeValue,
|
|||
BfIRType toType;
|
||||
if (typeInst != NULL)
|
||||
{
|
||||
mBfIRBuilder->PopulateType(typeInst);
|
||||
if (typeInst->WantsGCMarking())
|
||||
mCurTypeInstance->mHasAppendWantMark = true;
|
||||
EmitAppendAlign(typeInst->mInstAlign, typeInst->mInstSize);
|
||||
sizeValue = GetConstValue(typeInst->mInstSize);
|
||||
toType = mBfIRBuilder->MapTypeInstPtr(typeInst);
|
||||
|
@ -10665,6 +10678,35 @@ BfIRValue BfModule::AppendAllocFromType(BfType* type, BfIRValue appendSizeValue,
|
|||
|
||||
retTypeInstance = typeInst;
|
||||
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()))
|
||||
|
@ -15871,7 +15913,7 @@ BfTypedValue BfModule::GetThis(bool markUsing)
|
|||
auto curMethodOwner = mCurMethodInstance->mMethodInstanceGroup->mOwner;
|
||||
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);
|
||||
}
|
||||
|
@ -17411,12 +17453,15 @@ BfTypedValue BfModule::TryConstCalcAppend(BfMethodInstance* methodInst, SizedArr
|
|||
appendAllocVisitor.mFailed = true;
|
||||
if (!appendAllocVisitor.mFailed)
|
||||
constValue = appendAllocVisitor.mConstAccum;
|
||||
if (appendAllocVisitor.mHasAppendWantMark)
|
||||
methodInst->mHasAppendWantMark = true;
|
||||
|
||||
if (isFirstRun)
|
||||
{
|
||||
mCurMethodInstance->mEndingAppendAllocAlign = appendAllocVisitor.mCurAppendAlign;
|
||||
if (mCurMethodInstance->mAppendAllocAlign <= 0)
|
||||
mCurMethodInstance->mAppendAllocAlign = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (isFirstRun)
|
||||
{
|
||||
|
@ -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)
|
||||
|
@ -20534,6 +20592,19 @@ void BfModule::EmitGCMarkMembers()
|
|||
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()
|
||||
|
@ -21452,7 +21523,8 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup,
|
|||
else
|
||||
{
|
||||
bool wantPtr = (thisType->IsComposite()) && (!paramVar->mIsLowered);
|
||||
if ((thisType->IsTypedPrimitive()) && (methodDef->HasNoThisSplat()))
|
||||
if ((thisType->IsTypedPrimitive()) &&
|
||||
((methodDef->HasNoThisSplat()) || (methodInstance->mCallingConvention == BfCallingConvention_Cdecl)))
|
||||
wantPtr = true;
|
||||
|
||||
if (wantPtr)
|
||||
|
@ -21582,7 +21654,8 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup,
|
|||
{
|
||||
diType = mBfIRBuilder->DbgGetType(paramVar->mResolvedType);
|
||||
bool wantRef = paramVar->mResolvedType->IsComposite();
|
||||
if ((paramVar->mResolvedType->IsTypedPrimitive()) && (methodDef->HasNoThisSplat()))
|
||||
if ((paramVar->mResolvedType->IsTypedPrimitive()) &&
|
||||
((methodDef->HasNoThisSplat()) || (methodInstance->mCallingConvention == BfCallingConvention_Cdecl)))
|
||||
wantRef = true;
|
||||
|
||||
if (wantRef)
|
||||
|
@ -23897,6 +23970,12 @@ void BfModule::GetMethodCustomAttributes(BfMethodInstance* methodInstance)
|
|||
}
|
||||
|
||||
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)
|
||||
{
|
||||
auto linkNameAttr = customAttributes->Get(mCompiler->mCallingConventionAttributeTypeDef);
|
||||
|
|
|
@ -128,10 +128,11 @@ enum BfCastResultFlags : int8
|
|||
enum BfAllocFlags : int8
|
||||
{
|
||||
BfAllocFlags_None = 0,
|
||||
BfAllocFlags_RawArray = 1,
|
||||
BfAllocFlags_ZeroMemory = 2,
|
||||
BfAllocFlags_NoDtorCall = 4,
|
||||
BfAllocFlags_NoDefaultToMalloc = 8
|
||||
BfAllocFlags_HasAppendWantMark = 1,
|
||||
BfAllocFlags_RawArray = 2,
|
||||
BfAllocFlags_ZeroMemory = 4,
|
||||
BfAllocFlags_NoDtorCall = 8,
|
||||
BfAllocFlags_NoDefaultToMalloc = 0x10,
|
||||
};
|
||||
|
||||
enum BfProtectionCheckFlags : int8
|
||||
|
@ -1736,7 +1737,7 @@ public:
|
|||
void CleanupFileInstances();
|
||||
void AssertErrorState();
|
||||
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();
|
||||
BfIRValue AllocBytes(BfAstNode* refNode, const BfAllocTarget& allocTarget, BfType* type, BfIRValue sizeValue, BfIRValue alignValue, BfAllocFlags allocFlags/*bool zeroMemory, bool defaultToMalloc*/);
|
||||
BfIRValue GetMarkFuncPtr(BfType* type);
|
||||
|
|
|
@ -1381,11 +1381,6 @@ int BfMethodInstance::DbgGetVirtualMethodNum()
|
|||
|
||||
void BfMethodInstance::GetIRFunctionInfo(BfModule* module, BfIRType& returnType, SizedArrayImpl<BfIRType>& paramTypes, bool forceStatic)
|
||||
{
|
||||
if (mMethodDef->mName == "Test4")
|
||||
{
|
||||
NOP;
|
||||
}
|
||||
|
||||
BfModule* resolveModule = module->mContext->mUnreifiedModule;
|
||||
|
||||
resolveModule->PopulateType(mReturnType);
|
||||
|
@ -1458,7 +1453,11 @@ void BfMethodInstance::GetIRFunctionInfo(BfModule* module, BfIRType& returnType,
|
|||
bool doSplat = false;
|
||||
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();
|
||||
}
|
||||
|
@ -2468,6 +2467,22 @@ bool BfTypeInstance::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)
|
||||
{
|
||||
if (mGenericTypeInfo != NULL)
|
||||
|
|
|
@ -908,6 +908,7 @@ public:
|
|||
bool mInCEMachine:1;
|
||||
bool mCeCancelled:1;
|
||||
bool mIsDisposed:1;
|
||||
bool mHasAppendWantMark:1;
|
||||
BfMethodChainType mChainType;
|
||||
BfComptimeFlags mComptimeFlags;
|
||||
BfCallingConvention mCallingConvention;
|
||||
|
@ -951,6 +952,7 @@ public:
|
|||
mInCEMachine = false;
|
||||
mCeCancelled = false;
|
||||
mIsDisposed = false;
|
||||
mHasAppendWantMark = false;
|
||||
mChainType = BfMethodChainType_None;
|
||||
mComptimeFlags = BfComptimeFlag_None;
|
||||
mCallingConvention = BfCallingConvention_Unspecified;
|
||||
|
@ -2064,6 +2066,7 @@ public:
|
|||
bool mHasPackingHoles;
|
||||
bool mWantsGCMarking;
|
||||
bool mHasDeclError;
|
||||
bool mHasAppendWantMark;
|
||||
|
||||
public:
|
||||
BfTypeInstance()
|
||||
|
@ -2116,6 +2119,7 @@ public:
|
|||
mWantsGCMarking = false;
|
||||
mHasParameterizedBase = false;
|
||||
mHasDeclError = false;
|
||||
mHasAppendWantMark = false;
|
||||
mMergedFieldDataCount = 0;
|
||||
mConstHolder = NULL;
|
||||
}
|
||||
|
@ -2213,6 +2217,8 @@ public:
|
|||
bool DefineStateAllowsStaticMethods() { return mDefineState >= BfTypeDefineState_HasInterfaces_Direct; }
|
||||
bool IsAnonymous();
|
||||
bool IsAnonymousInitializerType();
|
||||
bool HasAppendCtor();
|
||||
bool BaseHasAppendCtor();
|
||||
|
||||
virtual void ReportMemory(MemReporter* memReporter) override;
|
||||
};
|
||||
|
|
|
@ -239,6 +239,7 @@ enum BfTypeFlags
|
|||
|
||||
BfTypeFlags_Static = 0x200000,
|
||||
BfTypeFlags_Abstract = 0x400000,
|
||||
BfTypeFlags_HasAppendWantMark = 0x800000,
|
||||
};
|
||||
|
||||
enum BfMethodFlags
|
||||
|
|
|
@ -8513,7 +8513,7 @@ String WinDebugger::DbgTypedValueToString(const DbgTypedValue& origTypedValue, c
|
|||
{
|
||||
addr_target objectSize = ReadMemory<addr_target>(ptrVal + sizeof(addr_target));
|
||||
addr_target largeAllocInfo = ReadMemory<addr_target>(ptrVal + objectSize);
|
||||
stackTraceLen = largeAllocInfo & 0xFFFF;
|
||||
stackTraceLen = (largeAllocInfo >> 8) & 0xFFFF;
|
||||
stackTraceAddr = ptrVal + objectSize + sizeof(addr_target);
|
||||
}
|
||||
else if ((bfObjectFlags & BfObjectFlag_AllocInfo_Short) != 0)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue