/// <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)); }
/// <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)); }
/// <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); }
/// <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)); }
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); }
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); }
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)); } } } } }
/// <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)); }
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); }
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;