diff --git a/ILRuntime/Runtime/Intepreter/ILIntepreter.cs b/ILRuntime/Runtime/Intepreter/ILIntepreter.cs index b9071753..4b561a07 100644 --- a/ILRuntime/Runtime/Intepreter/ILIntepreter.cs +++ b/ILRuntime/Runtime/Intepreter/ILIntepreter.cs @@ -137,7 +137,7 @@ public object Run(ILMethod method, object instance, object[] p) } unhandledException = false; StackObject* objRef, objRef2, dst, val, a, b, arrRef; - object obj; + object obj = null; IType type; Type clrType; int intVal; @@ -155,7 +155,7 @@ public object Run(ILMethod method, object instance, object[] p) mStack.Add(null); break; case ObjectTypes.ValueTypeObjectReference: - CloneStackValueType(a, a, mStack); + //CloneStackValueType(a, a, mStack); break; case ObjectTypes.Object: case ObjectTypes.FieldReference: @@ -1960,12 +1960,43 @@ public object Run(ILMethod method, object instance, object[] p) dst = ILIntepreter.ResolveReference(objRef); var ft = domain.GetType(dst->Value); if (ft is ILType) - dst = Minus(dst, (int)ip->TokenLong + 1); + val = Minus(dst, (int)ip->TokenLong + 1); else - dst = Minus(dst, ((CLRType)ft).FieldIndexMapping[(int)ip->TokenLong] + 1); - StackObject valRef = *ret; - CopyToStack(ret, dst, mStack); - FreeStackValueType(&valRef); + val = Minus(dst, ((CLRType)ft).FieldIndexMapping[(int)ip->TokenLong] + 1); + if (val->ObjectType == ObjectTypes.ValueTypeObjectReference && ret->ObjectType == ObjectTypes.ValueTypeObjectReference) + { + int start = int.MaxValue; + int end = int.MaxValue; + objRef2 = dst; + stack.CountValueTypeManaged(ret, ref start, ref end, &objRef2); + stack.RelocateValueType(val, ref dst, ref start); + stack.ValueTypeStackPointer = dst; + if (start <= end) + stack.RemoveManagedStackRange(start, end); + } + else + { + StackObject valRef; + if (val->ObjectType == ObjectTypes.ValueTypeObjectReference) + { + Free(ret); + CopyToStack(ret, val, mStack); + } + else + { + valRef = *val; + if (val->ObjectType >= ObjectTypes.Object) + obj = mStack[val->Value]; + //CopyToStack(ret, dst, mStack); + Free(ret); + if (valRef.ObjectType >= ObjectTypes.Object) + { + valRef.Value = mStack.Count; + mStack.Add(obj); + } + *ret = valRef; + } + } } else { @@ -4206,8 +4237,6 @@ void DumpStack(StackObject* esp) void CloneStackValueType(StackObject* src, StackObject* dst, IList mStack) { StackObject* descriptor = ILIntepreter.ResolveReference(src); - if (src == dst) - FreeStackValueType(src); stack.AllocValueType(dst, AppDomain.GetType(descriptor->Value)); StackObject* dstDescriptor = ILIntepreter.ResolveReference(dst); int cnt = descriptor->ValueLow; @@ -5083,12 +5112,22 @@ bool CheckExceptionType(IType catchType, object exception, bool explicitMatch) public void CopyToStack(StackObject* dst, StackObject* src, IList mStack) { - *dst = *src; - if (dst->ObjectType >= ObjectTypes.Object) + if (src->ObjectType == ObjectTypes.ValueTypeObjectReference) { - dst->Value = mStack.Count; - var obj = mStack[src->Value]; - mStack.Add(obj); + var descriptor = ResolveReference(src); + var t = domain.GetType(descriptor->Value); + AllocValueType(dst, t); + CopyStackValueType(src, dst, mStack); + } + else + { + *dst = *src; + if (dst->ObjectType >= ObjectTypes.Object) + { + dst->Value = mStack.Count; + var obj = mStack[src->Value]; + mStack.Add(obj); + } } } @@ -5298,11 +5337,18 @@ public static void UnboxObject(StackObject* esp, object obj, IList mStac #endif public void Free(StackObject* esp) { - if (esp->ObjectType >= ObjectTypes.Object) + switch (esp->ObjectType) { - var mStack = stack.ManagedStack; - if (esp->Value == mStack.Count - 1) - mStack.RemoveAt(esp->Value); + case ObjectTypes.Object: + case ObjectTypes.FieldReference: + case ObjectTypes.ArrayReference: + var mStack = stack.ManagedStack; + if (esp->Value == mStack.Count - 1) + mStack.RemoveAt(esp->Value); + break; + case ObjectTypes.ValueTypeObjectReference: + FreeStackValueType(esp); + break; } #if DEBUG && !DISABLE_ILRUNTIME_DEBUG esp->ObjectType = ObjectTypes.Null; @@ -5317,6 +5363,7 @@ public void FreeStackValueType(StackObject* esp) var addr = ILIntepreter.ResolveReference(esp); if (addr <= ValueTypeBasePointer)//Only Stack allocation after base pointer should be freed, local variable are freed automatically stack.FreeValueTypeObject(esp); + esp->ObjectType = ObjectTypes.Null; } } diff --git a/ILRuntime/Runtime/Stack/RuntimeStack.cs b/ILRuntime/Runtime/Stack/RuntimeStack.cs index 6197790b..d5ef5366 100644 --- a/ILRuntime/Runtime/Stack/RuntimeStack.cs +++ b/ILRuntime/Runtime/Stack/RuntimeStack.cs @@ -57,6 +57,12 @@ public StackObject* ValueTypeStackPointer { return valueTypePtr; } + set + { + if (value > ValueTypeStackBase) + throw new StackOverflowException(); + valueTypePtr = value; + } } public StackObject* ValueTypeStackBase @@ -139,7 +145,7 @@ public void PushFrame(ref StackFrame frame) return ret; } - void RelocateValueType(StackObject* src, ref StackObject* dst, ref int mStackBase) + public void RelocateValueType(StackObject* src, ref StackObject* dst, ref int mStackBase) { StackObject* descriptor = ILIntepreter.ResolveReference(src); if (descriptor > dst) @@ -345,19 +351,8 @@ public void ClearValueTypeObject(IType type, StackObject* ptr) } } - public void FreeValueTypeObject(StackObject* esp) + public void RemoveManagedStackRange(int start, int end) { - 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(); if (start != int.MaxValue) { if (end == managedStack.Count - 1) @@ -373,7 +368,23 @@ public void FreeValueTypeObject(StackObject* esp) } } - void CountValueTypeManaged(StackObject* esp, ref int start, ref int end, StackObject** endAddr) + 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;