Example #1
0
        public static void CollectGarbage()
        {
            GCWatch.Start();

            // 从stack出发
            foreach (var thread in ThreadManager.Threads)
            {
                // 要保证GC执行期间线程全部停止
                for (uint i = 0; i < thread.Stack.SP; ++i)
                {
                    if (thread.Stack.Slots[i].DataTag == SlotDataTag.ADDRESS)
                    {
                        MarkObject(thread.Stack.GetAddress(i));
                    }
                }
            }

            // 从类的静态区出发
            foreach (var staticClassData in StaticArea.Singleton.DataMap.Values)
            {
                uint addr = MemoryMap.MapToAbsolute(staticClassData.Offset, MemoryTag.STATIC);
                ModuleLoader.Classes.TryGetValue(addr, out VMClass vmClass);
                foreach (var staticField in vmClass.StaticFields)
                {
                    if (staticField.Type.Tag == VariableTypeTag.ADDRESS)
                    {
                        // 是地址
                        MarkObject(BitConverter.ToUInt32(staticClassData.Data, staticField.Offset));
                    }
                }
            }

            // 回收
            LinkedListNode <HeapData> cur = Heap.Singleton.Data.First;

            while (cur != null)
            {
                if ((cur.Value.GCInfo & (uint)GCTag.GCMark) == 0)
                {
                    // 不可达对象,删除
                    LinkedListNode <HeapData> tmp = cur;
                    cur = cur.Next;
                    Heap.Singleton.DataMap.Remove(tmp.Value.Offset);
                    Heap.Singleton.Data.Remove(tmp);
                    Heap.Singleton.Size -= tmp.Value.Data.Length;
                    FreedSize           += tmp.Value.Data.Length / 1024;
                }
                else
                {
                    // 清除GCMark
                    cur.Value.GCInfo = cur.Value.GCInfo & (~(uint)GCTag.GCMark);
                    cur = cur.Next;
                }
            }

            GCWatch.Stop();
            GCTotalTime += GCWatch.ElapsedMilliseconds;
            if (GCWatch.ElapsedMilliseconds > GCMaxTime)
            {
                GCMaxTime = GCWatch.ElapsedMilliseconds;
            }
            GCCount++;
        }