mirror of
https://github.com/beefytech/Beef.git
synced 2025-06-08 11:38:21 +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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue