123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633 |
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using ILRuntime.CLR.Method;
- using ILRuntime.CLR.TypeSystem;
- using ILRuntime.Other;
- using ILRuntime.Runtime.Intepreter;
- namespace ILRuntime.Runtime.Stack
- {
- unsafe class RuntimeStack : IDisposable
- {
- ILIntepreter intepreter;
- StackObject* pointer;
- StackObject* endOfMemory;
- StackObject* valueTypePtr;
- StackObjectAllocator allocator;
- IntPtr nativePointer;
- #if DEBUG && !DISABLE_ILRUNTIME_DEBUG
- IList<object> managedStack = new List<object>(32);
- #else
- IList<object> managedStack = new UncheckedList<object>(32);
- #endif
- UncheckedStack<StackFrame> frames = new UncheckedStack<StackFrame>();
- public const int MAXIMAL_STACK_OBJECTS = 1024 * 16;
- public UncheckedStack<StackFrame> Frames { get { return frames; } }
- public RuntimeStack(ILIntepreter intepreter)
- {
- this.intepreter = intepreter;
- nativePointer = System.Runtime.InteropServices.Marshal.AllocHGlobal(sizeof(StackObject) * MAXIMAL_STACK_OBJECTS);
- pointer = (StackObject*)nativePointer.ToPointer();
- endOfMemory = Add(pointer, MAXIMAL_STACK_OBJECTS);
- valueTypePtr = endOfMemory - 1;
- }
- ~RuntimeStack()
- {
- Dispose();
- }
- public StackObject* StackBase
- {
- get
- {
- return pointer;
- }
- }
- public StackObject* ValueTypeStackPointer
- {
- get
- {
- return valueTypePtr;
- }
- internal set
- {
- if (value > ValueTypeStackBase)
- throw new StackOverflowException();
- valueTypePtr = value;
- }
- }
- public StackObject* ValueTypeStackBase
- {
- get
- {
- return endOfMemory - 1;
- }
- }
- public IList<object> ManagedStack { get { return managedStack; } }
- public void ResetValueTypePointer()
- {
- valueTypePtr = endOfMemory - 1;
- }
- public void InitializeFrame(ILMethod method, StackObject* esp, out StackFrame res)
- {
- #if DEBUG
- if (esp < pointer || esp >= endOfMemory)
- throw new StackOverflowException();
- if (frames.Count > 0 && frames.Peek().BasePointer > esp)
- throw new StackOverflowException();
- #endif
- res = new StackFrame();
- res.LocalVarPointer = esp;
- res.Method = method;
- #if DEBUG && !DISABLE_ILRUNTIME_DEBUG
- res.Address = new IntegerReference();
- for (int i = 0; i < method.LocalVariableCount; i++)
- {
- var p = Add(esp, i);
- p->ObjectType = ObjectTypes.Null;
- }
- #endif
- res.BasePointer = method.LocalVariableCount > 0 ? Add(esp, method.LocalVariableCount) : esp;
- res.ManagedStackBase = managedStack.Count;
- res.ValueTypeBasePointer = valueTypePtr;
- //frames.Push(res);
- }
- public void PushFrame(ref StackFrame frame)
- {
- frames.Push(ref frame);
- }
- public StackObject* PopFrame(ref StackFrame frame, StackObject* esp)
- {
- #if DEBUG
- if (frames.Count > 0 && frames.Peek().BasePointer == frame.BasePointer)
- #endif
- frames.Pop();
- #if DEBUG
- else
- throw new NotSupportedException();
- #endif
- StackObject* returnVal = esp - 1;
- var method = frame.Method;
- StackObject* ret = ILIntepreter.Minus(frame.LocalVarPointer, method.ParameterCount);
- int mStackBase = frame.ManagedStackBase;
- if (method.HasThis)
- ret--;
- if (allocator != null)
- allocator.FreeBefore(frame.ValueTypeBasePointer);
- for (StackObject* ptr = ret; ptr < frame.LocalVarPointer; ptr++)
- {
- if (ptr->ObjectType == ObjectTypes.ValueTypeObjectReference)
- {
- var addr = ILIntepreter.ResolveReference(ptr);
- int start = int.MaxValue;
- int end = int.MaxValue;
- var tmp = addr;
- CountValueTypeManaged(ptr, ref start, ref end, &tmp);
- if (addr > frame.ValueTypeBasePointer)
- {
- frame.ValueTypeBasePointer = addr;
- }
- if (start < mStackBase)
- mStackBase = start;
- }
- }
- if(method.ReturnType != intepreter.AppDomain.VoidType)
- {
- *ret = *returnVal;
- if(ret->ObjectType == ObjectTypes.Object)
- {
- ret->Value = mStackBase;
- managedStack[mStackBase] = managedStack[returnVal->Value];
- mStackBase++;
- }
- else if(ret->ObjectType == ObjectTypes.ValueTypeObjectReference)
- {
- StackObject* oriAddr = frame.ValueTypeBasePointer;
- RelocateValueType(ret, ref frame.ValueTypeBasePointer, ref mStackBase);
- *(long*)&ret->Value = (long)oriAddr;
- }
- ret++;
- }
- #if DEBUG && !DISABLE_ILRUNTIME_DEBUG
- ((List<object>)managedStack).RemoveRange(mStackBase, managedStack.Count - mStackBase);
- #else
- ((UncheckedList<object>)managedStack).RemoveRange(mStackBase, managedStack.Count - mStackBase);
- #endif
- valueTypePtr = frame.ValueTypeBasePointer;
- return ret;
- }
- public void RelocateValueTypeAndFreeAfterDst(StackObject* src, StackObject* dst)
- {
- var objRef2 = dst;
- dst = ILIntepreter.ResolveReference(dst);
- int start = int.MaxValue;
- int end = int.MaxValue;
- CountValueTypeManaged(objRef2, ref start, ref end, &objRef2);
- RelocateValueType(src, ref dst, ref start);
- ValueTypeStackPointer = dst;
- if (start <= end)
- RemoveManagedStackRange(start, end);
- }
- void RelocateValueType(StackObject* src, ref StackObject* dst, ref int mStackBase)
- {
- StackObject* descriptor = ILIntepreter.ResolveReference(src);
- if (descriptor > dst)
- throw new StackOverflowException();
- *dst = *descriptor;
- int cnt = descriptor->ValueLow;
- StackObject* endAddr = ILIntepreter.Minus(dst, cnt + 1);
- for(int i = 0; i < cnt; i++)
- {
- StackObject* addr = ILIntepreter.Minus(descriptor, i + 1);
- StackObject* tarVal = ILIntepreter.Minus(dst, i + 1);
- *tarVal = *addr;
- switch (addr->ObjectType)
- {
- case ObjectTypes.Object:
- case ObjectTypes.ArrayReference:
- case ObjectTypes.FieldReference:
- if (tarVal->Value >= mStackBase)
- {
- int oldIdx = addr->Value;
- tarVal->Value = mStackBase;
- managedStack[mStackBase] = managedStack[oldIdx];
- mStackBase++;
- }
- break;
- case ObjectTypes.ValueTypeObjectReference:
- var newAddr = endAddr;
- RelocateValueType(addr, ref endAddr, ref mStackBase);
- *(long*)&tarVal->Value = (long)newAddr;
- break;
- }
- }
- dst = endAddr;
- }
- int CountValueTypeManaged(IType type)
- {
- int res = 0;
- if (type is ILType)
- {
- ILType t = (ILType)type;
- for (int i = 0; i < t.FieldTypes.Length; i++)
- {
- var ft = t.FieldTypes[i];
- if (!ft.IsPrimitive && !ft.IsEnum)
- {
- if (ft.IsValueType)
- {
- if (!(ft is ILType) && ((CLRType)ft).ValueTypeBinder == null)
- {
- res++;
- }
- }
- else
- {
- res++;
- }
- }
- }
- if (type.BaseType != null && type.BaseType is ILType)
- res += CountValueTypeManaged((ILType)type.BaseType);
- }
- else
- {
- CLRType t = (CLRType)type;
- var cnt = t.TotalFieldCount;
- for (int i = 0; i < cnt; i++)
- {
- var it = t.OrderedFieldTypes[i] as CLRType;
- if (!it.IsPrimitive && it.IsEnum)
- {
- if (it.IsValueType)
- {
- if (it.ValueTypeBinder == null)
- {
- res++;
- }
- }
- else
- {
- res++;
- }
- }
- }
- }
- return res;
- }
- void AllocBlock(int size, out StackObject* dst, out int managedIdx)
- {
- dst = valueTypePtr;
- valueTypePtr = ILIntepreter.Minus(valueTypePtr, size);
- if (valueTypePtr <= StackBase)
- throw new StackOverflowException();
- managedIdx = managedStack.Count;
- }
- public void ClearAllocator()
- {
- if (allocator != null)
- allocator.Clear();
- }
- public void AllocValueTypeAndCopy(StackObject* ptr, StackObject* src)
- {
- var dst = ILIntepreter.ResolveReference(src);
- var type = intepreter.AppDomain.GetTypeByIndex(dst->Value);
- int size, managedCount;
- type.GetValueTypeSize(out size, out managedCount);
- if (allocator == null)
- allocator = new StackObjectAllocator(AllocBlock);
- StackObjectAllocation alloc;
- if(allocator.AllocExisting(ptr, size, managedCount, out alloc))
- {
- if (dst != alloc.Address)
- {
- dst = alloc.Address;
- ptr->ObjectType = ObjectTypes.ValueTypeObjectReference;
- *(long*)&ptr->Value = (long)dst;
- int managedIdx = alloc.ManagedIndex;
- InitializeValueTypeObject(type, dst, true, ref managedIdx, false);
- intepreter.CopyStackValueType(src, ptr, managedStack);
- FreeValueTypeObject(src);
- }
- else
- {
- ptr->ObjectType = ObjectTypes.ValueTypeObjectReference;
- *(long*)&ptr->Value = (long)dst;
- }
- }
- else
- {
- int start = int.MaxValue;
- int end = int.MinValue;
- StackObject* endAddr;
- CountValueTypeManaged(src, ref start, ref end, &endAddr);
- if (endAddr == valueTypePtr)
- valueTypePtr = dst;
- allocator.RegisterAllocation(ptr, dst, size, start, managedCount);
- ptr->ObjectType = ObjectTypes.ValueTypeObjectReference;
- *(long*)&ptr->Value = (long)dst;
- }
- }
- public void AllocValueType(StackObject* ptr, IType type, bool register = false, bool noInitialize = false)
- {
- if (type.IsValueType)
- {
- StackObject* dst;
- int size, managedCount;
- type.GetValueTypeSize(out size, out managedCount);
- int managedIdx = -1;
- if (register)
- {
- if (allocator == null)
- allocator = new StackObjectAllocator(AllocBlock);
- var allocation = allocator.Alloc(ptr, size, managedCount);
- dst = allocation.Address;
- managedIdx = allocation.ManagedIndex;
- }
- else
- {
- dst = valueTypePtr;
- managedIdx = managedStack.Count;
- valueTypePtr = ILIntepreter.Minus(valueTypePtr, size);
- if (valueTypePtr <= StackBase)
- throw new StackOverflowException();
- }
- ptr->ObjectType = ObjectTypes.ValueTypeObjectReference;
- *(long*)&ptr->Value = (long)dst;
- InitializeValueTypeObject(type, dst, register, ref managedIdx, noInitialize);
- }
- else
- throw new ArgumentException(type.FullName + " is not a value type.", "type");
- }
- internal void InitializeValueTypeObject(IType type, StackObject* ptr, bool register, ref int managedIdx, bool noInitialize)
- {
- ptr->ObjectType = ObjectTypes.ValueTypeDescriptor;
- ptr->Value = type.TypeIndex;
- ptr->ValueLow = type.TotalFieldCount;
- StackObject* endPtr = ptr - (type.TotalFieldCount + 1);
- if (noInitialize)
- return;
- if (type is ILType)
- {
- ILType t = (ILType)type;
- for (int i = 0; i < t.FieldTypes.Length; i++)
- {
- var ft = t.FieldTypes[i];
- StackObject* val = ILIntepreter.Minus(ptr, t.FieldStartIndex + i + 1);
- if (ft.IsPrimitive)
- *val = ft.DefaultObject;
- else if (ft.IsEnum)
- StackObject.Initialized(val, ft);
- else
- {
- if (ft.IsValueType)
- {
- if (ft is ILType || ((CLRType)ft).ValueTypeBinder != null)
- {
- val->ObjectType = ObjectTypes.ValueTypeObjectReference;
- *(long*)&val->Value = (long)endPtr;
- InitializeValueTypeObject(ft, endPtr, register, ref managedIdx, noInitialize);
- int size, mCnt;
- ft.GetValueTypeSize(out size, out mCnt);
- endPtr -= size;
- }
- else
- {
- val->ObjectType = ObjectTypes.Object;
- val->Value = managedIdx;
- if (managedIdx < managedStack.Count)
- managedStack[managedIdx] = ((CLRType)ft).CreateDefaultInstance();
- else
- managedStack.Add(((CLRType)ft).CreateDefaultInstance());
- managedIdx++;
- }
- }
- else
- {
- val->ObjectType = ObjectTypes.Object;
- val->Value = managedIdx;
- if (managedIdx < managedStack.Count)
- managedStack[managedIdx] = null;
- else
- managedStack.Add(null);
- managedIdx++;
- }
- }
- }
- if (type.BaseType != null && type.BaseType is ILType)
- InitializeValueTypeObject((ILType)type.BaseType, ptr, register, ref managedIdx, noInitialize);
- }
- else
- {
- CLRType t = (CLRType)type;
- var cnt = t.TotalFieldCount;
- for (int i = 0; i < cnt; i++)
- {
- var it = t.OrderedFieldTypes[i] as CLRType;
- StackObject* val = ILIntepreter.Minus(ptr, i + 1);
- if (it.IsPrimitive)
- *val = it.DefaultObject;
- else if (it.IsEnum)
- StackObject.Initialized(val, it);
- else
- {
- if (it.IsValueType)
- {
- if (it.ValueTypeBinder != null)
- {
- val->ObjectType = ObjectTypes.ValueTypeObjectReference;
- *(long*)&val->Value = (long)endPtr;
- InitializeValueTypeObject(it, endPtr, register, ref managedIdx, noInitialize);
- int size, mCnt;
- it.GetValueTypeSize(out size, out mCnt);
- endPtr -= size;
- }
- else
- {
- val->ObjectType = ObjectTypes.Object;
- val->Value = managedIdx;
- if (managedIdx < managedStack.Count)
- managedStack[managedIdx] = it.CreateDefaultInstance();
- else
- managedStack.Add(it.CreateDefaultInstance());
- managedIdx++;
- }
- }
- else
- {
- val->ObjectType = ObjectTypes.Object;
- val->Value = managedIdx;
- if (managedIdx < managedStack.Count)
- managedStack[managedIdx] = null;
- else
- managedStack.Add(null);
- managedIdx++;
- }
- }
- }
- }
- }
- public void ClearValueTypeObject(IType type, StackObject* ptr)
- {
- if (type is ILType)
- {
- ILType t = (ILType)type;
- for (int i = 0; i < t.FieldTypes.Length; i++)
- {
- var ft = t.FieldTypes[i];
- StackObject* val = ILIntepreter.Minus(ptr, t.FieldStartIndex + i + 1);
- if (ft.IsPrimitive || ft.IsEnum)
- StackObject.Initialized(val, ft);
- else
- {
- switch (val->ObjectType)
- {
- case ObjectTypes.ValueTypeObjectReference:
- ClearValueTypeObject(ft, ILIntepreter.ResolveReference(val));
- break;
- default:
- if (ft.IsValueType)
- {
- if(ft is ILType)
- {
- throw new NotImplementedException();
- }
- else
- {
- managedStack[val->Value] = ((CLRType)ft).CreateDefaultInstance();
- }
- }
- else
- managedStack[val->Value] = null;
- break;
- }
- }
- }
- if (type.BaseType != null && type.BaseType is ILType)
- ClearValueTypeObject((ILType)type.BaseType, ptr);
- }
- else
- {
- CLRType t = (CLRType)type;
- var cnt = t.TotalFieldCount;
- for (int i = 0; i < cnt; i++)
- {
- var vt = t.OrderedFieldTypes[i] as CLRType;
- StackObject* val = ILIntepreter.Minus(ptr, i + 1);
- if (vt.IsPrimitive)
- StackObject.Initialized(val, vt);
- else
- {
- switch (val->ObjectType)
- {
- case ObjectTypes.ValueTypeObjectReference:
- {
- var dst = ILIntepreter.ResolveReference(val);
- ClearValueTypeObject(vt, dst);
- }
- break;
- default:
- if (vt.IsValueType)
- {
- managedStack[val->Value] = vt.CreateDefaultInstance();
- }
- else
- managedStack[val->Value] = null;
- break;
- }
- }
- }
- }
- }
- internal void RemoveManagedStackRange(int start, int end)
- {
- if (start != int.MaxValue)
- {
- if (end == managedStack.Count - 1)
- {
- #if DEBUG && !DISABLE_ILRUNTIME_DEBUG
- ((List<object>)managedStack).RemoveRange(start, managedStack.Count - start);
- #else
- ((UncheckedList<object>)managedStack).RemoveRange(start, managedStack.Count - start);
- #endif
- }
- else
- throw new NotSupportedException();
- }
- }
- public void FreeRegisterValueType(StackObject* esp)
- {
- if (esp->ObjectType != ObjectTypes.ValueTypeObjectReference)
- return;
- allocator.Free(esp);
- }
- public void FreeValueTypeObject(StackObject* esp)
- {
- if (esp->ObjectType != ObjectTypes.ValueTypeObjectReference)
- return;
- int start = int.MaxValue;
- int end = int.MinValue;
- StackObject* endAddr;
- CountValueTypeManaged(esp, ref start, ref end, &endAddr);
- if (endAddr == valueTypePtr)
- valueTypePtr = ILIntepreter.ResolveReference(esp);
- else
- throw new NotSupportedException();
- RemoveManagedStackRange(start, end);
- }
- public void CountValueTypeManaged(StackObject* esp, ref int start, ref int end, StackObject** endAddr)
- {
- StackObject* descriptor = ILIntepreter.ResolveReference(esp);
- int cnt = descriptor->ValueLow;
- *endAddr = ILIntepreter.Minus(descriptor, cnt + 1);
- for (int i = 0; i < cnt; i++)
- {
- StackObject* addr = ILIntepreter.Minus(descriptor, i + 1);
- switch (addr->ObjectType)
- {
- case ObjectTypes.Object:
- case ObjectTypes.ArrayReference:
- case ObjectTypes.FieldReference:
- {
- if (start == int.MaxValue)
- {
- start = addr->Value;
- end = start;
- }
- else if (addr->Value == end + 1)
- end++;
- else
- throw new NotSupportedException();
- }
- break;
- case ObjectTypes.ValueTypeObjectReference:
- CountValueTypeManaged(addr, ref start, ref end, endAddr);
- break;
- }
- }
- }
- public void Dispose()
- {
- if (nativePointer != IntPtr.Zero)
- {
- System.Runtime.InteropServices.Marshal.FreeHGlobal(nativePointer);
- nativePointer = IntPtr.Zero;
- }
- }
- StackObject* Add(StackObject* a, int b)
- {
- return (StackObject*)((long)a + sizeof(StackObject) * b);
- }
- }
- }
|