From c8898774431f58ba2e3e863e5586820563a7aff5 Mon Sep 17 00:00:00 2001 From: Brian Fiete Date: Mon, 19 May 2025 16:19:15 +0200 Subject: [PATCH] Minlib fixes --- IDE/mintest/minlib/src/System/Internal.bf | 217 +++++++++++++++++++++- IDE/mintest/minlib/src/System/Object.bf | 6 + IDE/mintest/minlib/src/System/Type.bf | 2 +- 3 files changed, 220 insertions(+), 5 deletions(-) diff --git a/IDE/mintest/minlib/src/System/Internal.bf b/IDE/mintest/minlib/src/System/Internal.bf index 22ffbb9e..6997229d 100644 --- a/IDE/mintest/minlib/src/System/Internal.bf +++ b/IDE/mintest/minlib/src/System/Internal.bf @@ -13,6 +13,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")] @@ -64,19 +91,19 @@ namespace System [CallingConvention(.Cdecl)] public static extern void Dbg_ObjectCreated(Object obj, int size, ClassVData* classVData); [CallingConvention(.Cdecl)] - public static extern void Dbg_ObjectCreatedEx(Object obj, int size, ClassVData* classVData); + public static extern void Dbg_ObjectCreatedEx(Object obj, int size, ClassVData* classVData, uint8 allocFlags); [CallingConvention(.Cdecl)] public static extern void Dbg_ObjectAllocated(Object obj, int size, ClassVData* classVData); [CallingConvention(.Cdecl)] - public static extern void Dbg_ObjectAllocatedEx(Object obj, int size, ClassVData* classVData); + public static extern void Dbg_ObjectAllocatedEx(Object obj, int size, ClassVData* classVData, uint8 allocFlags); [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)] @@ -92,6 +119,188 @@ 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, bool doChecks) + { +#if BF_ENABLE_OBJECT_DEBUG_FLAGS + void Handle(AppendAllocEntry* headAllocEntry) + { + AppendAllocEntry* checkAllocEntry = headAllocEntry; + while (checkAllocEntry != null) + { + switch (checkAllocEntry.mKind) + { + case .Object(let obj): + if (doChecks) + { +#unwarn + if (!obj.[DisableObjectAccessChecks]IsDeleted()) + { + if (obj.GetType().HasDestructor) + { + Runtime.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(); diff --git a/IDE/mintest/minlib/src/System/Object.bf b/IDE/mintest/minlib/src/System/Object.bf index 431680cf..34210c3a 100644 --- a/IDE/mintest/minlib/src/System/Object.bf +++ b/IDE/mintest/minlib/src/System/Object.bf @@ -172,6 +172,12 @@ namespace System } #endif + [NoShow] + public virtual Object DynamicCastToSignature(int32 sig) + { + return null; + } + int IHashable.GetHashCode() { return (int)Internal.UnsafeCastToPtr(this); diff --git a/IDE/mintest/minlib/src/System/Type.bf b/IDE/mintest/minlib/src/System/Type.bf index 234265dc..df5edb66 100644 --- a/IDE/mintest/minlib/src/System/Type.bf +++ b/IDE/mintest/minlib/src/System/Type.bf @@ -1266,7 +1266,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);