Ejemplo n.º 1
0
        private static void MarkObject(uint addr)
        {
            MemoryTag tag = MemoryMap.MapToOffset(addr, out addr);

            if (tag == MemoryTag.HEAP)
            {
                HeapData data = Heap.Singleton.GetData(addr);
                data.GCInfo |= (uint)GCTag.GCMark;
                uint typeInfo = data.TypeInfo;
                if ((data.GCInfo & (uint)GCTag.ArrayMark) != 0)
                {
                    // 是数组
                    if (typeInfo == (uint)VariableTypeTag.ADDRESS)
                    {
                        // 是地址数组
                        int len = BitConverter.ToInt32(data.Data, HeapData.MiscDataSize);
                        for (int i = 0; i < len; i++)
                        {
                            MarkObject(BitConverter.ToUInt32(data.Data, HeapData.ArrayOffsetMap(VariableType.AddressType.Size, i)));
                        }
                    }
                }
                else
                {
                    // 是普通对象
                    ModuleLoader.Classes.TryGetValue(typeInfo, out VMClass vmClass);
                    foreach (var field in vmClass.Fields)
                    {
                        if (field.Type.Tag == VariableTypeTag.ADDRESS)
                        {
                            // 是地址
                            MarkObject(BitConverter.ToUInt32(data.Data, field.Offset));
                        }
                    }
                }
            }
        }
Ejemplo n.º 2
0
        /// <summary>
        /// 注意要和SystemLib中的String的对象格式相同
        /// </summary>
        /// <param name="value"></param>
        /// <returns>绝对地址</returns>
        public uint AddConstantString(string value)
        {
            if (!StringPool.TryGetValue(value, out HeapData data))
            {
                // 分配byte数组
                HeapData stringData = MallocCharArray(Encoding.UTF8.GetByteCount(value));
                Encoding.UTF8.GetBytes(value, new Span <byte>(stringData.Data, HeapData.ArrayLengthSize + HeapData.MiscDataSize,
                                                              stringData.Data.Length - HeapData.ArrayLengthSize - HeapData.MiscDataSize));

                // String对象
                byte[] vs = new byte[HeapData.MiscDataSize + HeapData.StringLengthSize + HeapData.StringDataSize];
                // 头部信息可以不填,因为MethodArea是内存的边界,GC不会继续walk
                // 长度信息
                BitConverter.TryWriteBytes(new Span <byte>(vs, HeapData.MiscDataSize, HeapData.StringLengthSize), value.Length);
                // Data信息
                BitConverter.TryWriteBytes(new Span <byte>(vs, HeapData.MiscDataSize + HeapData.StringLengthSize, HeapData.StringDataSize),
                                           MemoryMap.MapToAbsolute(stringData.Offset, MemoryTag.METHOD));

                // 字符串
                data = Malloc(vs);
                StringPool.Add(value, data);
            }
            return(MemoryMap.MapToAbsolute(data.Offset, MemoryTag.METHOD));
        }
Ejemplo n.º 3
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++;
        }
Ejemplo n.º 4
0
 public static uint GetAbsoluteAddress(PreservedAddressTag tag)
 {
     return(MemoryMap.MapToAbsolute((uint)tag, MemoryTag.PRESERVED));
 }
