예제 #1
0
 /// <summary>
 /// Creates a new garbage collector
 /// </summary>
 /// <param name="virtualMachine">The virtual machine</param>
 public GarbageCollector(VirtualMachine virtualMachine)
 {
     this.virtualMachine  = virtualMachine;
     this.youngGeneration = new CollectorGeneration(
         virtualMachine.MemoryManager,
         virtualMachine.ManagedObjectReferences,
         4 * 1024 * 1024);
 }
예제 #2
0
        /// <summary>
        /// Marks the given value
        /// </summary>
        /// <param name="generation">The generation</param>
        /// <param name="value">The value</param>
        /// <param name="type">The type of the value</param>
        private void MarkValue(CollectorGeneration generation, long value, BaseType type)
        {
            if (type.IsReference)
            {
                //Don't mark nulls
                if (value == 0)
                {
                    return;
                }

                this.MarkObject(generation, this.GetObjectReference(new IntPtr(value)));
            }
        }
예제 #3
0
        /// <summary>
        /// Sweeps the objects in the given generation
        /// </summary>
        /// <param name="generation">The generation</param>
        private void SweepObjects(CollectorGeneration generation)
        {
            generation.Heap.VisitObjects(objectReference =>
            {
                if (objectReference.IsMarked)
                {
                    objectReference.Unmark();
                    objectReference.IncreaseSurvivalCount();
                }
                else
                {
                    if (this.virtualMachine.Config.EnableDebug && this.virtualMachine.Config.PrintDeallocation)
                    {
                        RuntimeInterface.DebugLog($"Deleted object {objectReference}");
                    }

                    this.DeleteObject(objectReference);
                }
            });
        }
예제 #4
0
        /// <summary>
        /// Marks all the objects starting at the given frame
        /// </summary>
        /// <param name="generation">The generation</param>
        /// <param name="stackFrame">The stack frame</param>
        private void MarkAllObjects(CollectorGeneration generation, StackFrame stackFrame)
        {
            var stalkWalker = new StackWalker(this.virtualMachine.CallStack);

            stalkWalker.VisitObjectReferences(
                stackFrame,
                frameEntry =>
            {
                var objectPointer = new IntPtr(frameEntry.Value);
                this.MarkObject(generation, this.GetObjectReference(objectPointer));
            },
                frame =>
            {
                if (this.virtualMachine.Config.EnableDebug && this.virtualMachine.Config.PrintStackFrameWhenGC)
                {
                    RuntimeInterface.DebugLog($"{frame.Function.Definition.Name} ({frame.InstructionIndex})");
                    RuntimeInterface.PrintStackFrame(frame, false);
                }
            });
        }
예제 #5
0
        /// <summary>
        /// Allocates an object of the given size
        /// </summary>
        /// <param name="generation">The generation to allocate in</param>
        /// <param name="type">The type of the object</param>
        /// <param name="size">The size of the object</param>
        private IntPtr AllocateObject(CollectorGeneration generation, BaseType type, int size)
        {
            var fullSize      = Constants.ObjectHeaderSize + size;
            var objectPointer = generation.Allocate(fullSize);

            NativeHelpers.SetBlock(objectPointer, fullSize, 0);

            //Set the header
            var typeObjectRef = this.virtualMachine.GetManagedReference(type);

            NativeHelpers.SetInt(objectPointer, 0, typeObjectRef);                         //Type
            NativeHelpers.SetByte(objectPointer, Constants.ManagedObjectReferenceSize, 0); //GC info

            var dataPointer = objectPointer + Constants.ObjectHeaderSize;

            if (this.virtualMachine.Config.LogAllocation)
            {
                this.Allocations.Add(dataPointer);
            }

            //The returned ptr is to the data
            return(dataPointer);
        }
예제 #6
0
        /// <summary>
        /// Marks the given object
        /// </summary>
        /// <param name="generation">The generation</param>
        /// <param name="objectReference">A reference to the object</param>
        private void MarkObject(CollectorGeneration generation, ObjectReference objectReference)
        {
            if (!objectReference.IsMarked)
            {
                objectReference.Mark();

                if (objectReference.Type.IsArray)
                {
                    //Mark ref elements
                    var arrayType = (ArrayType)objectReference.Type;

                    if (arrayType.ElementType.IsReference)
                    {
                        var arrayReference = new ArrayReference(objectReference);

                        for (int i = 0; i < arrayReference.Length; i++)
                        {
                            var elementPtr = arrayReference.GetElement(i);
                            this.MarkValue(generation, NativeHelpers.ReadLong(elementPtr), arrayType.ElementType);
                        }
                    }
                }
                else if (objectReference.Type.IsClass)
                {
                    //Mark ref fields
                    var classType = (ClassType)objectReference.Type;
                    foreach (var field in classType.Metadata.Fields)
                    {
                        if (field.Type.IsReference)
                        {
                            var fieldValue = NativeHelpers.ReadLong(objectReference.DataPointer + field.LayoutOffset);
                            this.MarkValue(generation, fieldValue, field.Type);
                        }
                    }
                }
            }
        }