#if DEBUG #define GC_DEBUG #endif using System; using System.Collections.Generic; using System.Linq; using System.Runtime.InteropServices; using System.Text; namespace Indy.IL2CPU { public static class GCImplementation { public static uint AllocNewObject(uint aSize) { uint xNewObject = RuntimeEngine.Heap_AllocNewObject(aSize + 4); #if GC_DEBUG Console.Write("New Object allocated: "); WriteNumber(xNewObject + 4, false); Console.WriteLine(); #endif return xNewObject + 4; } /// /// This function gets the pointer to the memory location of where it's stored. /// /// public static unsafe void IncRefCount(uint aObject) { if (aObject == 0) { return; } uint* xTheObject = (uint*)aObject; xTheObject -= 1; if ((*xTheObject & 0x80000000) != 0) { Console.Write("StaleObject: "); WriteNumber(aObject, false); Console.WriteLine(); return; } //xTheObject -= 2; #if GC_DEBUG uint xCount = #endif *xTheObject = *xTheObject + 1; #if GC_DEBUG if (xCount == 0x80000000) { Console.WriteLine("GC: RefCount Maximum Exceeded!"); return; } Console.Write("ObjectIncRefCount, Object = "); WriteNumber(aObject, false); Console.Write(", RefCount = "); WriteNumber(xCount, false); Console.WriteLine(); #endif } /// /// This function gets the pointer to the memory location of where it's stored. /// /// public static unsafe void DecRefCount(uint aObject) { if (aObject == 0) { return; } uint* xTheObject = (uint*)aObject; xTheObject += 1; // check for staticly embedded arrays/objects. these are embedded as values in the binary target, and should // therefore not be collected. if ((*xTheObject & 0x80000000) == 0x80000000) { return; } xTheObject -= 2; uint xCount = *xTheObject; if (xCount == 0) { return; } #if GC_DEBUG if ((xCount & 0x80000000) == 0x80000000) { Console.Write("StaleObject: "); WriteNumber(aObject, false); Console.WriteLine(); return; } #endif xCount = *xTheObject = xCount - 1; if (xCount == 0) { #if !GC_DEBUG RuntimeEngine.Heap_Free(aObject - 4); #endif #if GC_DEBUG Console.Write("ObjectReclaimed, Object = "); WriteNumber(aObject, false); Console.WriteLine(); xTheObject = (uint*)(aObject - 4); *xTheObject = 0x80000000; } else { Console.Write("ObjectDecRefCount, Object = "); WriteNumber(aObject, false); Console.Write(", RefCount = "); WriteNumber(xCount, false); Console.WriteLine(); #endif } } #if GC_DEBUG private static void WriteNumber(uint aValue, bool aZeroFill) { uint xValue = aValue; byte xCurrentBits = 32; byte xCharsWritten = 0; bool xSignificantDigitWritten = aZeroFill; Console.Write("0x"); while (xCurrentBits >= 4) { xCurrentBits -= 4; byte xCurrentDigit = (byte)((xValue >> xCurrentBits) & 0xF); string xDigitString = null; switch (xCurrentDigit) { case 0: if (xSignificantDigitWritten) { xDigitString = "0"; goto default; } break; case 1: xDigitString = "1"; goto default; case 2: xDigitString = "2"; goto default; case 3: xDigitString = "3"; goto default; case 4: xDigitString = "4"; goto default; case 5: xDigitString = "5"; goto default; case 6: xDigitString = "6"; goto default; case 7: xDigitString = "7"; goto default; case 8: xDigitString = "8"; goto default; case 9: xDigitString = "9"; goto default; case 10: xDigitString = "A"; goto default; case 11: xDigitString = "B"; goto default; case 12: xDigitString = "C"; goto default; case 13: xDigitString = "D"; goto default; case 14: xDigitString = "E"; goto default; case 15: xDigitString = "F"; goto default; default: if (xDigitString == null) { Console.Write("NoDigitSet"); } xSignificantDigitWritten = true; xCharsWritten += 1; Console.Write(xDigitString); break; } } } #endif } }