public static void *NewObj(FlingOops.Type theType) { if (!Enabled) { BasicConsole.SetTextColour(BasicConsole.warning_colour); BasicConsole.WriteLine("Warning! GC returning null pointer because GC not enabled."); BasicConsole.DelayOutput(10); BasicConsole.SetTextColour(BasicConsole.default_colour); return(null); } //try //{ InsideGC = true; //Alloc space for GC header that prefixes object data //Alloc space for new object uint totalSize = theType.Size; totalSize += (uint)sizeof(GCHeader); GCHeader *newObjPtr = (GCHeader *)Heap.AllocZeroed(totalSize, "GC : NewObject"); if ((UInt32)newObjPtr == 0) { InsideGC = false; BasicConsole.SetTextColour(BasicConsole.error_colour); BasicConsole.WriteLine("Error! GC can't create a new object because the heap returned a null pointer."); BasicConsole.DelayOutput(10); BasicConsole.SetTextColour(BasicConsole.default_colour); return(null); } NumObjs++; //Initialise the GCHeader SetSignature(newObjPtr); newObjPtr->RefCount = 1; //Initialise the object _Type field FlingOops.ObjectWithType newObj = (FlingOops.ObjectWithType)Utilities.ObjectUtilities.GetObject(newObjPtr + 1); newObj._Type = theType; //Move past GCHeader byte *newObjBytePtr = (byte *)(newObjPtr + 1); InsideGC = false; return(newObjBytePtr); //} //finally //{ //} }
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("Cleaning up object..."); #endif FlingOops.Object obj = (FlingOops.Object)Utilities.ObjectUtilities.GetObject(objPtr); if (obj is FlingOops.Array) { //Decrement ref count of elements FlingOops.Array arr = (FlingOops.Array)obj; if (!arr.elemType.IsValueType) { FlingOops.Object[] objArr = (FlingOops.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) { FlingOops.Type fieldType = (FlingOops.Type)Utilities.ObjectUtilities.GetObject(FieldInfoPtr->FieldType); if (!fieldType.IsValueType && !fieldType.IsPointer) { byte * fieldPtr = objPtr + FieldInfoPtr->Offset; FlingOops.Object theFieldObj = (FlingOops.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; } } #if GC_TRACE BasicConsole.WriteLine("Adding object to clean up..."); #endif AddObjectToCleanup(gcHeaderPtr, objPtr); #if GC_TRACE BasicConsole.WriteLine("Completed decrement ref count processing."); #endif } } }
public static void *NewArr(int length, FlingOops.Type elemType) { if (!Enabled) { BasicConsole.SetTextColour(BasicConsole.warning_colour); BasicConsole.WriteLine("Warning! GC returning null pointer because GC not enabled."); BasicConsole.DelayOutput(10); BasicConsole.SetTextColour(BasicConsole.default_colour); return(null); } //try { if (length < 0) { BasicConsole.WriteLine("length < 0. Overflow exception."); return(null); //ExceptionMethods.Throw_OverflowException(); } InsideGC = true; //Alloc space for GC header that prefixes object data //Alloc space for new array object //Alloc space for new array elems uint totalSize = ((FlingOops.Type) typeof(FlingOops.Array)).Size; if (elemType.IsValueType) { totalSize += elemType.Size * (uint)length; } else { totalSize += elemType.StackSize * (uint)length; } totalSize += (uint)sizeof(GCHeader); GCHeader *newObjPtr = (GCHeader *)Heap.AllocZeroed(totalSize, "GC : NewArray"); if ((UInt32)newObjPtr == 0) { InsideGC = false; BasicConsole.SetTextColour(BasicConsole.error_colour); BasicConsole.WriteLine("Error! GC can't create a new array because the heap returned a null pointer."); BasicConsole.DelayOutput(10); BasicConsole.SetTextColour(BasicConsole.default_colour); return(null); } NumObjs++; //Initialise the GCHeader SetSignature(newObjPtr); newObjPtr->RefCount = 1; FlingOops.Array newArr = (FlingOops.Array)Utilities.ObjectUtilities.GetObject(newObjPtr + 1); newArr._Type = (FlingOops.Type) typeof(FlingOops.Array); newArr.length = length; newArr.elemType = elemType; //Move past GCHeader byte *newObjBytePtr = (byte *)(newObjPtr + 1); InsideGC = false; return(newObjBytePtr); } //finally { } }