/// <summary> /// Marks all objects referenced /// </summary> /// <param name="obj"></param> /// <param name="type"></param> public static void SweepTypedObject(uint *obj, uint type) { if (obj == null) { return; } uint fields = VTablesImpl.GetGCFieldCount(type); var offsets = VTablesImpl.GetGCFieldOffsets(type); var types = VTablesImpl.GetGCFieldTypes(type); for (int i = 0; i < fields; i++) { if (!VTablesImpl.IsValueType(types[i])) { var location = (uint *)((byte *)obj + offsets[i]) + 1; // +1 since we are only using 32bits from the 64bit if (*location != 0) // Check if its null { location = *(uint **)location; if (RAT.GetPageType(location) == RAT.PageType.HeapSmall) { MarkAndSweepObject(location); } } } else if (VTablesImpl.IsStruct(types[i])) { var obj1 = (uint *)((byte *)obj + offsets[i]); SweepTypedObject(obj1, types[i]); } } }
public static unsafe Array AllocateNewArray(int *aTypeHandle, int aLength, uint aGCFlags) { if (aGCFlags != 0 && aGCFlags != 16) // 16 means that zeroing is optional { var debugger = new Debugger("Plug", "GC"); debugger.Send($"-- AllocateNewArray -- Invalid aGCFlags: {aGCFlags}"); Debugger.DoBochsBreak(); throw new NotImplementedException(); } var aSize = (int)VTablesImpl.GetSize((uint)*aTypeHandle); return(CreateNewArray(aSize, aLength)); }
private void TestVTablesImpl() { object obj = new object(); Assert.AreEqual(GCImplementation.GetType(obj), ((CosmosRuntimeType)obj.GetType()).mTypeId, "Both methods to get type id return the same value for object"); string s = "a"; Assert.AreEqual(GCImplementation.GetType(s), ((CosmosRuntimeType)s.GetType()).mTypeId, "Both methods to get type id return the same value for string"); Assert.AreEqual(GCImplementation.GetType(s), ((CosmosRuntimeType)typeof(string)).mTypeId, "Methods and constato get type id return the same value for string"); List <int> x = new List <int>(); Assert.AreEqual(GCImplementation.GetType(x), ((CosmosRuntimeType)typeof(List <int>)).mTypeId, "Methods and constant get type id return the same value for List<int>"); TestType tObj = new TestType(); Assert.AreEqual(GCImplementation.GetType(tObj), ((CosmosRuntimeType)typeof(TestType)).mTypeId, "Methods and constant get type id return the same value for TestType"); Assert.AreEqual(4, VTablesImpl.GetGCFieldCount(GCImplementation.GetType(tObj)), "TestType has 4 fields tracked by GC"); var types = VTablesImpl.GetGCFieldTypes(GCImplementation.GetType(tObj)); Assert.AreEqual(4, types.Length, "GetGCFieldTypes returns correct number of values"); Assert.AreEqual(((CosmosRuntimeType)typeof(object)).mTypeId, types[0], "GetGCFieldTypes returns object at offset 0"); Assert.AreEqual(((CosmosRuntimeType)typeof(List <int>)).mTypeId, types[1], "GetGCFieldTypes returns List<int> at offset 1"); Assert.AreEqual(((CosmosRuntimeType)typeof(string)).mTypeId, types[2], "GetGCFieldTypes returns string at offset 2"); Assert.AreEqual(((CosmosRuntimeType)typeof(object)).mTypeId, types[3], "GetGCFieldTypes returns object at offset 3"); Assert.AreEqual(4, VTablesImpl.GetGCFieldOffsets(GCImplementation.GetType(tObj)).Length, "GetGCFieldOffsets returned the correct number of values"); Assert.AreEqual(new uint[] { 12, 20, 28, 36 }, VTablesImpl.GetGCFieldOffsets(GCImplementation.GetType(tObj)), "GetGCFieldOffsets returns the correct values"); ClassWithStruct classWithStruct = new ClassWithStruct(); Assert.AreEqual(3, VTablesImpl.GetGCFieldCount(GCImplementation.GetType(classWithStruct)), "ClassWithStruct has 3 fields tracked by GC"); types = VTablesImpl.GetGCFieldTypes(GCImplementation.GetType(classWithStruct)); Assert.AreEqual(((CosmosRuntimeType)typeof(object)).mTypeId, types[0], "GetGCFieldTypes returns object at offset 0"); Assert.AreEqual(((CosmosRuntimeType)typeof(TestStruct)).mTypeId, types[1], "GetGCFieldTypes returns TestStruct at offset 1"); Assert.AreEqual(((CosmosRuntimeType)typeof(object)).mTypeId, types[2], "GetGCFieldTypes returns object at offset 2"); }
private static bool ContainsReference(uint mType) { if (!VTablesImpl.IsValueType(mType)) { return(true); } else if (VTablesImpl.IsStruct(mType)) { var fields = VTablesImpl.GetGCFieldTypes(mType); for (int i = 0; i < fields.Length; i++) { if (ContainsReference(fields[i])) { return(true); } } return(false); } else { return(false); } }
/// <summary> /// Marks a GC managed object as referenced and recursivly marks child objects as well /// </summary> /// <param name="aPtr"></param> public static void MarkAndSweepObject(void *aPtr) { var gcPointer = (ObjectGCStatus *)aPtr; if ((gcPointer[-1] & ObjectGCStatus.Hit) == ObjectGCStatus.Hit) { return; // we already hit this object } // Mark gcPointer[-1] |= ObjectGCStatus.Hit; // Sweep uint *obj = (uint *)aPtr; // Check what we are dealing with if (*(obj + 1) == (uint)ObjectUtils.InstanceTypeEnum.NormalObject) { if (_StringType == 0) { _StringType = GetStringTypeID(); } var type = *obj; // Deal with strings first if (type == _StringType) { return; // we are done since they dont hold any reference to fields } SweepTypedObject(obj, type); } else if (*(obj + 1) == (uint)ObjectUtils.InstanceTypeEnum.Array) { var elementType = *obj; var length = *(obj + 2); var size = *(obj + 3); if (VTablesImpl.IsValueType(elementType)) { if (VTablesImpl.IsStruct(elementType)) { for (int i = 0; i < length; i++) { var location = (uint *)((byte *)obj + size * i) + 4; SweepTypedObject(location, elementType); } } } else { for (int i = 0; i < length; i++) { var location = (uint *)((byte *)obj + size * i) + 4 + 1; if (*location != 0) { location = *(uint **)location; if (RAT.GetPageType(location) == RAT.PageType.HeapSmall) // so we dont try free string literals { MarkAndSweepObject(location); } } } } } else if (*(obj + 1) == (uint)ObjectUtils.InstanceTypeEnum.BoxedValueType) { // do nothing } }