コード例 #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));
                        }
                    }
                }
            }
        }
コード例 #2
0
ファイル: VMExecutor.cs プロジェクト: XiPotatonium/XiVM
        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;