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 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++; }
public static uint GetAbsoluteAddress(PreservedAddressTag tag) { return(MemoryMap.MapToAbsolute((uint)tag, MemoryTag.PRESERVED)); }
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;