public static void _DecrementRefCount(byte *objPtr) { if ((uint)objPtr < (uint)sizeof(GCHeader)) { BasicConsole.SetTextColour(BasicConsole.error_colour); BasicConsole.WriteLine("Error! GC can't decrement ref count of an object in low memory."); BasicConsole.DelayOutput(5); BasicConsole.SetTextColour(BasicConsole.default_colour); } GCHeader *gcHeaderPtr = (GCHeader *)(objPtr - sizeof(GCHeader)); if (CheckSignature(gcHeaderPtr)) { gcHeaderPtr->RefCount--; //If the ref count goes below 0 then there was a circular reference somewhere. // In actuality we don't care we can just only do cleanup when the ref count is // exactly 0. if (gcHeaderPtr->RefCount == 0) { #if GC_TRACE BasicConsole.WriteLine("Cleaned up object."); #endif Testing2.Object obj = (Testing2.Object)Utilities.ObjectUtilities.GetObject(objPtr); if (obj is Testing2.Array) { //Decrement ref count of elements Testing2.Array arr = (Testing2.Array)obj; if (!arr.elemType.IsValueType) { Testing2.Object[] objArr = (Testing2.Object[])Utilities.ObjectUtilities.GetObject(objPtr); for (int i = 0; i < arr.length; i++) { DecrementRefCount(objArr[i], true); } } } //Cleanup fields FieldInfo *FieldInfoPtr = obj._Type.FieldTablePtr; //Loop through all fields. The if-block at the end handles moving to parent // fields. while (FieldInfoPtr != null) { if (FieldInfoPtr->Size > 0) { Testing2.Type fieldType = (Testing2.Type)Utilities.ObjectUtilities.GetObject(FieldInfoPtr->FieldType); if (!fieldType.IsValueType && !fieldType.IsPointer) { byte * fieldPtr = objPtr + FieldInfoPtr->Offset; Testing2.Object theFieldObj = (Testing2.Object)Utilities.ObjectUtilities.GetObject(fieldPtr); DecrementRefCount(theFieldObj, true); #if GC_TRACE BasicConsole.WriteLine("Cleaned up field."); #endif } FieldInfoPtr++; } if (FieldInfoPtr->Size == 0) { FieldInfoPtr = (FieldInfo *)FieldInfoPtr->FieldType; } } AddObjectToCleanup(gcHeaderPtr, objPtr); } } }
public static void _DecrementRefCount(byte* objPtr) { if ((uint)objPtr < (uint)sizeof(GCHeader)) { BasicConsole.SetTextColour(BasicConsole.error_colour); BasicConsole.WriteLine("Error! GC can't decrement ref count of an object in low memory."); uint* basePtr = (uint*)ExceptionMethods.BasePointer; // Go up the linked-list of stack frames to (hopefully) the outermost caller basePtr = (uint*)*(basePtr); // DecrementRefCount(x, y) basePtr = (uint*)*(basePtr); // DecrementRefCount(x) uint retAddr = *(basePtr + 1); uint objAddr = (uint)objPtr; String msgStr = "Caller: 0x , Object: 0x "; // Object: 37 // Caller: 17 ExceptionMethods.FillString(retAddr, 17, msgStr); ExceptionMethods.FillString(objAddr, 37, msgStr); BasicConsole.WriteLine(msgStr); BasicConsole.DelayOutput(5); BasicConsole.SetTextColour(BasicConsole.default_colour); } GCHeader* gcHeaderPtr = (GCHeader*)(objPtr - sizeof(GCHeader)); if (CheckSignature(gcHeaderPtr)) { gcHeaderPtr->RefCount--; //If the ref count goes below 0 then there was a circular reference somewhere. // In actuality we don't care we can just only do cleanup when the ref count is // exactly 0. if (gcHeaderPtr->RefCount == 0) { #if GC_TRACE if (OutputTrace) { BasicConsole.WriteLine("Cleaned up object."); } #endif FOS_System.Object obj = (FOS_System.Object)Utilities.ObjectUtilities.GetObject(objPtr); if (obj is FOS_System.Array) { //Decrement ref count of elements FOS_System.Array arr = (FOS_System.Array)obj; if (!arr.elemType.IsValueType) { FOS_System.Object[] objArr = (FOS_System.Object[])Utilities.ObjectUtilities.GetObject(objPtr); for (int i = 0; i < arr.length; i++) { DecrementRefCount(objArr[i], true); } } } //Cleanup fields FieldInfo* FieldInfoPtr = obj._Type.FieldTablePtr; //Loop through all fields. The if-block at the end handles moving to parent // fields. while (FieldInfoPtr != null) { if (FieldInfoPtr->Size > 0) { FOS_System.Type fieldType = (FOS_System.Type)Utilities.ObjectUtilities.GetObject(FieldInfoPtr->FieldType); if (!fieldType.IsValueType && !fieldType.IsPointer) { byte* fieldPtr = objPtr + FieldInfoPtr->Offset; FOS_System.Object theFieldObj = (FOS_System.Object)Utilities.ObjectUtilities.GetObject(fieldPtr); DecrementRefCount(theFieldObj, true); #if GC_TRACE if (OutputTrace) { BasicConsole.WriteLine("Cleaned up field."); } #endif } FieldInfoPtr++; } if (FieldInfoPtr->Size == 0) { FieldInfoPtr = (FieldInfo*)FieldInfoPtr->FieldType; } } AddObjectToCleanup(gcHeaderPtr, objPtr); } } }