Example #1
0
        /// <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]);
                }
            }
        }
Example #2
0
        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));
        }
Example #3
0
        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");
        }
Example #4
0
 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);
     }
 }
Example #5
0
        /// <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
            }
        }