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