Ejemplo n.º 5
0
        private void Execute()
        {
            Watch.Start();

            IP = 0;
            Stack.PushFrame(0, 0);    // 全局的ret ip可以随便填
            PushLocals();

            uint   addr, uValue;
            int    iValue, lhsi, rhsi, index, ip;
            double dValue;

            byte[]  data;
            VMField vmField;

            while (!Stack.Empty)
            {
                byte opCode = CurrentInstructions[IP++];
                switch ((InstructionType)opCode)
                {
                case InstructionType.NOP:
                    break;

                case InstructionType.DUP:
                    Stack.DupN(1);
                    break;

                case InstructionType.DUP2:
                    Stack.DupN(2);
                    break;

                case InstructionType.PUSHB:
                    Stack.PushInt(ConsumeByte());
                    break;

                case InstructionType.PUSHI:
                    Stack.PushInt(ConsumeInt());
                    break;

                case InstructionType.PUSHD:
                    Stack.PushDouble(ConsumeDouble());
                    break;

                case InstructionType.PUSHA:
                    Stack.PushAddress(ConsumeUint());
                    break;

                case InstructionType.POPB:
                case InstructionType.POPI:
                    Stack.PopInt();
                    break;

                case InstructionType.POPD:
                    Stack.PopDouble();
                    break;

                case InstructionType.POPA:
                    Stack.PopAddress();
                    break;

                case InstructionType.LOADB:
                case InstructionType.LOADI:
                    addr = Stack.PopAddress();
                    switch (MemoryMap.MapToOffset(addr, out addr))
                    {
                    case MemoryTag.STACK:
                        Stack.PushInt(Stack.GetInt(addr));
                        break;

                    default:
                        throw new NotImplementedException();
                    }
                    break;

                case InstructionType.LOADD:
                    addr = Stack.PopAddress();
                    switch (MemoryMap.MapToOffset(addr, out addr))
                    {
                    case MemoryTag.STACK:
                        Stack.PushDouble(Stack.GetDouble(addr));
                        break;

                    default:
                        throw new NotImplementedException();
                    }
                    break;

                case InstructionType.LOADA:
                    addr = Stack.PopAddress();
                    switch (MemoryMap.MapToOffset(addr, out addr))
                    {
                    case MemoryTag.STACK:
                        Stack.PushAddress(Stack.GetAddress(addr));
                        break;

                    default:
                        throw new NotImplementedException();
                    }
                    break;

                case InstructionType.STOREB:
                case InstructionType.STOREI:
                    addr   = Stack.PopAddress();
                    iValue = Stack.TopInt;
                    switch (MemoryMap.MapToOffset(addr, out addr))
                    {
                    case MemoryTag.PRESERVED:
                        Preserved.SetInt(addr, iValue);
                        break;

                    case MemoryTag.STACK:
                        Stack.SetValue(addr, iValue);
                        break;

                    default:
                        throw new NotImplementedException();
                    }
                    break;

                case InstructionType.STORED:
                    addr   = Stack.PopAddress();
                    dValue = Stack.TopDouble;
                    switch (MemoryMap.MapToOffset(addr, out addr))
                    {
                    case MemoryTag.STACK:
                        Stack.SetValue(addr, dValue);
                        break;

                    default:
                        throw new NotImplementedException();
                    }
                    break;

                case InstructionType.STOREA:
                    addr   = Stack.PopAddress();
                    uValue = Stack.TopAddress;
                    switch (MemoryMap.MapToOffset(addr, out addr))
                    {
                    case MemoryTag.PRESERVED:
                        Preserved.SetAddress(addr, uValue);
                        break;

                    case MemoryTag.STACK:
                        Stack.SetValue(addr, uValue);
                        break;

                    default:
                        throw new NotImplementedException();
                    }
                    break;

                case InstructionType.ALOADB:
                    index = Stack.PopInt();
                    addr  = Stack.PopAddress();
                    switch (MemoryMap.MapToOffset(addr, out addr))
                    {
                    case MemoryTag.HEAP:
                        data = Heap.Singleton.GetData(addr).Data;
                        Stack.PushInt(data[HeapData.ArrayOffsetMap(sizeof(byte), index)]);
                        break;

                    default:
                        throw new NotImplementedException();
                    }
                    break;

                case InstructionType.ALOADI:
                    index = Stack.PopInt();
                    addr  = Stack.PopAddress();
                    switch (MemoryMap.MapToOffset(addr, out addr))
                    {
                    case MemoryTag.HEAP:
                        data = Heap.Singleton.GetData(addr).Data;
                        Stack.PushInt(BitConverter.ToInt32(data, HeapData.ArrayOffsetMap(sizeof(int), index)));
                        break;

                    default:
                        throw new NotImplementedException();
                    }
                    break;

                case InstructionType.ALOADD:
                    index = Stack.PopInt();
                    addr  = Stack.PopAddress();
                    switch (MemoryMap.MapToOffset(addr, out addr))
                    {
                    case MemoryTag.HEAP:
                        data = Heap.Singleton.GetData(addr).Data;
                        Stack.PushDouble(BitConverter.ToDouble(data, HeapData.ArrayOffsetMap(sizeof(double), index)));
                        break;

                    default:
                        throw new NotImplementedException();
                    }
                    break;

                case InstructionType.ALOADA:
                    index = Stack.PopInt();
                    addr  = Stack.PopAddress();
                    switch (MemoryMap.MapToOffset(addr, out addr))
                    {
                    case MemoryTag.HEAP:
                        data = Heap.Singleton.GetData(addr).Data;
                        Stack.PushAddress(BitConverter.ToUInt32(data, HeapData.ArrayOffsetMap(sizeof(uint), index)));
                        break;

                    default:
                        throw new NotImplementedException();
                    }
                    break;

                case InstructionType.ASTOREB:
                    index  = Stack.PopInt();
                    addr   = Stack.PopAddress();
                    iValue = Stack.TopInt;
                    switch (MemoryMap.MapToOffset(addr, out addr))
                    {
                    case MemoryTag.HEAP:
                        data = Heap.Singleton.GetData(addr).Data;
                        data[HeapData.ArrayOffsetMap(sizeof(byte), index)] = (byte)iValue;
                        break;

                    default:
                        throw new NotImplementedException();
                    }
                    break;

                case InstructionType.ASTOREI:
                    index  = Stack.PopInt();
                    addr   = Stack.PopAddress();
                    iValue = Stack.TopInt;
                    switch (MemoryMap.MapToOffset(addr, out addr))
                    {
                    case MemoryTag.HEAP:
                        data = Heap.Singleton.GetData(addr).Data;
                        BitConverter.TryWriteBytes(new Span <byte>(data, HeapData.ArrayOffsetMap(sizeof(int), index), sizeof(int)), iValue);
                        break;

                    default:
                        throw new NotImplementedException();
                    }
                    break;

                case InstructionType.ASTORED:
                    index  = Stack.PopInt();
                    addr   = Stack.PopAddress();
                    dValue = Stack.TopDouble;
                    switch (MemoryMap.MapToOffset(addr, out addr))
                    {
                    case MemoryTag.HEAP:
                        data = Heap.Singleton.GetData(addr).Data;
                        BitConverter.TryWriteBytes(new Span <byte>(data, HeapData.ArrayOffsetMap(sizeof(double), index), sizeof(double)), dValue);
                        break;

                    default:
                        throw new NotImplementedException();
                    }
                    break;

                case InstructionType.ASTOREA:
                    index  = Stack.PopInt();
                    addr   = Stack.PopAddress();
                    uValue = Stack.TopAddress;
                    switch (MemoryMap.MapToOffset(addr, out addr))
                    {
                    case MemoryTag.HEAP:
                        data = Heap.Singleton.GetData(addr).Data;
                        BitConverter.TryWriteBytes(new Span <byte>(data, HeapData.ArrayOffsetMap(sizeof(uint), index), sizeof(uint)), uValue);
                        break;

                    default:
                        throw new NotImplementedException();
                    }
                    break;

                case InstructionType.ADDI:
                    rhsi         = Stack.PopInt();
                    Stack.TopInt = Stack.TopInt + rhsi;
                    break;

                case InstructionType.SUBI:
                    rhsi         = Stack.PopInt();
                    Stack.TopInt = Stack.TopInt - rhsi;
                    break;

                case InstructionType.MULI:
                    rhsi         = Stack.PopInt();
                    Stack.TopInt = Stack.TopInt * rhsi;
                    break;

                case InstructionType.DIVI:
                    rhsi         = Stack.PopInt();
                    Stack.TopInt = Stack.TopInt / rhsi;
                    break;

                case InstructionType.MOD:
                    rhsi         = Stack.PopInt();
                    Stack.TopInt = Stack.TopInt % rhsi;
                    break;

                case InstructionType.NEGI:
                    Stack.TopInt = -Stack.TopInt;
                    break;

                case InstructionType.I2D:
                    iValue = Stack.PopInt();
                    Stack.PushDouble(iValue);
                    break;

                case InstructionType.D2I:
                    dValue = Stack.PopDouble();
                    Stack.PushInt((int)dValue);
                    break;

                case InstructionType.SETEQI:
                case InstructionType.SETNEI:
                case InstructionType.SETLTI:
                case InstructionType.SETLEI:
                case InstructionType.SETGTI:
                case InstructionType.SETGEI:
                    rhsi = Stack.PopInt();
                    lhsi = Stack.PopInt();
                    Stack.PushInt((InstructionType)opCode switch
                    {
                        InstructionType.SETEQI => lhsi == rhsi ? 1 : 0,
                        InstructionType.SETNEI => lhsi != rhsi ? 1 : 0,
                        InstructionType.SETLTI => lhsi <rhsi ? 1 : 0,
                                                        InstructionType.SETLEI => lhsi <= rhsi ? 1 : 0,
                                                        InstructionType.SETGTI => lhsi> rhsi ? 1 : 0,
                        InstructionType.SETGEI => lhsi >= rhsi ? 1 : 0,
                        _ => throw new NotImplementedException(),
                    });
                    break;