Пример #1
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="vmClass"></param>
        /// <returns>绝对地址</returns>
        public uint MallocClassStaticArea(VMClass vmClass)
        {
            HeapData ret = Malloc(vmClass.StaticFieldSize);

            // TODO 头部信息暂时不知道填什么

            return(MemoryMap.MapToAbsolute(ret.Offset, MemoryTag.STATIC));
        }
Пример #2
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="objectClass"></param>
        /// <returns>绝对地址</returns>
        public uint New(VMClass objectClass)
        {
            HeapData data = Malloc(objectClass.FieldSize);

            // 类型信息
            data.TypeInfo = objectClass.StaticFieldAddress;

            return(MemoryMap.MapToAbsolute(data.Offset, MemoryTag.HEAP));
        }
Пример #3
0
        /// <summary>
        /// 构建字符串的char数组
        /// </summary>
        /// <param name="len">byte长度</param>
        /// <returns></returns>
        private HeapData MallocCharArray(int len)
        {
            int size = len * sizeof(byte) + HeapData.MiscDataSize + HeapData.ArrayLengthSize;

            HeapData ret = Malloc(size);

            // 长度信息
            BitConverter.TryWriteBytes(new Span <byte>(ret.Data, HeapData.MiscDataSize, HeapData.ArrayLengthSize), len);
            // 头部信息可以不填,因为MethodArea是内存的边界,GC不会继续walk

            return(ret);
        }
Пример #4
0
        /// <summary>
        /// 数组
        /// </summary>
        /// <param name="typeTag"></param>
        /// <param name="len"></param>
        /// <returns></returns>
        public uint MallocArray(VariableTypeTag typeTag, int len)
        {
            int size = len * VariableType.GetSize(typeTag) + HeapData.MiscDataSize + HeapData.ArrayLengthSize;

            HeapData ret = Malloc(size);

            // 数组长度
            BitConverter.TryWriteBytes(new Span <byte>(ret.Data, HeapData.MiscDataSize, HeapData.ArrayLengthSize), len);
            // GC的数组tag
            BitConverter.TryWriteBytes(new Span <byte>(ret.Data, sizeof(uint), sizeof(uint)), (uint)GCTag.ArrayMark);
            // 数组的Type是基本类型
            ret.TypeInfo = (uint)typeTag;

            return(MemoryMap.MapToAbsolute(ret.Offset, MemoryTag.HEAP));
        }
Пример #5
0
        public HeapData Malloc(int size)
        {
            if (size == 0)
            {
                throw new XiVMError("Malloc space of size 0 is not supported");
            }
            if (Size + size > SizeLimit)
            {
                throw new XiVMError("MethodArea overflow");
            }
            HeapData ret = new HeapData((uint)Size, new byte[size]);

            DataMap.Add((uint)Size, ret);
            Size += size;
            return(ret);
        }
Пример #6
0
        public HeapData Malloc(byte[] data)
        {
            if (data.Length == 0)
            {
                throw new XiVMError("Malloc space of size 0 is not supported");
            }
            if (Size + data.Length > SizeLimit)
            {
                throw new XiVMError("MethodArea overflow");
            }

            HeapData ret = new HeapData((uint)Size, data);

            DataMap.Add((uint)Size, ret);
            Size += data.Length;
            return(ret);
        }
Пример #7
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));
                        }
                    }
                }
            }
        }
Пример #8
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));
        }
Пример #9
0
        public HeapData Malloc(int size)
        {
            if (size == 0)
            {
                throw new XiVMError("Malloc space of size 0 is not supported");
            }

            if (Size + size > SizeLimit)
            {
                GarbageCollector.CollectGarbage();
                if (Size + size > SizeLimit)
                {
                    throw new XiVMError("Heap overflow");
                }
            }

            // Best Fit
            LinkedListNode <HeapData> best = null;
            int bestFragmentSize           = 0;
            LinkedListNode <HeapData> cur  = Data.First;

            while (cur != null)
            {
                if (cur.Next != null)
                {
                    int fragmentSize = (int)(cur.Next.Value.Offset - (cur.Value.Offset + cur.Value.Data.Length));
                    if (fragmentSize >= size)
                    {
                        // 可以填入
                        if (best == null || bestFragmentSize > fragmentSize)
                        {
                            // best fit
                            best             = cur;
                            bestFragmentSize = fragmentSize;
                        }
                    }
                }

                cur = cur.Next;
            }

            HeapData ret = null;

            if (best == null)
            {
                // 未找到内碎片,在末尾添加
                ret = new HeapData(
                    Data.Count == 0 ? 0 : Data.Last.Value.Offset + (uint)Data.Last.Value.Data.Length,
                    new byte[size]);
                Data.AddLast(ret);
            }
            else
            {
                // fit
                ret = new HeapData(best.Value.Offset + (uint)best.Value.Data.Length,
                                   new byte[size]);
                Data.AddAfter(best, ret);
            }

            DataMap.Add(ret.Offset, ret);
            Size += size;
            if (Size > MaxSize)
            {
                MaxSize = size;
            }

            return(ret);
        }
Пример #10
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;