You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
5912 lines
318 KiB
5912 lines
318 KiB
using System; |
|
using System.Collections.Generic; |
|
using System.Linq; |
|
using System.Text; |
|
using System.Threading; |
|
|
|
using ILRuntime.Runtime.Enviorment; |
|
using ILRuntime.Runtime.Stack; |
|
using ILRuntime.CLR.Method; |
|
using ILRuntime.CLR.TypeSystem; |
|
using ILRuntime.Runtime.Intepreter.OpCodes; |
|
using ILRuntime.Runtime.Debugger; |
|
using ILRuntime.CLR.Utils; |
|
using ILRuntime.Other; |
|
|
|
namespace ILRuntime.Runtime.Intepreter |
|
{ |
|
public unsafe partial class ILIntepreter |
|
{ |
|
Enviorment.AppDomain domain; |
|
RuntimeStack stack; |
|
object _lockObj; |
|
bool allowUnboundCLRMethod; |
|
|
|
internal RuntimeStack Stack { get { return stack; } } |
|
public bool ShouldBreak { get; set; } |
|
public StepTypes CurrentStepType { get; set; } |
|
public StackObject* LastStepFrameBase { get; set; } |
|
public int LastStepInstructionIndex { get; set; } |
|
StackObject* ValueTypeBasePointer; |
|
#pragma warning disable CS0414 |
|
bool mainthreadLock; |
|
public ILIntepreter(Enviorment.AppDomain domain) |
|
{ |
|
this.domain = domain; |
|
stack = new RuntimeStack(this); |
|
allowUnboundCLRMethod = domain.AllowUnboundCLRMethod; |
|
#if DEBUG && !DISABLE_ILRUNTIME_DEBUG |
|
_lockObj = new object(); |
|
#endif |
|
} |
|
|
|
public Enviorment.AppDomain AppDomain { get { return domain; } } |
|
|
|
public void Break() |
|
{ |
|
//Clear old debug state |
|
ClearDebugState(); |
|
#if DEBUG && !NO_PROFILER |
|
if(domain.UnityMainThreadID == Thread.CurrentThread.ManagedThreadId) |
|
{ |
|
mainthreadLock = true; |
|
while (mainthreadLock) |
|
{ |
|
domain.DebugService.ResolvePendingRequests(); |
|
Thread.Sleep(10); |
|
} |
|
return; |
|
} |
|
#endif |
|
lock (_lockObj) |
|
{ |
|
Monitor.Wait(_lockObj); |
|
} |
|
} |
|
|
|
public void Resume() |
|
{ |
|
mainthreadLock = false; |
|
lock (_lockObj) |
|
Monitor.Pulse(_lockObj); |
|
} |
|
|
|
public void ClearDebugState() |
|
{ |
|
ShouldBreak = false; |
|
CurrentStepType = StepTypes.None; |
|
LastStepFrameBase = (StackObject*)0; |
|
LastStepInstructionIndex = 0; |
|
} |
|
public object Run(ILMethod method, object instance, object[] p) |
|
{ |
|
IList<object> mStack = stack.ManagedStack; |
|
int mStackBase = mStack.Count; |
|
StackObject* esp = stack.StackBase; |
|
stack.ResetValueTypePointer(); |
|
if (method.HasThis) |
|
{ |
|
if (instance is CrossBindingAdaptorType) |
|
instance = ((CrossBindingAdaptorType)instance).ILInstance; |
|
if (instance == null) |
|
throw new NullReferenceException("instance should not be null!"); |
|
esp = PushObject(esp, mStack, instance); |
|
} |
|
bool useRegister = method.ShouldUseRegisterVM; |
|
esp = PushParameters(method, esp, p, useRegister); |
|
bool unhandledException; |
|
if (useRegister) |
|
esp = ExecuteR(method, esp, out unhandledException); |
|
else |
|
esp = Execute(method, esp, out unhandledException); |
|
object result = method.ReturnType != domain.VoidType ? method.ReturnType.TypeForCLR.CheckCLRTypes(StackObject.ToObject((esp - 1), domain, mStack)) : null; |
|
//ClearStack |
|
#if DEBUG && !DISABLE_ILRUNTIME_DEBUG |
|
((List<object>)mStack).RemoveRange(mStackBase, mStack.Count - mStackBase); |
|
#else |
|
((UncheckedList<object>)mStack).RemoveRange(mStackBase, mStack.Count - mStackBase); |
|
#endif |
|
return result; |
|
} |
|
internal StackObject* Execute(ILMethod method, StackObject* esp, out bool unhandledException) |
|
{ |
|
allowUnboundCLRMethod = domain.AllowUnboundCLRMethod; |
|
#if DEBUG |
|
if (method == null) |
|
throw new NullReferenceException(); |
|
#endif |
|
#if DEBUG && !NO_PROFILER |
|
if (System.Threading.Thread.CurrentThread.ManagedThreadId == AppDomain.UnityMainThreadID) |
|
|
|
#if UNITY_5_5_OR_NEWER |
|
UnityEngine.Profiling.Profiler.BeginSample(method.ToString()); |
|
#else |
|
UnityEngine.Profiler.BeginSample(method.ToString()); |
|
#endif |
|
|
|
#endif |
|
OpCode[] body = method.Body; |
|
StackFrame frame; |
|
stack.InitializeFrame(method, esp, out frame); |
|
StackObject* v1 = frame.LocalVarPointer; |
|
StackObject* v2 = frame.LocalVarPointer + 1; |
|
StackObject* v3 = frame.LocalVarPointer + 1 + 1; |
|
StackObject* v4 = Add(frame.LocalVarPointer, 3); |
|
Exception lastCaughtEx = null; |
|
int finallyEndAddress = 0; |
|
var ehs = method.ExceptionHandler; |
|
|
|
esp = frame.BasePointer; |
|
var arg = Minus(frame.LocalVarPointer, method.ParameterCount); |
|
IList<object> mStack = stack.ManagedStack; |
|
int paramCnt = method.ParameterCount; |
|
if (method.HasThis)//this parameter is always object reference |
|
{ |
|
arg--; |
|
paramCnt++; |
|
/// 为确保性能,暂时先确保开发的时候,安全检查完备。 |
|
/// 当然手机端运行时可能会出现为空的类对象可正常调用成员函数,导致成员函数里面访问成员变量报错时可能使得根据Log跟踪BUG时方向错误。 |
|
#if DEBUG && !DISABLE_ILRUNTIME_DEBUG |
|
var thisObj = RetriveObject(arg, mStack); |
|
if (thisObj == null) |
|
throw new NullReferenceException(); |
|
#endif |
|
} |
|
unhandledException = false; |
|
StackObject* objRef, objRef2, dst, val, a, b, arrRef; |
|
object obj = null; |
|
IType type; |
|
Type clrType; |
|
int intVal; |
|
|
|
//Managed Stack reserved for arguments(In case of starg) |
|
for (int i = 0; i < paramCnt; i++) |
|
{ |
|
a = Add(arg, i); |
|
switch (a->ObjectType) |
|
{ |
|
case ObjectTypes.Null: |
|
//Need to reserve place for null, in case of starg |
|
a->ObjectType = ObjectTypes.Object; |
|
a->Value = mStack.Count; |
|
mStack.Add(null); |
|
break; |
|
case ObjectTypes.ValueTypeObjectReference: |
|
//CloneStackValueType(a, a, mStack); |
|
break; |
|
case ObjectTypes.Object: |
|
case ObjectTypes.FieldReference: |
|
case ObjectTypes.ArrayReference: |
|
{ |
|
if (i > 0 || !method.HasThis)//this instance should not be cloned |
|
mStack[a->Value] = CheckAndCloneValueType(mStack[a->Value], AppDomain); |
|
} |
|
frame.ManagedStackBase--; |
|
break; |
|
} |
|
} |
|
|
|
stack.PushFrame(ref frame); |
|
|
|
int locBase = mStack.Count; |
|
//Managed Stack reserved for local variable |
|
for (int i = 0; i < method.LocalVariableCount; i++) |
|
{ |
|
mStack.Add(null); |
|
} |
|
|
|
for (int i = 0; i < method.LocalVariableCount; i++) |
|
{ |
|
var v = method.Variables[i]; |
|
bool isEnum = false; |
|
var vt = v.VariableType; |
|
IType t; |
|
if (vt.IsGenericParameter) |
|
{ |
|
t = method.FindGenericArgument(vt.Name); |
|
} |
|
else |
|
{ |
|
t = AppDomain.GetType(v.VariableType, method.DeclearingType, method); |
|
} |
|
isEnum = t.IsEnum; |
|
|
|
if (!t.IsByRef && t.IsValueType && !t.IsPrimitive && !isEnum) |
|
{ |
|
if (t is ILType) |
|
{ |
|
//var obj = ((ILType)t).Instantiate(false); |
|
var loc = Add(v1, i); |
|
stack.AllocValueType(loc, t); |
|
|
|
/*loc->ObjectType = ObjectTypes.Object; |
|
loc->Value = mStack.Count; |
|
mStack.Add(obj);*/ |
|
|
|
} |
|
else |
|
{ |
|
CLRType cT = (CLRType)t; |
|
var loc = Add(v1, i); |
|
if (cT.ValueTypeBinder != null) |
|
{ |
|
stack.AllocValueType(loc, t); |
|
} |
|
else |
|
{ |
|
obj = ((CLRType)t).CreateDefaultInstance(); |
|
loc->ObjectType = ObjectTypes.Object; |
|
loc->Value = locBase + i; |
|
mStack[locBase + i] = obj; |
|
} |
|
} |
|
} |
|
else |
|
{ |
|
if (t.IsPrimitive || isEnum) |
|
{ |
|
var loc = Add(v1, i); |
|
StackObject.Initialized(loc, t); |
|
} |
|
else |
|
{ |
|
var loc = Add(v1, i); |
|
loc->ObjectType = ObjectTypes.Object; |
|
loc->Value = locBase + i; |
|
} |
|
} |
|
} |
|
|
|
var bp = stack.ValueTypeStackPointer; |
|
ValueTypeBasePointer = bp; |
|
fixed (OpCode* ptr = body) |
|
{ |
|
OpCode* ip = ptr; |
|
OpCodeEnum code = ip->Code; |
|
bool returned = false; |
|
while (!returned) |
|
{ |
|
try |
|
{ |
|
#if DEBUG && !DISABLE_ILRUNTIME_DEBUG |
|
if (ShouldBreak) |
|
Break(); |
|
var insOffset = (int)(ip - ptr); |
|
frame.Address.Value = insOffset; |
|
AppDomain.DebugService.CheckShouldBreak(method, this, insOffset); |
|
#endif |
|
code = ip->Code; |
|
switch (code) |
|
{ |
|
#region Arguments and Local Variable |
|
case OpCodeEnum.Ldarg_0: |
|
CopyToStack(esp, arg, mStack); |
|
esp++; |
|
break; |
|
case OpCodeEnum.Ldarg_1: |
|
CopyToStack(esp, arg + 1, mStack); |
|
esp++; |
|
break; |
|
case OpCodeEnum.Ldarg_2: |
|
CopyToStack(esp, arg + 1 + 1, mStack); |
|
esp++; |
|
break; |
|
case OpCodeEnum.Ldarg_3: |
|
CopyToStack(esp, arg + 1 + 1 + 1, mStack); |
|
esp++; |
|
break; |
|
case OpCodeEnum.Ldarg: |
|
case OpCodeEnum.Ldarg_S: |
|
CopyToStack(esp, Add(arg, ip->TokenInteger), mStack); |
|
esp++; |
|
break; |
|
case OpCodeEnum.Ldarga: |
|
case OpCodeEnum.Ldarga_S: |
|
{ |
|
a = Add(arg, ip->TokenInteger); |
|
esp->ObjectType = ObjectTypes.StackObjectReference; |
|
*(long*)&esp->Value = (long)a; |
|
esp++; |
|
} |
|
break; |
|
case OpCodeEnum.Starg: |
|
case OpCodeEnum.Starg_S: |
|
{ |
|
a = Add(arg, ip->TokenInteger); |
|
val = esp - 1; |
|
int idx = a->Value; |
|
bool isObj = a->ObjectType >= ObjectTypes.Object; |
|
if (val->ObjectType >= ObjectTypes.Object) |
|
{ |
|
if (a->ObjectType == ObjectTypes.ValueTypeObjectReference) |
|
{ |
|
dst = ILIntepreter.ResolveReference(a); |
|
CopyValueTypeToStack(dst, mStack[val->Value], mStack); |
|
} |
|
else |
|
{ |
|
a->ObjectType = val->ObjectType; |
|
mStack[a->Value] = mStack[val->Value]; |
|
a->ValueLow = val->ValueLow; |
|
} |
|
} |
|
else |
|
{ |
|
if (a->ObjectType == ObjectTypes.ValueTypeObjectReference) |
|
{ |
|
if (val->ObjectType == ObjectTypes.ValueTypeObjectReference) |
|
{ |
|
CopyStackValueType(val, a, mStack); |
|
FreeStackValueType(val); |
|
} |
|
else |
|
throw new NotSupportedException(); |
|
} |
|
else |
|
{ |
|
if (val->ObjectType == ObjectTypes.ValueTypeObjectReference) |
|
{ |
|
if (isObj) |
|
{ |
|
mStack[a->Value] = StackObject.ToObject(val, domain, mStack); |
|
} |
|
else |
|
throw new NotSupportedException(); |
|
} |
|
else |
|
{ |
|
*a = *val; |
|
if (isObj) |
|
{ |
|
a->Value = idx; |
|
if (val->ObjectType == ObjectTypes.Null) |
|
{ |
|
mStack[a->Value] = null; |
|
} |
|
} |
|
} |
|
} |
|
} |
|
Free(val); |
|
esp--; |
|
} |
|
break; |
|
case OpCodeEnum.Stloc_0: |
|
{ |
|
esp--; |
|
int idx = locBase; |
|
StLocSub(esp, v1, idx, mStack); |
|
} |
|
break; |
|
case OpCodeEnum.Ldloc_0: |
|
CopyToStack(esp, v1, mStack); |
|
esp++; |
|
break; |
|
case OpCodeEnum.Stloc_1: |
|
{ |
|
esp--; |
|
int idx = locBase + 1; |
|
StLocSub(esp, v2, idx, mStack); |
|
} |
|
break; |
|
case OpCodeEnum.Ldloc_1: |
|
CopyToStack(esp, v2, mStack); |
|
esp++; |
|
break; |
|
case OpCodeEnum.Stloc_2: |
|
{ |
|
esp--; |
|
int idx = locBase + 2; |
|
StLocSub(esp, v3, idx, mStack); |
|
break; |
|
} |
|
case OpCodeEnum.Ldloc_2: |
|
CopyToStack(esp, v3, mStack); |
|
esp++; |
|
break; |
|
case OpCodeEnum.Stloc_3: |
|
{ |
|
esp--; |
|
int idx = locBase + 3; |
|
|
|
StLocSub(esp, v4, idx, mStack); |
|
} |
|
break; |
|
case OpCodeEnum.Ldloc_3: |
|
CopyToStack(esp, v4, mStack); |
|
esp++; |
|
break; |
|
case OpCodeEnum.Stloc: |
|
case OpCodeEnum.Stloc_S: |
|
{ |
|
esp--; |
|
var v = Add(frame.LocalVarPointer, ip->TokenInteger); |
|
int idx = locBase + ip->TokenInteger; |
|
StLocSub(esp, v, idx, mStack); |
|
} |
|
break; |
|
case OpCodeEnum.Ldloc: |
|
case OpCodeEnum.Ldloc_S: |
|
{ |
|
var v = Add(frame.LocalVarPointer, ip->TokenInteger); |
|
CopyToStack(esp, v, mStack); |
|
esp++; |
|
} |
|
break; |
|
case OpCodeEnum.Ldloca: |
|
case OpCodeEnum.Ldloca_S: |
|
{ |
|
var v = Add(frame.LocalVarPointer, ip->TokenInteger); |
|
esp->ObjectType = ObjectTypes.StackObjectReference; |
|
*(long*)&esp->Value = (long)v; |
|
esp++; |
|
} |
|
break; |
|
case OpCodeEnum.Ldobj: |
|
{ |
|
objRef = esp - 1; |
|
switch (objRef->ObjectType) |
|
{ |
|
case ObjectTypes.ArrayReference: |
|
{ |
|
var t = AppDomain.GetType(ip->TokenInteger); |
|
obj = mStack[objRef->Value]; |
|
var idx = objRef->ValueLow; |
|
Free(objRef); |
|
LoadFromArrayReference(obj, idx, objRef, t, mStack); |
|
} |
|
break; |
|
case ObjectTypes.StackObjectReference: |
|
{ |
|
CopyToStack(objRef, GetObjectAndResolveReference(objRef), mStack); |
|
} |
|
break; |
|
case ObjectTypes.FieldReference: |
|
{ |
|
obj = mStack[objRef->Value]; |
|
int idx = objRef->ValueLow; |
|
Free(objRef); |
|
if (obj is ILTypeInstance) |
|
{ |
|
((ILTypeInstance)obj).PushToStack(idx, objRef, this, mStack); |
|
} |
|
else |
|
{ |
|
var t = AppDomain.GetType(ip->TokenInteger); |
|
if (!((CLRType)t).CopyFieldToStack(idx, obj, this, ref objRef, mStack)) |
|
{ |
|
obj = ((CLRType)t).GetFieldValue(idx, obj); |
|
PushObject(objRef, mStack, obj); |
|
} |
|
} |
|
} |
|
break; |
|
case ObjectTypes.StaticFieldReference: |
|
{ |
|
var t = AppDomain.GetType(objRef->Value); |
|
int idx = objRef->ValueLow; |
|
Free(objRef); |
|
if (t is ILType) |
|
{ |
|
((ILType)t).StaticInstance.PushToStack(idx, objRef, this, mStack); |
|
} |
|
else |
|
{ |
|
if (!((CLRType)t).CopyFieldToStack(idx, null, this, ref objRef, mStack)) |
|
{ |
|
obj = ((CLRType)t).GetFieldValue(idx, null); |
|
PushObject(objRef, mStack, obj); |
|
} |
|
} |
|
} |
|
break; |
|
default: |
|
throw new NotImplementedException(); |
|
} |
|
} |
|
break; |
|
case OpCodeEnum.Stobj: |
|
{ |
|
objRef = esp - 1 - 1; |
|
val = esp - 1; |
|
switch (objRef->ObjectType) |
|
{ |
|
case ObjectTypes.ArrayReference: |
|
{ |
|
var t = AppDomain.GetType(ip->TokenInteger); |
|
StoreValueToArrayReference(objRef, val, t, mStack); |
|
} |
|
break; |
|
case ObjectTypes.StackObjectReference: |
|
{ |
|
objRef = GetObjectAndResolveReference(objRef); |
|
if (objRef->ObjectType == ObjectTypes.ValueTypeObjectReference) |
|
{ |
|
switch (val->ObjectType) |
|
{ |
|
case ObjectTypes.Object: |
|
dst = ILIntepreter.ResolveReference(objRef); |
|
CopyValueTypeToStack(dst, mStack[val->Value], mStack); |
|
break; |
|
case ObjectTypes.ValueTypeObjectReference: |
|
CopyStackValueType(val, objRef, mStack); |
|
break; |
|
default: |
|
throw new NotImplementedException(); |
|
} |
|
} |
|
else |
|
{ |
|
if (val->ObjectType >= ObjectTypes.Object) |
|
{ |
|
mStack[objRef->Value] = mStack[val->Value]; |
|
objRef->ValueLow = val->ValueLow; |
|
} |
|
else |
|
{ |
|
*objRef = *val; |
|
} |
|
} |
|
} |
|
break; |
|
case ObjectTypes.FieldReference: |
|
{ |
|
obj = mStack[objRef->Value]; |
|
int idx = objRef->ValueLow; |
|
if (obj is ILTypeInstance) |
|
{ |
|
((ILTypeInstance)obj).AssignFromStack(idx, val, AppDomain, mStack); |
|
} |
|
else |
|
{ |
|
var t = AppDomain.GetType(ip->TokenInteger); |
|
if (!((CLRType)t).AssignFieldFromStack(idx, ref obj, this, val, mStack)) |
|
((CLRType)t).SetFieldValue(idx, ref obj, t.TypeForCLR.CheckCLRTypes(StackObject.ToObject(val, AppDomain, mStack))); |
|
} |
|
} |
|
break; |
|
case ObjectTypes.StaticFieldReference: |
|
{ |
|
var t = AppDomain.GetType(objRef->Value); |
|
if (t is ILType) |
|
{ |
|
((ILType)t).StaticInstance.AssignFromStack(objRef->ValueLow, val, AppDomain, mStack); |
|
} |
|
else |
|
{ |
|
obj = null; |
|
if (!((CLRType)t).AssignFieldFromStack(objRef->ValueLow, ref obj, this, val, mStack)) |
|
((CLRType)t).SetStaticFieldValue(objRef->ValueLow, t.TypeForCLR.CheckCLRTypes(StackObject.ToObject(val, AppDomain, mStack))); |
|
} |
|
} |
|
break; |
|
default: |
|
throw new NotImplementedException(); |
|
} |
|
Free(esp - 1); |
|
Free(esp - 1 - 1); |
|
esp = esp - 1 - 1; |
|
} |
|
break; |
|
#endregion |
|
|
|
#region Load Constants |
|
case OpCodeEnum.Ldc_I4_M1: |
|
esp->Value = -1; |
|
esp->ObjectType = ObjectTypes.Integer; |
|
esp++; |
|
break; |
|
case OpCodeEnum.Ldc_I4_0: |
|
esp->Value = 0; |
|
esp->ObjectType = ObjectTypes.Integer; |
|
esp++; |
|
break; |
|
case OpCodeEnum.Ldc_I4_1: |
|
esp->Value = 1; |
|
esp->ObjectType = ObjectTypes.Integer; |
|
esp++; |
|
break; |
|
case OpCodeEnum.Ldc_I4_2: |
|
esp->Value = 2; |
|
esp->ObjectType = ObjectTypes.Integer; |
|
esp++; |
|
break; |
|
case OpCodeEnum.Ldc_I4_3: |
|
esp->Value = 3; |
|
esp->ObjectType = ObjectTypes.Integer; |
|
esp++; |
|
break; |
|
case OpCodeEnum.Ldc_I4_4: |
|
esp->Value = 4; |
|
esp->ObjectType = ObjectTypes.Integer; |
|
esp++; |
|
break; |
|
case OpCodeEnum.Ldc_I4_5: |
|
esp->Value = 5; |
|
esp->ObjectType = ObjectTypes.Integer; |
|
esp++; |
|
break; |
|
case OpCodeEnum.Ldc_I4_6: |
|
esp->Value = 6; |
|
esp->ObjectType = ObjectTypes.Integer; |
|
esp++; |
|
break; |
|
case OpCodeEnum.Ldc_I4_7: |
|
esp->Value = 7; |
|
esp->ObjectType = ObjectTypes.Integer; |
|
esp++; |
|
break; |
|
case OpCodeEnum.Ldc_I4_8: |
|
esp->Value = 8; |
|
esp->ObjectType = ObjectTypes.Integer; |
|
esp++; |
|
break; |
|
case OpCodeEnum.Ldc_I4: |
|
case OpCodeEnum.Ldc_I4_S: |
|
esp->Value = ip->TokenInteger; |
|
esp->ObjectType = ObjectTypes.Integer; |
|
esp++; |
|
break; |
|
case OpCodeEnum.Ldc_I8: |
|
{ |
|
*(long*)(&esp->Value) = ip->TokenLong; |
|
esp->ObjectType = ObjectTypes.Long; |
|
esp++; |
|
} |
|
break; |
|
case OpCodeEnum.Ldc_R4: |
|
{ |
|
*(float*)(&esp->Value) = *(float*)&ip->TokenInteger; |
|
esp->ObjectType = ObjectTypes.Float; |
|
esp++; |
|
} |
|
break; |
|
case OpCodeEnum.Ldc_R8: |
|
{ |
|
*(double*)(&esp->Value) = *(double*)&ip->TokenLong; |
|
esp->ObjectType = ObjectTypes.Double; |
|
esp++; |
|
} |
|
break; |
|
case OpCodeEnum.Ldnull: |
|
{ |
|
esp = PushNull(esp); |
|
} |
|
break; |
|
case OpCodeEnum.Ldind_I: |
|
case OpCodeEnum.Ldind_I1: |
|
case OpCodeEnum.Ldind_I2: |
|
case OpCodeEnum.Ldind_I4: |
|
case OpCodeEnum.Ldind_U1: |
|
case OpCodeEnum.Ldind_U2: |
|
case OpCodeEnum.Ldind_U4: |
|
{ |
|
val = GetObjectAndResolveReference(esp - 1); |
|
dst = esp - 1; |
|
switch (val->ObjectType) |
|
{ |
|
case ObjectTypes.FieldReference: |
|
{ |
|
var instance = mStack[val->Value]; |
|
var idx = val->ValueLow; |
|
Free(dst); |
|
LoadFromFieldReference(instance, idx, dst, mStack); |
|
} |
|
break; |
|
case ObjectTypes.ArrayReference: |
|
{ |
|
var instance = mStack[val->Value]; |
|
var idx = val->ValueLow; |
|
Free(dst); |
|
LoadFromArrayReference(instance, idx, dst, instance.GetType().GetElementType(), mStack); |
|
} |
|
break; |
|
case ObjectTypes.StaticFieldReference: |
|
{ |
|
var t = AppDomain.GetType(val->Value); |
|
int idx = val->ValueLow; |
|
Free(dst); |
|
if (t is ILType) |
|
{ |
|
((ILType)t).StaticInstance.PushToStack(idx, dst, this, mStack); |
|
} |
|
else |
|
{ |
|
if (!((CLRType)t).CopyFieldToStack(idx, null, this, ref dst, mStack)) |
|
{ |
|
obj = ((CLRType)t).GetFieldValue(idx, null); |
|
PushObject(dst, mStack, obj); |
|
} |
|
} |
|
} |
|
break; |
|
default: |
|
{ |
|
dst->ObjectType = ObjectTypes.Integer; |
|
dst->Value = val->Value; |
|
dst->ValueLow = 0; |
|
} |
|
break; |
|
} |
|
} |
|
break; |
|
case OpCodeEnum.Ldind_I8: |
|
{ |
|
val = GetObjectAndResolveReference(esp - 1); |
|
dst = esp - 1; |
|
switch (val->ObjectType) |
|
{ |
|
case ObjectTypes.FieldReference: |
|
{ |
|
var instance = mStack[val->Value]; |
|
var idx = val->ValueLow; |
|
Free(dst); |
|
LoadFromFieldReference(instance, idx, dst, mStack); |
|
} |
|
break; |
|
case ObjectTypes.ArrayReference: |
|
{ |
|
var instance = mStack[val->Value]; |
|
var idx = val->ValueLow; |
|
Free(dst); |
|
LoadFromArrayReference(instance, idx, dst, instance.GetType().GetElementType(), mStack); |
|
} |
|
break; |
|
case ObjectTypes.StaticFieldReference: |
|
{ |
|
var t = AppDomain.GetType(val->Value); |
|
int idx = val->ValueLow; |
|
Free(dst); |
|
if (t is ILType) |
|
{ |
|
((ILType)t).StaticInstance.PushToStack(idx, dst, this, mStack); |
|
} |
|
else |
|
{ |
|
if (!((CLRType)t).CopyFieldToStack(idx, null, this, ref dst, mStack)) |
|
{ |
|
obj = ((CLRType)t).GetFieldValue(idx, null); |
|
PushObject(dst, mStack, obj); |
|
} |
|
} |
|
} |
|
break; |
|
default: |
|
{ |
|
*dst = *val; |
|
dst->ObjectType = ObjectTypes.Long; |
|
} |
|
break; |
|
} |
|
} |
|
break; |
|
case OpCodeEnum.Ldind_R4: |
|
{ |
|
val = GetObjectAndResolveReference(esp - 1); |
|
dst = esp - 1; |
|
switch (val->ObjectType) |
|
{ |
|
case ObjectTypes.FieldReference: |
|
{ |
|
var instance = mStack[val->Value]; |
|
var idx = val->ValueLow; |
|
Free(dst); |
|
LoadFromFieldReference(instance, idx, dst, mStack); |
|
} |
|
break; |
|
case ObjectTypes.ArrayReference: |
|
{ |
|
var instance = mStack[val->Value]; |
|
var idx = val->ValueLow; |
|
Free(dst); |
|
LoadFromArrayReference(instance, idx, dst, instance.GetType().GetElementType(), mStack); |
|
} |
|
break; |
|
case ObjectTypes.StaticFieldReference: |
|
{ |
|
var t = AppDomain.GetType(val->Value); |
|
int idx = val->ValueLow; |
|
Free(dst); |
|
if (t is ILType) |
|
{ |
|
((ILType)t).StaticInstance.PushToStack(idx, dst, this, mStack); |
|
} |
|
else |
|
{ |
|
if (!((CLRType)t).CopyFieldToStack(idx, null, this, ref dst, mStack)) |
|
{ |
|
obj = ((CLRType)t).GetFieldValue(idx, null); |
|
PushObject(dst, mStack, obj); |
|
} |
|
} |
|
} |
|
break; |
|
default: |
|
{ |
|
dst->ObjectType = ObjectTypes.Float; |
|
dst->Value = val->Value; |
|
dst->ValueLow = 0; |
|
} |
|
break; |
|
} |
|
} |
|
break; |
|
case OpCodeEnum.Ldind_R8: |
|
{ |
|
val = GetObjectAndResolveReference(esp - 1); |
|
dst = esp - 1; |
|
switch (val->ObjectType) |
|
{ |
|
case ObjectTypes.FieldReference: |
|
{ |
|
var instance = mStack[val->Value]; |
|
var idx = val->ValueLow; |
|
Free(dst); |
|
LoadFromFieldReference(instance, idx, dst, mStack); |
|
} |
|
break; |
|
case ObjectTypes.ArrayReference: |
|
{ |
|
var instance = mStack[val->Value]; |
|
var idx = val->ValueLow; |
|
Free(dst); |
|
LoadFromArrayReference(instance, idx, dst, instance.GetType().GetElementType(), mStack); |
|
} |
|
break; |
|
case ObjectTypes.StaticFieldReference: |
|
{ |
|
var t = AppDomain.GetType(val->Value); |
|
int idx = val->ValueLow; |
|
Free(dst); |
|
if (t is ILType) |
|
{ |
|
((ILType)t).StaticInstance.PushToStack(idx, dst, this, mStack); |
|
} |
|
else |
|
{ |
|
if (!((CLRType)t).CopyFieldToStack(idx, null, this, ref dst, mStack)) |
|
{ |
|
obj = ((CLRType)t).GetFieldValue(idx, null); |
|
PushObject(dst, mStack, obj); |
|
} |
|
} |
|
} |
|
break; |
|
default: |
|
{ |
|
*dst = *val; |
|
dst->ObjectType = ObjectTypes.Double; |
|
} |
|
break; |
|
} |
|
} |
|
break; |
|
case OpCodeEnum.Ldind_Ref: |
|
{ |
|
val = GetObjectAndResolveReference(esp - 1); |
|
dst = esp - 1; |
|
switch (val->ObjectType) |
|
{ |
|
case ObjectTypes.FieldReference: |
|
{ |
|
var instance = mStack[val->Value]; |
|
var idx = val->ValueLow; |
|
Free(dst); |
|
LoadFromFieldReference(instance, idx, dst, mStack); |
|
} |
|
break; |
|
case ObjectTypes.ArrayReference: |
|
{ |
|
var instance = mStack[val->Value]; |
|
var idx = val->ValueLow; |
|
Free(dst); |
|
LoadFromArrayReference(instance, idx, dst, instance.GetType().GetElementType(), mStack); |
|
} |
|
break; |
|
case ObjectTypes.StaticFieldReference: |
|
{ |
|
var t = AppDomain.GetType(val->Value); |
|
int idx = val->ValueLow; |
|
Free(dst); |
|
if (t is ILType) |
|
{ |
|
((ILType)t).StaticInstance.PushToStack(idx, dst, this, mStack); |
|
} |
|
else |
|
{ |
|
if (!((CLRType)t).CopyFieldToStack(idx, null, this, ref dst, mStack)) |
|
{ |
|
obj = ((CLRType)t).GetFieldValue(idx, null); |
|
PushObject(dst, mStack, obj); |
|
} |
|
} |
|
} |
|
break; |
|
default: |
|
{ |
|
dst->ObjectType = ObjectTypes.Object; |
|
dst->Value = mStack.Count; |
|
mStack.Add(mStack[val->Value]); |
|
} |
|
break; |
|
} |
|
} |
|
break; |
|
case OpCodeEnum.Stind_I: |
|
case OpCodeEnum.Stind_I1: |
|
case OpCodeEnum.Stind_I2: |
|
case OpCodeEnum.Stind_I4: |
|
case OpCodeEnum.Stind_R4: |
|
{ |
|
dst = GetObjectAndResolveReference(esp - 1 - 1); |
|
val = esp - 1; |
|
switch (dst->ObjectType) |
|
{ |
|
case ObjectTypes.FieldReference: |
|
{ |
|
obj = mStack[dst->Value]; |
|
StoreValueToFieldReference(ref obj, dst->ValueLow, val, mStack); |
|
mStack[dst->Value] = obj; |
|
} |
|
break; |
|
case ObjectTypes.ArrayReference: |
|
{ |
|
StoreValueToArrayReference(dst, val, mStack[dst->Value].GetType().GetElementType(), mStack); |
|
} |
|
break; |
|
case ObjectTypes.StaticFieldReference: |
|
{ |
|
type = AppDomain.GetType(dst->Value); |
|
int idx = dst->ValueLow; |
|
if (type != null) |
|
{ |
|
if (type is ILType) |
|
{ |
|
ILType t = type as ILType; |
|
t.StaticInstance.AssignFromStack(idx, val, AppDomain, mStack); |
|
} |
|
else |
|
{ |
|
CLRType t = type as CLRType; |
|
var f = t.GetField(idx); |
|
obj = null; |
|
if (!((CLRType)t).AssignFieldFromStack(idx, ref obj, this, val, mStack)) |
|
t.SetStaticFieldValue(idx, f.FieldType.CheckCLRTypes(CheckAndCloneValueType(StackObject.ToObject(val, domain, mStack), domain))); |
|
} |
|
} |
|
else |
|
throw new TypeLoadException(); |
|
} |
|
break; |
|
default: |
|
{ |
|
dst->Value = val->Value; |
|
} |
|
break; |
|
} |
|
Free(esp - 1); |
|
Free(esp - 1 - 1); |
|
esp = esp - 1 - 1; |
|
} |
|
break; |
|
case OpCodeEnum.Stind_I8: |
|
{ |
|
dst = GetObjectAndResolveReference(esp - 1 - 1); |
|
val = esp - 1; |
|
switch (dst->ObjectType) |
|
{ |
|
case ObjectTypes.FieldReference: |
|
{ |
|
obj = mStack[dst->Value]; |
|
StoreValueToFieldReference(ref obj, dst->ValueLow, val, mStack); |
|
mStack[dst->Value] = obj; |
|
} |
|
break; |
|
case ObjectTypes.ArrayReference: |
|
{ |
|
StoreValueToArrayReference(dst, val, typeof(long), mStack); |
|
} |
|
break; |
|
case ObjectTypes.StaticFieldReference: |
|
{ |
|
type = AppDomain.GetType(dst->Value); |
|
int idx = dst->ValueLow; |
|
if (type != null) |
|
{ |
|
if (type is ILType) |
|
{ |
|
ILType t = type as ILType; |
|
t.StaticInstance.AssignFromStack(idx, val, AppDomain, mStack); |
|
} |
|
else |
|
{ |
|
CLRType t = type as CLRType; |
|
obj = null; |
|
if (!((CLRType)t).AssignFieldFromStack(idx, ref obj, this, val, mStack)) |
|
t.SetStaticFieldValue(idx, typeof(long).CheckCLRTypes(CheckAndCloneValueType(StackObject.ToObject(val, domain, mStack), domain))); |
|
} |
|
} |
|
else |
|
throw new TypeLoadException(); |
|
} |
|
break; |
|
default: |
|
{ |
|
dst->Value = val->Value; |
|
dst->ValueLow = val->ValueLow; |
|
} |
|
break; |
|
} |
|
|
|
Free(esp - 1); |
|
Free(esp - 1 - 1); |
|
esp = esp - 1 - 1; |
|
} |
|
break; |
|
case OpCodeEnum.Stind_R8: |
|
{ |
|
dst = GetObjectAndResolveReference(esp - 1 - 1); |
|
val = esp - 1; |
|
switch (dst->ObjectType) |
|
{ |
|
case ObjectTypes.FieldReference: |
|
{ |
|
obj = mStack[dst->Value]; |
|
StoreValueToFieldReference(ref obj, dst->ValueLow, val, mStack); |
|
mStack[dst->Value] = obj; |
|
} |
|
break; |
|
case ObjectTypes.ArrayReference: |
|
{ |
|
StoreValueToArrayReference(dst, val, typeof(double), mStack); |
|
} |
|
break; |
|
case ObjectTypes.StaticFieldReference: |
|
{ |
|
type = AppDomain.GetType(dst->Value); |
|
int idx = dst->ValueLow; |
|
if (type != null) |
|
{ |
|
if (type is ILType) |
|
{ |
|
ILType t = type as ILType; |
|
t.StaticInstance.AssignFromStack(idx, val, AppDomain, mStack); |
|
} |
|
else |
|
{ |
|
CLRType t = type as CLRType; |
|
obj = null; |
|
if (!((CLRType)t).AssignFieldFromStack(idx, ref obj, this, val, mStack)) |
|
t.SetStaticFieldValue(idx, typeof(double).CheckCLRTypes(CheckAndCloneValueType(StackObject.ToObject(val, domain, mStack), domain))); |
|
} |
|
} |
|
else |
|
throw new TypeLoadException(); |
|
} |
|
break; |
|
default: |
|
{ |
|
dst->Value = val->Value; |
|
dst->ValueLow = val->ValueLow; |
|
} |
|
break; |
|
} |
|
|
|
Free(esp - 1); |
|
Free(esp - 1 - 1); |
|
esp = esp - 1 - 1; |
|
} |
|
break; |
|
case OpCodeEnum.Stind_Ref: |
|
{ |
|
dst = GetObjectAndResolveReference(esp - 1 - 1); |
|
val = esp - 1; |
|
switch (dst->ObjectType) |
|
{ |
|
case ObjectTypes.FieldReference: |
|
{ |
|
obj = mStack[dst->Value]; |
|
StoreValueToFieldReference(ref obj, dst->ValueLow, val, mStack); |
|
mStack[dst->Value] = obj; |
|
} |
|
break; |
|
case ObjectTypes.ArrayReference: |
|
{ |
|
StoreValueToArrayReference(dst, val, typeof(object), mStack); |
|
} |
|
break; |
|
case ObjectTypes.StaticFieldReference: |
|
{ |
|
type = AppDomain.GetType(dst->Value); |
|
int idx = dst->ValueLow; |
|
if (type != null) |
|
{ |
|
if (type is ILType) |
|
{ |
|
ILType t = type as ILType; |
|
t.StaticInstance.AssignFromStack(idx, val, AppDomain, mStack); |
|
} |
|
else |
|
{ |
|
CLRType t = type as CLRType; |
|
var f = t.GetField(idx); |
|
obj = null; |
|
if (!((CLRType)t).AssignFieldFromStack(idx, ref obj, this, val, mStack)) |
|
t.SetStaticFieldValue(idx, f.FieldType.CheckCLRTypes(CheckAndCloneValueType(StackObject.ToObject(val, domain, mStack), domain))); |
|
} |
|
} |
|
else |
|
throw new TypeLoadException(); |
|
} |
|
break; |
|
default: |
|
{ |
|
switch (val->ObjectType) |
|
{ |
|
case ObjectTypes.Object: |
|
mStack[dst->Value] = mStack[val->Value]; |
|
break; |
|
case ObjectTypes.Null: |
|
mStack[dst->Value] = null; |
|
break; |
|
default: |
|
throw new NotImplementedException(); |
|
} |
|
} |
|
break; |
|
} |
|
|
|
Free(esp - 1); |
|
Free(esp - 1 - 1); |
|
esp = esp - 1 - 1; |
|
} |
|
break; |
|
case OpCodeEnum.Ldstr: |
|
esp = PushObject(esp, mStack, AppDomain.GetString(ip->TokenLong)); |
|
break; |
|
#endregion |
|
|
|
#region Althemetics |
|
case OpCodeEnum.Add: |
|
{ |
|
b = esp - 1; |
|
a = esp - 1 - 1; |
|
esp = a; |
|
switch (a->ObjectType) |
|
{ |
|
case ObjectTypes.Long: |
|
*((long*)&esp->Value) = *((long*)&a->Value) + *((long*)&b->Value); |
|
break; |
|
case ObjectTypes.Integer: |
|
esp->Value = a->Value + b->Value; |
|
break; |
|
case ObjectTypes.Float: |
|
*((float*)&esp->Value) = *((float*)&a->Value) + *((float*)&b->Value); |
|
break; |
|
case ObjectTypes.Double: |
|
*((double*)&esp->Value) = *((double*)&a->Value) + *((double*)&b->Value); |
|
break; |
|
default: |
|
throw new NotImplementedException(); |
|
} |
|
esp++; |
|
} |
|
break; |
|
case OpCodeEnum.Sub: |
|
{ |
|
b = esp - 1; |
|
a = esp - 1 - 1; |
|
esp = a; |
|
switch (a->ObjectType) |
|
{ |
|
case ObjectTypes.Long: |
|
*((long*)&esp->Value) = *((long*)&a->Value) - *((long*)&b->Value); |
|
break; |
|
case ObjectTypes.Integer: |
|
esp->Value = a->Value - b->Value; |
|
break; |
|
case ObjectTypes.Float: |
|
*((float*)&esp->Value) = *((float*)&a->Value) - *((float*)&b->Value); |
|
break; |
|
case ObjectTypes.Double: |
|
*((double*)&esp->Value) = *((double*)&a->Value) - *((double*)&b->Value); |
|
break; |
|
default: |
|
throw new NotImplementedException(); |
|
} |
|
esp++; |
|
} |
|
break; |
|
case OpCodeEnum.Mul: |
|
{ |
|
b = esp - 1; |
|
a = esp - 1 - 1; |
|
esp = a; |
|
switch (a->ObjectType) |
|
{ |
|
case ObjectTypes.Long: |
|
*((long*)&esp->Value) = *((long*)&a->Value) * *((long*)&b->Value); |
|
break; |
|
case ObjectTypes.Integer: |
|
esp->Value = a->Value * b->Value; |
|
break; |
|
case ObjectTypes.Float: |
|
*((float*)&esp->Value) = *((float*)&a->Value) * *((float*)&b->Value); |
|
break; |
|
case ObjectTypes.Double: |
|
*((double*)&esp->Value) = *((double*)&a->Value) * *((double*)&b->Value); |
|
break; |
|
default: |
|
throw new NotImplementedException(); |
|
} |
|
esp++; |
|
} |
|
break; |
|
case OpCodeEnum.Div: |
|
{ |
|
b = esp - 1; |
|
a = esp - 1 - 1; |
|
esp = a; |
|
switch (a->ObjectType) |
|
{ |
|
case ObjectTypes.Long: |
|
*((long*)&esp->Value) = *((long*)&a->Value) / *((long*)&b->Value); |
|
break; |
|
case ObjectTypes.Integer: |
|
esp->Value = a->Value / b->Value; |
|
break; |
|
case ObjectTypes.Float: |
|
*((float*)&esp->Value) = *((float*)&a->Value) / *((float*)&b->Value); |
|
break; |
|
case ObjectTypes.Double: |
|
*((double*)&esp->Value) = *((double*)&a->Value) / *((double*)&b->Value); |
|
break; |
|
default: |
|
throw new NotImplementedException(); |
|
} |
|
esp++; |
|
} |
|
break; |
|
case OpCodeEnum.Div_Un: |
|
{ |
|
b = esp - 1; |
|
a = esp - 1 - 1; |
|
esp = a; |
|
switch (a->ObjectType) |
|
{ |
|
case ObjectTypes.Long: |
|
*((ulong*)&esp->Value) = *((ulong*)&a->Value) / *((ulong*)&b->Value); |
|
break; |
|
case ObjectTypes.Integer: |
|
esp->Value = (int)((uint)a->Value / (uint)b->Value); |
|
break; |
|
default: |
|
throw new NotImplementedException(); |
|
} |
|
esp++; |
|
} |
|
break; |
|
case OpCodeEnum.Rem: |
|
{ |
|
b = esp - 1; |
|
a = esp - 1 - 1; |
|
esp = a; |
|
switch (a->ObjectType) |
|
{ |
|
case ObjectTypes.Long: |
|
*((long*)&esp->Value) = *((long*)&a->Value) % *((long*)&b->Value); |
|
break; |
|
case ObjectTypes.Integer: |
|
esp->Value = a->Value % b->Value; |
|
break; |
|
case ObjectTypes.Float: |
|
*(float*)&esp->Value = *(float*)&a->Value % *(float*)&b->Value; |
|
break; |
|
case ObjectTypes.Double: |
|
*(double*)&esp->Value = *(double*)&a->Value % *(double*)&b->Value; |
|
break; |
|
default: |
|
throw new NotImplementedException(); |
|
} |
|
esp++; |
|
} |
|
break; |
|
case OpCodeEnum.Rem_Un: |
|
{ |
|
b = esp - 1; |
|
a = esp - 1 - 1; |
|
esp = a; |
|
switch (a->ObjectType) |
|
{ |
|
case ObjectTypes.Long: |
|
*((ulong*)&esp->Value) = *((ulong*)&a->Value) % *((ulong*)&b->Value); |
|
break; |
|
case ObjectTypes.Integer: |
|
esp->Value = (int)((uint)a->Value % (uint)b->Value); |
|
break; |
|
default: |
|
throw new NotImplementedException(); |
|
} |
|
esp++; |
|
} |
|
break; |
|
case OpCodeEnum.Xor: |
|
{ |
|
b = esp - 1; |
|
a = esp - 1 - 1; |
|
esp = a; |
|
switch (a->ObjectType) |
|
{ |
|
case ObjectTypes.Long: |
|
*((long*)&esp->Value) = *((long*)&a->Value) ^ *((long*)&b->Value); |
|
break; |
|
case ObjectTypes.Integer: |
|
esp->Value = a->Value ^ b->Value; |
|
break; |
|
default: |
|
throw new NotImplementedException(); |
|
} |
|
esp++; |
|
} |
|
break; |
|
case OpCodeEnum.And: |
|
{ |
|
b = esp - 1; |
|
a = esp - 1 - 1; |
|
esp = a; |
|
switch (a->ObjectType) |
|
{ |
|
case ObjectTypes.Long: |
|
*((long*)&esp->Value) = *((long*)&a->Value) & *((long*)&b->Value); |
|
break; |
|
case ObjectTypes.Integer: |
|
esp->Value = a->Value & b->Value; |
|
break; |
|
default: |
|
throw new NotImplementedException(); |
|
} |
|
esp++; |
|
} |
|
break; |
|
case OpCodeEnum.Or: |
|
{ |
|
b = esp - 1; |
|
a = esp - 1 - 1; |
|
esp = a; |
|
switch (a->ObjectType) |
|
{ |
|
case ObjectTypes.Long: |
|
*((long*)&esp->Value) = *((long*)&a->Value) | *((long*)&b->Value); |
|
break; |
|
case ObjectTypes.Integer: |
|
esp->Value = a->Value | b->Value; |
|
break; |
|
default: |
|
throw new NotImplementedException(); |
|
} |
|
esp++; |
|
} |
|
break; |
|
case OpCodeEnum.Shl: |
|
{ |
|
b = esp - 1; |
|
a = esp - 1 - 1; |
|
esp = a; |
|
int bits = b->Value; |
|
switch (a->ObjectType) |
|
{ |
|
case ObjectTypes.Long: |
|
*((long*)&esp->Value) = *((long*)&a->Value) << bits; |
|
break; |
|
case ObjectTypes.Integer: |
|
esp->Value = a->Value << bits; |
|
break; |
|
default: |
|
throw new NotImplementedException(); |
|
} |
|
esp++; |
|
} |
|
break; |
|
case OpCodeEnum.Shr: |
|
{ |
|
b = esp - 1; |
|
a = esp - 1 - 1; |
|
esp = a; |
|
int bits = b->Value; |
|
switch (a->ObjectType) |
|
{ |
|
case ObjectTypes.Long: |
|
*((long*)&esp->Value) = *((long*)&a->Value) >> bits; |
|
break; |
|
case ObjectTypes.Integer: |
|
esp->Value = a->Value >> bits; |
|
break; |
|
default: |
|
throw new NotImplementedException(); |
|
} |
|
esp++; |
|
} |
|
break; |
|
case OpCodeEnum.Shr_Un: |
|
{ |
|
b = esp - 1; |
|
a = esp - 1 - 1; |
|
esp = a; |
|
int bits = b->Value; |
|
switch (a->ObjectType) |
|
{ |
|
case ObjectTypes.Long: |
|
*((ulong*)&esp->Value) = *((ulong*)&a->Value) >> bits; |
|
break; |
|
case ObjectTypes.Integer: |
|
*(uint*)&esp->Value = (uint)a->Value >> bits; |
|
break; |
|
default: |
|
throw new NotImplementedException(); |
|
} |
|
esp++; |
|
} |
|
break; |
|
case OpCodeEnum.Not: |
|
{ |
|
a = esp - 1; |
|
switch (a->ObjectType) |
|
{ |
|
case ObjectTypes.Long: |
|
*((long*)&a->Value) = ~*((long*)&a->Value); |
|
break; |
|
case ObjectTypes.Integer: |
|
a->Value = ~a->Value; |
|
break; |
|
default: |
|
throw new NotImplementedException(); |
|
} |
|
} |
|
break; |
|
case OpCodeEnum.Neg: |
|
{ |
|
a = esp - 1; |
|
switch (a->ObjectType) |
|
{ |
|
case ObjectTypes.Long: |
|
*((long*)&a->Value) = -*((long*)&a->Value); |
|
break; |
|
case ObjectTypes.Integer: |
|
a->Value = -a->Value; |
|
break; |
|
case ObjectTypes.Float: |
|
*((float*)&a->Value) = -*((float*)&a->Value); |
|
break; |
|
case ObjectTypes.Double: |
|
*((double*)&a->Value) = -*((double*)&a->Value); |
|
break; |
|
default: |
|
throw new NotImplementedException(); |
|
} |
|
} |
|
break; |
|
#endregion |
|
|
|
#region Control Flows |
|
case OpCodeEnum.Ret: |
|
returned = true; |
|
break; |
|
case OpCodeEnum.Brtrue: |
|
case OpCodeEnum.Brtrue_S: |
|
{ |
|
esp--; |
|
bool res = false; |
|
switch (esp->ObjectType) |
|
{ |
|
case ObjectTypes.Integer: |
|
res = esp->Value != 0; |
|
break; |
|
case ObjectTypes.Long: |
|
res = *(long*)&esp->Value != 0; |
|
break; |
|
case ObjectTypes.Object: |
|
res = mStack[esp->Value] != null; |
|
break; |
|
} |
|
if (res) |
|
{ |
|
ip = ptr + ip->TokenInteger; |
|
Free(esp); |
|
continue; |
|
} |
|
else |
|
Free(esp); |
|
} |
|
break; |
|
case OpCodeEnum.Brfalse: |
|
case OpCodeEnum.Brfalse_S: |
|
{ |
|
esp--; |
|
bool res = false; |
|
switch (esp->ObjectType) |
|
{ |
|
case ObjectTypes.Null: |
|
res = true; |
|
break; |
|
case ObjectTypes.Integer: |
|
res = esp->Value == 0; |
|
break; |
|
case ObjectTypes.Long: |
|
res = *(long*)&esp->Value == 0; |
|
break; |
|
case ObjectTypes.Object: |
|
res = mStack[esp->Value] == null; |
|
Free(esp); |
|
break; |
|
default: |
|
Free(esp); |
|
break; |
|
} |
|
if (res) |
|
{ |
|
ip = ptr + ip->TokenInteger; |
|
continue; |
|
} |
|
} |
|
break; |
|
case OpCodeEnum.Beq: |
|
case OpCodeEnum.Beq_S: |
|
{ |
|
b = esp - 1; |
|
a = esp - 1 - 1; |
|
bool transfer = false; |
|
if (a->ObjectType == b->ObjectType) |
|
{ |
|
switch (a->ObjectType) |
|
{ |
|
case ObjectTypes.Null: |
|
transfer = true; |
|
break; |
|
case ObjectTypes.Integer: |
|
transfer = a->Value == b->Value; |
|
break; |
|
case ObjectTypes.Long: |
|
transfer = *(long*)&a->Value == *(long*)&b->Value; |
|
break; |
|
case ObjectTypes.Float: |
|
transfer = *(float*)&a->Value == *(float*)&b->Value; |
|
break; |
|
case ObjectTypes.Double: |
|
transfer = *(double*)&a->Value == *(double*)&b->Value; |
|
break; |
|
case ObjectTypes.Object: |
|
transfer = mStack[a->Value] == mStack[b->Value]; |
|
break; |
|
default: |
|
throw new NotImplementedException(); |
|
} |
|
} |
|
Free(esp - 1); |
|
Free(esp - 1 - 1); |
|
esp = esp - 1 - 1; |
|
if (transfer) |
|
{ |
|
ip = ptr + ip->TokenInteger; |
|
continue; |
|
} |
|
|
|
} |
|
break; |
|
case OpCodeEnum.Bne_Un: |
|
case OpCodeEnum.Bne_Un_S: |
|
{ |
|
b = esp - 1; |
|
a = esp - 1 - 1; |
|
bool transfer = false; |
|
if (a->ObjectType == b->ObjectType) |
|
{ |
|
switch (a->ObjectType) |
|
{ |
|
case ObjectTypes.Null: |
|
transfer = false; |
|
break; |
|
case ObjectTypes.Integer: |
|
transfer = (uint)a->Value != (uint)b->Value; |
|
break; |
|
case ObjectTypes.Float: |
|
transfer = *(float*)&a->Value != *(float*)&b->Value; |
|
break; |
|
case ObjectTypes.Long: |
|
transfer = *(long*)&a->Value != *(long*)&b->Value; |
|
break; |
|
case ObjectTypes.Double: |
|
transfer = *(double*)&a->Value != *(double*)&b->Value; |
|
break; |
|
case ObjectTypes.Object: |
|
transfer = mStack[a->Value] != mStack[b->Value]; |
|
break; |
|
default: |
|
throw new NotImplementedException(); |
|
} |
|
} |
|
else |
|
transfer = true; |
|
Free(esp - 1); |
|
Free(esp - 1 - 1); |
|
esp = esp - 1 - 1; |
|
if (transfer) |
|
{ |
|
ip = ptr + ip->TokenInteger; |
|
continue; |
|
} |
|
|
|
} |
|
break; |
|
case OpCodeEnum.Bgt: |
|
case OpCodeEnum.Bgt_S: |
|
{ |
|
b = esp - 1; |
|
a = esp - 1 - 1; |
|
esp = esp - 1 - 1; |
|
bool transfer = false; |
|
switch (esp->ObjectType) |
|
{ |
|
case ObjectTypes.Integer: |
|
transfer = a->Value > b->Value; |
|
break; |
|
case ObjectTypes.Long: |
|
transfer = *(long*)&a->Value > *(long*)&b->Value; |
|
break; |
|
case ObjectTypes.Float: |
|
transfer = *(float*)&a->Value > *(float*)&b->Value; |
|
break; |
|
case ObjectTypes.Double: |
|
transfer = *(double*)&a->Value > *(double*)&b->Value; |
|
break; |
|
default: |
|
throw new NotImplementedException(); |
|
} |
|
|
|
if (transfer) |
|
{ |
|
ip = ptr + ip->TokenInteger; |
|
continue; |
|
} |
|
|
|
} |
|
break; |
|
case OpCodeEnum.Bgt_Un: |
|
case OpCodeEnum.Bgt_Un_S: |
|
{ |
|
b = esp - 1; |
|
a = esp - 1 - 1; |
|
esp = esp - 1 - 1; |
|
bool transfer = false; |
|
switch (esp->ObjectType) |
|
{ |
|
case ObjectTypes.Integer: |
|
transfer = (uint)a->Value > (uint)b->Value; |
|
break; |
|
case ObjectTypes.Long: |
|
transfer = *(ulong*)&a->Value > *(ulong*)&b->Value; |
|
break; |
|
case ObjectTypes.Float: |
|
transfer = *(float*)&a->Value > *(float*)&b->Value; |
|
break; |
|
case ObjectTypes.Double: |
|
transfer = *(double*)&a->Value > *(double*)&b->Value; |
|
break; |
|
default: |
|
throw new NotImplementedException(); |
|
} |
|
|
|
if (transfer) |
|
{ |
|
ip = ptr + ip->TokenInteger; |
|
continue; |
|
} |
|
|
|
} |
|
break; |
|
case OpCodeEnum.Bge: |
|
case OpCodeEnum.Bge_S: |
|
{ |
|
b = esp - 1; |
|
a = esp - 1 - 1; |
|
esp = esp - 1 - 1; |
|
bool transfer = false; |
|
switch (esp->ObjectType) |
|
{ |
|
case ObjectTypes.Integer: |
|
transfer = a->Value >= b->Value; |
|
break; |
|
case ObjectTypes.Long: |
|
transfer = *(long*)&a->Value >= *(long*)&b->Value; |
|
break; |
|
case ObjectTypes.Float: |
|
transfer = *(float*)&a->Value >= *(float*)&b->Value; |
|
break; |
|
case ObjectTypes.Double: |
|
transfer = *(double*)&a->Value >= *(double*)&b->Value; |
|
break; |
|
|
|
default: |
|
throw new NotImplementedException(); |
|
} |
|
|
|
if (transfer) |
|
{ |
|
ip = ptr + ip->TokenInteger; |
|
continue; |
|
} |
|
|
|
} |
|
break; |
|
case OpCodeEnum.Bge_Un: |
|
case OpCodeEnum.Bge_Un_S: |
|
{ |
|
b = esp - 1; |
|
a = esp - 1 - 1; |
|
esp = esp - 1 - 1; |
|
bool transfer = false; |
|
switch (esp->ObjectType) |
|
{ |
|
case ObjectTypes.Integer: |
|
transfer = (uint)a->Value >= (uint)b->Value; |
|
break; |
|
case ObjectTypes.Long: |
|
transfer = *(ulong*)&a->Value >= *(ulong*)&b->Value; |
|
break; |
|
case ObjectTypes.Float: |
|
transfer = *(float*)&a->Value >= *(float*)&b->Value; |
|
break; |
|
case ObjectTypes.Double: |
|
transfer = *(double*)&a->Value >= *(double*)&b->Value; |
|
break; |
|
default: |
|
throw new NotImplementedException(); |
|
} |
|
|
|
if (transfer) |
|
{ |
|
ip = ptr + ip->TokenInteger; |
|
continue; |
|
} |
|
|
|
} |
|
break; |
|
case OpCodeEnum.Blt: |
|
case OpCodeEnum.Blt_S: |
|
{ |
|
b = esp - 1; |
|
a = esp - 1 - 1; |
|
esp = esp - 1 - 1; |
|
bool transfer = false; |
|
switch (esp->ObjectType) |
|
{ |
|
case ObjectTypes.Integer: |
|
transfer = a->Value < b->Value; |
|
break; |
|
case ObjectTypes.Long: |
|
transfer = *(long*)&a->Value < *(long*)&b->Value; |
|
break; |
|
case ObjectTypes.Float: |
|
transfer = *(float*)&a->Value < *(float*)&b->Value; |
|
break; |
|
case ObjectTypes.Double: |
|
transfer = *(double*)&a->Value < *(double*)&b->Value; |
|
break; |
|
default: |
|
throw new NotImplementedException(); |
|
} |
|
|
|
if (transfer) |
|
{ |
|
ip = ptr + ip->TokenInteger; |
|
continue; |
|
} |
|
|
|
} |
|
break; |
|
case OpCodeEnum.Blt_Un: |
|
case OpCodeEnum.Blt_Un_S: |
|
{ |
|
b = esp - 1; |
|
a = esp - 1 - 1; |
|
esp = esp - 1 - 1; |
|
bool transfer = false; |
|
switch (esp->ObjectType) |
|
{ |
|
case ObjectTypes.Integer: |
|
transfer = (uint)a->Value < (uint)b->Value; |
|
break; |
|
case ObjectTypes.Long: |
|
transfer = *(ulong*)&a->Value < *(ulong*)&b->Value; |
|
break; |
|
case ObjectTypes.Float: |
|
transfer = *(float*)&a->Value < *(float*)&b->Value; |
|
break; |
|
case ObjectTypes.Double: |
|
transfer = *(double*)&a->Value < *(double*)&b->Value; |
|
break; |
|
default: |
|
throw new NotImplementedException(); |
|
} |
|
|
|
if (transfer) |
|
{ |
|
ip = ptr + ip->TokenInteger; |
|
continue; |
|
} |
|
|
|
} |
|
break; |
|
case OpCodeEnum.Ble: |
|
case OpCodeEnum.Ble_S: |
|
{ |
|
b = esp - 1; |
|
a = esp - 1 - 1; |
|
esp = esp - 1 - 1; |
|
bool transfer = false; |
|
switch (esp->ObjectType) |
|
{ |
|
case ObjectTypes.Integer: |
|
transfer = a->Value <= b->Value; |
|
break; |
|
case ObjectTypes.Long: |
|
transfer = *(long*)&a->Value <= *(long*)&b->Value; |
|
break; |
|
case ObjectTypes.Float: |
|
transfer = *(float*)&a->Value <= *(float*)&b->Value; |
|
break; |
|
case ObjectTypes.Double: |
|
transfer = *(double*)&a->Value <= *(double*)&b->Value; |
|
break; |
|
default: |
|
throw new NotImplementedException(); |
|
} |
|
|
|
if (transfer) |
|
{ |
|
ip = ptr + ip->TokenInteger; |
|
continue; |
|
} |
|
|
|
} |
|
break; |
|
case OpCodeEnum.Ble_Un: |
|
case OpCodeEnum.Ble_Un_S: |
|
{ |
|
b = esp - 1; |
|
a = esp - 1 - 1; |
|
esp = esp - 1 - 1; |
|
bool transfer = false; |
|
switch (esp->ObjectType) |
|
{ |
|
case ObjectTypes.Integer: |
|
transfer = (uint)a->Value <= (uint)b->Value; |
|
break; |
|
case ObjectTypes.Long: |
|
transfer = *(ulong*)&a->Value <= *(ulong*)&b->Value; |
|
break; |
|
case ObjectTypes.Float: |
|
transfer = *(float*)&a->Value <= *(float*)&b->Value; |
|
break; |
|
case ObjectTypes.Double: |
|
transfer = *(double*)&a->Value <= *(double*)&b->Value; |
|
break; |
|
default: |
|
throw new NotImplementedException(); |
|
} |
|
|
|
if (transfer) |
|
{ |
|
ip = ptr + ip->TokenInteger; |
|
continue; |
|
} |
|
|
|
} |
|
break; |
|
case OpCodeEnum.Br_S: |
|
case OpCodeEnum.Br: |
|
ip = ptr + ip->TokenInteger; |
|
continue; |
|
case OpCodeEnum.Switch: |
|
{ |
|
intVal = (esp - 1)->Value; |
|
Free(esp - 1); |
|
esp--; |
|
var table = method.JumpTables[ip->TokenInteger]; |
|
if (intVal >= 0 && intVal < table.Length) |
|
{ |
|
ip = ptr + table[intVal]; |
|
continue; |
|
} |
|
} |
|
break; |
|
case OpCodeEnum.Leave: |
|
case OpCodeEnum.Leave_S: |
|
{ |
|
if (ehs != null) |
|
{ |
|
ExceptionHandler eh = null; |
|
|
|
int addr = (int)(ip - ptr); |
|
eh = FindExceptionHandlerByBranchTarget(addr, ip->TokenInteger, ehs); |
|
if (eh != null) |
|
{ |
|
finallyEndAddress = ip->TokenInteger; |
|
ip = ptr + eh.HandlerStart; |
|
continue; |
|
} |
|
} |
|
ip = ptr + ip->TokenInteger; |
|
continue; |
|
} |
|
case OpCodeEnum.Endfinally: |
|
{ |
|
if (finallyEndAddress < 0) |
|
{ |
|
unhandledException = true; |
|
finallyEndAddress = 0; |
|
throw lastCaughtEx; |
|
} |
|
else |
|
{ |
|
ip = ptr + finallyEndAddress; |
|
finallyEndAddress = 0; |
|
continue; |
|
} |
|
} |
|
case OpCodeEnum.Call: |
|
case OpCodeEnum.Callvirt: |
|
{ |
|
IMethod m = domain.GetMethod(ip->TokenInteger); |
|
if (m == null) |
|
{ |
|
//Irrelevant method |
|
int cnt = (int)ip->TokenLong; |
|
//Balance the stack |
|
for (int i = 0; i < cnt; i++) |
|
{ |
|
Free(esp - 1); |
|
esp--; |
|
} |
|
} |
|
else |
|
{ |
|
if (m is ILMethod) |
|
{ |
|
ILMethod ilm = (ILMethod)m; |
|
bool processed = false; |
|
if (m.IsDelegateInvoke) |
|
{ |
|
var instance = StackObject.ToObject((Minus(esp, m.ParameterCount + 1)), domain, mStack); |
|
if (instance is IDelegateAdapter) |
|
{ |
|
esp = ((IDelegateAdapter)instance).ILInvoke(this, esp, mStack); |
|
processed = true; |
|
} |
|
} |
|
if (!processed) |
|
{ |
|
if (code == OpCodeEnum.Callvirt) |
|
{ |
|
objRef = GetObjectAndResolveReference(Minus(esp, ilm.ParameterCount + 1)); |
|
if (objRef->ObjectType == ObjectTypes.Null) |
|
throw new NullReferenceException(); |
|
if (objRef->ObjectType == ObjectTypes.ValueTypeObjectReference) |
|
{ |
|
dst = ILIntepreter.ResolveReference(objRef); |
|
var ft = domain.GetTypeByIndex(dst->Value) as ILType; |
|
ilm = ft.GetVirtualMethod(ilm) as ILMethod; |
|
} |
|
else |
|
{ |
|
obj = mStack[objRef->Value]; |
|
if (obj == null) |
|
throw new NullReferenceException(); |
|
ilm = ((ILTypeInstance)obj).Type.GetVirtualMethod(ilm) as ILMethod; |
|
} |
|
} |
|
if (ilm.ShouldUseRegisterVM) |
|
{ |
|
PrepareRegisterCallStack(esp, mStack, ilm); |
|
esp = ExecuteR(ilm, esp, out unhandledException); |
|
} |
|
else |
|
esp = Execute(ilm, esp, out unhandledException); |
|
ValueTypeBasePointer = bp; |
|
if (unhandledException) |
|
returned = true; |
|
} |
|
} |
|
else |
|
{ |
|
CLRMethod cm = (CLRMethod)m; |
|
bool processed = false; |
|
if (cm.IsDelegateInvoke) |
|
{ |
|
var instance = StackObject.ToObject((Minus(esp, cm.ParameterCount + 1)), domain, mStack); |
|
if (instance is IDelegateAdapter) |
|
{ |
|
if (cm.IsDelegateDynamicInvoke) |
|
{ |
|
arrRef = esp - 1; |
|
object[] objArr = StackObject.ToObject(arrRef, domain, mStack) as object[]; |
|
Free(arrRef); |
|
if (objArr != null) |
|
{ |
|
if (objArr.Length != cm.ParameterCount) |
|
throw new ArgumentException(string.Format("{0}.{1} has {2} arguments, but got {3}", cm.DeclearingType.FullName, cm.Name, cm.ParameterCount, objArr.Length)); |
|
esp = arrRef; |
|
for (intVal = 0; intVal < objArr.Length; intVal++) |
|
{ |
|
esp = PushObject(esp, mStack, objArr[intVal], cm.Parameters[intVal] == domain.ObjectType); |
|
} |
|
} |
|
} |
|
esp = ((IDelegateAdapter)instance).ILInvoke(this, esp, mStack); |
|
processed = true; |
|
} |
|
} |
|
|
|
if (!processed) |
|
{ |
|
var redirect = cm.Redirection; |
|
if (redirect != null) |
|
esp = redirect(this, esp, mStack, cm, false); |
|
else |
|
{ |
|
#if DEBUG && !DISABLE_ILRUNTIME_DEBUG |
|
if (!allowUnboundCLRMethod) |
|
throw new NotSupportedException(cm.ToString() + " is not bound!"); |
|
#endif |
|
#if DEBUG && !NO_PROFILER |
|
if (System.Threading.Thread.CurrentThread.ManagedThreadId == AppDomain.UnityMainThreadID) |
|
|
|
#if UNITY_5_5_OR_NEWER |
|
UnityEngine.Profiling.Profiler.BeginSample(cm.ToString()); |
|
#else |
|
UnityEngine.Profiler.BeginSample(cm.ToString()); |
|
#endif |
|
#endif |
|
object result = cm.Invoke(this, esp, mStack); |
|
#if DEBUG && !NO_PROFILER |
|
if (System.Threading.Thread.CurrentThread.ManagedThreadId == AppDomain.UnityMainThreadID) |
|
#if UNITY_5_5_OR_NEWER |
|
UnityEngine.Profiling.Profiler.EndSample(); |
|
#else |
|
UnityEngine.Profiler.EndSample(); |
|
#endif |
|
|
|
#endif |
|
if (result is CrossBindingAdaptorType) |
|
result = ((CrossBindingAdaptorType)result).ILInstance; |
|
int paramCount = cm.ParameterCount; |
|
for (int i = 1; i <= paramCount; i++) |
|
{ |
|
Free(Minus(esp, i)); |
|
} |
|
esp = Minus(esp, paramCount); |
|
if (cm.HasThis) |
|
{ |
|
Free(esp - 1); |
|
esp--; |
|
} |
|
if (cm.ReturnType != AppDomain.VoidType && !cm.IsConstructor) |
|
{ |
|
esp = PushObject(esp, mStack, result, cm.ReturnType.TypeForCLR == typeof(object)); |
|
} |
|
} |
|
} |
|
} |
|
|
|
} |
|
} |
|
break; |
|
#endregion |
|
|
|
#region FieldOperation |
|
case OpCodeEnum.Stfld: |
|
{ |
|
objRef = GetObjectAndResolveReference(esp - 1 - 1); |
|
if (objRef->ObjectType == ObjectTypes.ValueTypeObjectReference) |
|
{ |
|
dst = ILIntepreter.ResolveReference(objRef); |
|
var ft = domain.GetTypeByIndex(dst->Value); |
|
if (ft is ILType) |
|
CopyToValueTypeField(dst, (int)ip->TokenLong, esp - 1, mStack); |
|
else |
|
CopyToValueTypeField(dst, ((CLRType)ft).FieldIndexMapping[(int)ip->TokenLong], esp - 1, mStack); |
|
} |
|
else |
|
{ |
|
obj = RetriveObject(objRef, mStack); |
|
|
|
if (obj != null) |
|
{ |
|
ILTypeInstance instance = null; |
|
if (obj is ILTypeInstance) |
|
instance = obj as ILTypeInstance; |
|
else if (obj is CrossBindingAdaptorType) |
|
instance = (obj as CrossBindingAdaptorType).ILInstance; |
|
if (instance != null) |
|
{ |
|
val = esp - 1; |
|
instance.AssignFromStack((int)ip->TokenLong, val, AppDomain, mStack); |
|
} |
|
else |
|
{ |
|
var t = obj.GetType(); |
|
type = AppDomain.GetType((int)(ip->TokenLong >> 32)); |
|
if (type != null) |
|
{ |
|
val = esp - 1; |
|
var fieldToken = (int)ip->TokenLong; |
|
var f = ((CLRType)type).GetField(fieldToken); |
|
if (!((CLRType)type).AssignFieldFromStack(fieldToken, ref obj, this, val, mStack)) |
|
((CLRType)type).SetFieldValue(fieldToken, ref obj, f.FieldType.CheckCLRTypes(CheckAndCloneValueType(StackObject.ToObject(val, domain, mStack), domain))); |
|
//Writeback |
|
if (t.IsValueType) |
|
{ |
|
switch (objRef->ObjectType) |
|
{ |
|
case ObjectTypes.Object: |
|
mStack[objRef->Value] = obj; |
|
break; |
|
case ObjectTypes.FieldReference: |
|
{ |
|
var oldObj = mStack[objRef->Value]; |
|
int idx = objRef->ValueLow; |
|
if (oldObj is ILTypeInstance) |
|
{ |
|
((ILTypeInstance)oldObj)[idx] = obj; |
|
} |
|
else |
|
{ |
|
var it = AppDomain.GetType(oldObj.GetType()); |
|
((CLRType)it).SetFieldValue(idx, ref oldObj, obj); |
|
} |
|
} |
|
break; |
|
case ObjectTypes.ArrayReference: |
|
{ |
|
var arr = mStack[objRef->Value] as Array; |
|
int idx = objRef->ValueLow; |
|
arr.SetValue(obj, idx); |
|
} |
|
break; |
|
case ObjectTypes.StaticFieldReference: |
|
{ |
|
var it = AppDomain.GetType(objRef->Value); |
|
int idx = objRef->ValueLow; |
|
if (it is ILType) |
|
{ |
|
((ILType)it).StaticInstance[idx] = obj; |
|
} |
|
else |
|
{ |
|
((CLRType)it).SetStaticFieldValue(idx, obj); |
|
} |
|
} |
|
break; |
|
case ObjectTypes.ValueTypeObjectReference: |
|
{ |
|
dst = ILIntepreter.ResolveReference(objRef); |
|
var ct = domain.GetTypeByIndex(dst->Value) as CLRType; |
|
var binder = ct.ValueTypeBinder; |
|
binder.CopyValueTypeToStack(obj, dst, mStack); |
|
} |
|
break; |
|
default: |
|
throw new NotImplementedException(); |
|
} |
|
} |
|
} |
|
else |
|
throw new TypeLoadException(); |
|
} |
|
} |
|
else |
|
throw new NullReferenceException(); |
|
} |
|
Free(esp - 1); |
|
Free(esp - 1 - 1); |
|
esp = esp - 1 - 1; |
|
} |
|
break; |
|
case OpCodeEnum.Ldfld: |
|
{ |
|
var ret = esp - 1; |
|
objRef = GetObjectAndResolveReference(ret); |
|
if (objRef->ObjectType == ObjectTypes.ValueTypeObjectReference) |
|
{ |
|
dst = ILIntepreter.ResolveReference(objRef); |
|
var ft = domain.GetTypeByIndex(dst->Value); |
|
if (ft is ILType) |
|
val = Minus(dst, (int)ip->TokenLong + 1); |
|
else |
|
val = Minus(dst, ((CLRType)ft).FieldIndexMapping[(int)ip->TokenLong] + 1); |
|
if (val->ObjectType == ObjectTypes.ValueTypeObjectReference && ret->ObjectType == ObjectTypes.ValueTypeObjectReference) |
|
{ |
|
stack.RelocateValueTypeAndFreeAfterDst(val, ret); |
|
} |
|
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 |
|
{ |
|
obj = RetriveObject(objRef, mStack); |
|
Free(ret); |
|
if (obj != null) |
|
{ |
|
ILTypeInstance instance = null; |
|
if (obj is ILTypeInstance) |
|
instance = obj as ILTypeInstance; |
|
else if (obj is CrossBindingAdaptorType) |
|
instance = (obj as CrossBindingAdaptorType).ILInstance; |
|
if (instance != null) |
|
instance.PushToStack((int)ip->TokenLong, ret, this, mStack); |
|
else |
|
{ |
|
//var t = obj.GetType(); |
|
type = AppDomain.GetType((int)(ip->TokenLong >> 32)); |
|
if (type != null) |
|
{ |
|
var token = (int)ip->TokenLong; |
|
if (!((CLRType)type).CopyFieldToStack(token, obj, this, ref ret, mStack)) |
|
{ |
|
var ft = ((CLRType)type).GetField(token); |
|
obj = ((CLRType)type).GetFieldValue(token, obj); |
|
if (obj is CrossBindingAdaptorType) |
|
obj = ((CrossBindingAdaptorType)obj).ILInstance; |
|
PushObject(ret, mStack, obj, ft.FieldType == typeof(object)); |
|
} |
|
} |
|
else |
|
throw new TypeLoadException(); |
|
} |
|
} |
|
else |
|
throw new NullReferenceException(); |
|
} |
|
} |
|
break; |
|
case OpCodeEnum.Ldflda: |
|
{ |
|
objRef = GetObjectAndResolveReference(esp - 1); |
|
if (objRef->ObjectType == ObjectTypes.ValueTypeObjectReference) |
|
{ |
|
dst = esp - 1; |
|
var ft = domain.GetType((int)(ip->TokenLong >> 32)); |
|
StackObject* fieldAddr; |
|
if (ft is ILType) |
|
{ |
|
fieldAddr = Minus(ILIntepreter.ResolveReference(objRef), (int)ip->TokenLong + 1); |
|
} |
|
else |
|
{ |
|
fieldAddr = Minus(ILIntepreter.ResolveReference(objRef), ((CLRType)ft).FieldIndexMapping[(int)ip->TokenLong] + 1); |
|
} |
|
StackObject valRef = *dst; |
|
dst->ObjectType = ObjectTypes.StackObjectReference; |
|
*(long*)&dst->Value = (long)fieldAddr; |
|
FreeStackValueType(&valRef); |
|
} |
|
else |
|
{ |
|
obj = RetriveObject(objRef, mStack); |
|
|
|
Free(esp - 1); |
|
if (obj != null) |
|
{ |
|
if (obj is ILTypeInstance) |
|
{ |
|
ILTypeInstance instance = obj as ILTypeInstance; |
|
instance.PushFieldAddress((int)ip->TokenLong, esp - 1, mStack); |
|
} |
|
else |
|
{ |
|
objRef = esp - 1; |
|
objRef->ObjectType = ObjectTypes.FieldReference; |
|
objRef->Value = mStack.Count; |
|
mStack.Add(obj); |
|
objRef->ValueLow = (int)ip->TokenLong; |
|
} |
|
} |
|
else |
|
throw new NullReferenceException(); |
|
} |
|
} |
|
break; |
|
case OpCodeEnum.Stsfld: |
|
{ |
|
type = AppDomain.GetType((int)(ip->TokenLong >> 32)); |
|
if (type != null) |
|
{ |
|
if (type is ILType) |
|
{ |
|
ILType t = type as ILType; |
|
val = esp - 1; |
|
t.StaticInstance.AssignFromStack((int)ip->TokenLong, val, AppDomain, mStack); |
|
} |
|
else |
|
{ |
|
CLRType t = type as CLRType; |
|
int idx = (int)ip->TokenLong; |
|
var f = t.GetField(idx); |
|
val = esp - 1; |
|
obj = null; |
|
if (!((CLRType)t).AssignFieldFromStack(idx, ref obj, this, val, mStack)) |
|
t.SetStaticFieldValue(idx, f.FieldType.CheckCLRTypes(CheckAndCloneValueType(StackObject.ToObject(val, domain, mStack), domain))); |
|
} |
|
} |
|
else |
|
throw new TypeLoadException(); |
|
Free(esp - 1); |
|
esp -= 1; |
|
} |
|
break; |
|
case OpCodeEnum.Ldsfld: |
|
{ |
|
type = AppDomain.GetType((int)(ip->TokenLong >> 32)); |
|
if (type != null) |
|
{ |
|
if (type is ILType) |
|
{ |
|
ILType t = type as ILType; |
|
t.StaticInstance.PushToStack((int)ip->TokenLong, esp, this, mStack); |
|
esp++; |
|
} |
|
else |
|
{ |
|
CLRType t = type as CLRType; |
|
int idx = (int)ip->TokenLong; |
|
if (!((CLRType)type).CopyFieldToStack(idx, null, this, ref esp, mStack)) |
|
{ |
|
var f = t.GetField(idx); |
|
obj = t.GetFieldValue(idx, null); |
|
if (obj is CrossBindingAdaptorType) |
|
obj = ((CrossBindingAdaptorType)obj).ILInstance; |
|
esp = PushObject(esp, mStack, obj, f.FieldType == typeof(object)); |
|
} |
|
} |
|
} |
|
else |
|
throw new TypeLoadException(); |
|
} |
|
break; |
|
case OpCodeEnum.Ldsflda: |
|
{ |
|
int typeId = (int)(ip->TokenLong >> 32); |
|
int fieldIdx = (int)(ip->TokenLong); |
|
esp->ObjectType = ObjectTypes.StaticFieldReference; |
|
esp->Value = typeId; |
|
esp->ValueLow = fieldIdx; |
|
esp++; |
|
} |
|
break; |
|
case OpCodeEnum.Ldtoken: |
|
{ |
|
switch (ip->TokenInteger) |
|
{ |
|
case 0: |
|
{ |
|
type = AppDomain.GetType((int)(ip->TokenLong >> 32)); |
|
if (type != null) |
|
{ |
|
if (type is ILType) |
|
{ |
|
ILType t = type as ILType; |
|
t.StaticInstance.PushToStack((int)ip->TokenLong, esp, this, mStack); |
|
} |
|
else |
|
throw new NotImplementedException(); |
|
} |
|
} |
|
esp++; |
|
break; |
|
case 1: |
|
{ |
|
type = AppDomain.GetType((int)ip->TokenLong); |
|
if (type != null) |
|
{ |
|
esp = PushObject(esp, mStack, type.ReflectionType); |
|
} |
|
else |
|
throw new TypeLoadException(); |
|
} |
|
break; |
|
default: |
|
throw new NotImplementedException(); |
|
} |
|
} |
|
break; |
|
case OpCodeEnum.Ldftn: |
|
{ |
|
IMethod m = domain.GetMethod(ip->TokenInteger); |
|
esp = PushObject(esp, mStack, m); |
|
} |
|
break; |
|
case OpCodeEnum.Ldvirtftn: |
|
{ |
|
IMethod m = domain.GetMethod(ip->TokenInteger); |
|
objRef = esp - 1; |
|
if (m is ILMethod) |
|
{ |
|
ILMethod ilm = (ILMethod)m; |
|
|
|
obj = mStack[objRef->Value]; |
|
m = ((ILTypeInstance)obj).Type.GetVirtualMethod(ilm) as ILMethod; |
|
} |
|
else |
|
{ |
|
obj = mStack[objRef->Value]; |
|
if (obj is ILTypeInstance) |
|
m = ((ILTypeInstance)obj).Type.GetVirtualMethod(m); |
|
else if (obj is CrossBindingAdaptorType) |
|
{ |
|
m = ((CrossBindingAdaptorType)obj).ILInstance.Type.BaseType.GetVirtualMethod(m); |
|
} |
|
} |
|
Free(objRef); |
|
esp = PushObject(objRef, mStack, m); |
|
} |
|
break; |
|
#endregion |
|
|
|
#region Compare |
|
case OpCodeEnum.Ceq: |
|
{ |
|
StackObject* obj1 = esp - 1 - 1; |
|
StackObject* obj2 = esp - 1; |
|
bool res = false; |
|
if (obj1->ObjectType == obj2->ObjectType) |
|
{ |
|
switch (obj1->ObjectType) |
|
{ |
|
case ObjectTypes.Integer: |
|
case ObjectTypes.Float: |
|
res = obj1->Value == obj2->Value; |
|
break; |
|
case ObjectTypes.Object: |
|
res = mStack[obj1->Value] == mStack[obj2->Value]; |
|
break; |
|
case ObjectTypes.FieldReference: |
|
res = mStack[obj1->Value] == mStack[obj2->Value] && obj1->ValueLow == obj2->ValueLow; |
|
break; |
|
case ObjectTypes.Null: |
|
res = true; |
|
break; |
|
default: |
|
res = obj1->Value == obj2->Value && obj1->ValueLow == obj2->ValueLow; |
|
break; |
|
} |
|
} |
|
else |
|
{ |
|
switch (obj1->ObjectType) |
|
{ |
|
case ObjectTypes.Object: |
|
res = mStack[obj1->Value] == null && obj2->ObjectType == ObjectTypes.Null; |
|
break; |
|
case ObjectTypes.Null: |
|
res = obj2->ObjectType == ObjectTypes.Object && mStack[obj2->Value] == null; |
|
break; |
|
} |
|
} |
|
Free(esp - 1); |
|
Free(esp - 1 - 1); |
|
if (res) |
|
esp = PushOne(esp - 1 - 1); |
|
else |
|
esp = PushZero(esp - 1 - 1); |
|
|
|
} |
|
break; |
|
case OpCodeEnum.Clt: |
|
{ |
|
StackObject* obj1 = esp - 1 - 1; |
|
StackObject* obj2 = esp - 1; |
|
bool res = false; |
|
switch (obj1->ObjectType) |
|
{ |
|
case ObjectTypes.Integer: |
|
res = obj1->Value < obj2->Value; |
|
break; |
|
case ObjectTypes.Long: |
|
res = *(long*)&obj1->Value < *(long*)&obj2->Value; |
|
break; |
|
case ObjectTypes.Float: |
|
res = *(float*)&obj1->Value < *(float*)&obj2->Value; |
|
break; |
|
case ObjectTypes.Double: |
|
res = *(double*)&obj1->Value < *(double*)&obj2->Value; |
|
break; |
|
default: |
|
throw new NotImplementedException(); |
|
} |
|
if (res) |
|
esp = PushOne(esp - 1 - 1); |
|
else |
|
esp = PushZero(esp - 1 - 1); |
|
} |
|
break; |
|
case OpCodeEnum.Clt_Un: |
|
{ |
|
StackObject* obj1 = esp - 1 - 1; |
|
StackObject* obj2 = esp - 1; |
|
bool res = false; |
|
switch (obj1->ObjectType) |
|
{ |
|
case ObjectTypes.Integer: |
|
res = (uint)obj1->Value < (uint)obj2->Value && obj2->ObjectType != ObjectTypes.Null; |
|
break; |
|
case ObjectTypes.Long: |
|
res = (ulong)*(long*)&obj1->Value < (ulong)*(long*)&obj2->Value && obj2->ObjectType != ObjectTypes.Null; |
|
break; |
|
case ObjectTypes.Float: |
|
res = *(float*)&obj1->Value < *(float*)&obj2->Value && obj2->ObjectType != ObjectTypes.Null; |
|
break; |
|
case ObjectTypes.Double: |
|
res = *(double*)&obj1->Value < *(double*)&obj2->Value && obj2->ObjectType != ObjectTypes.Null; |
|
break; |
|
default: |
|
throw new NotImplementedException(); |
|
} |
|
if (res) |
|
esp = PushOne(esp - 1 - 1); |
|
else |
|
esp = PushZero(esp - 1 - 1); |
|
} |
|
break; |
|
case OpCodeEnum.Cgt: |
|
{ |
|
StackObject* obj1 = esp - 1 - 1; |
|
StackObject* obj2 = esp - 1; |
|
bool res = false; |
|
switch (obj1->ObjectType) |
|
{ |
|
case ObjectTypes.Integer: |
|
res = obj1->Value > obj2->Value || obj2->ObjectType == ObjectTypes.Null; |
|
break; |
|
case ObjectTypes.Long: |
|
res = *(long*)&obj1->Value > *(long*)&obj2->Value || obj2->ObjectType == ObjectTypes.Null; |
|
break; |
|
case ObjectTypes.Float: |
|
res = *(float*)&obj1->Value > *(float*)&obj2->Value || obj2->ObjectType == ObjectTypes.Null; |
|
break; |
|
case ObjectTypes.Double: |
|
res = *(double*)&obj1->Value > *(double*)&obj2->Value || obj2->ObjectType == ObjectTypes.Null; |
|
break; |
|
default: |
|
throw new NotImplementedException(); |
|
} |
|
if (res) |
|
esp = PushOne(esp - 1 - 1); |
|
else |
|
esp = PushZero(esp - 1 - 1); |
|
} |
|
break; |
|
case OpCodeEnum.Cgt_Un: |
|
{ |
|
StackObject* obj1 = esp - 1 - 1; |
|
StackObject* obj2 = esp - 1; |
|
bool res = false; |
|
switch (obj1->ObjectType) |
|
{ |
|
case ObjectTypes.Integer: |
|
res = ((uint)obj1->Value > (uint)obj2->Value) || obj2->ObjectType == ObjectTypes.Null; |
|
break; |
|
case ObjectTypes.Long: |
|
res = (ulong)*(long*)&obj1->Value > (ulong)*(long*)&obj2->Value || obj2->ObjectType == ObjectTypes.Null; |
|
break; |
|
case ObjectTypes.Float: |
|
res = *(float*)&obj1->Value > *(float*)&obj2->Value || obj2->ObjectType == ObjectTypes.Null; |
|
break; |
|
case ObjectTypes.Double: |
|
res = *(double*)&obj1->Value > *(double*)&obj2->Value || obj2->ObjectType == ObjectTypes.Null; |
|
break; |
|
case ObjectTypes.Object: |
|
res = mStack[obj1->Value] != null && obj2->ObjectType == ObjectTypes.Null; |
|
break; |
|
case ObjectTypes.Null: |
|
res = false; |
|
break; |
|
default: |
|
throw new NotImplementedException(); |
|
} |
|
if (res) |
|
esp = PushOne(esp - 1 - 1); |
|
else |
|
esp = PushZero(esp - 1 - 1); |
|
} |
|
break; |
|
#endregion |
|
|
|
#region Initialization & Instantiation |
|
case OpCodeEnum.Newobj: |
|
{ |
|
IMethod m = domain.GetMethod(ip->TokenInteger); |
|
if (m is ILMethod) |
|
{ |
|
type = m.DeclearingType as ILType; |
|
if (type.IsDelegate) |
|
{ |
|
objRef = GetObjectAndResolveReference(esp - 1 - 1); |
|
var mi = (IMethod)mStack[(esp - 1)->Value]; |
|
object ins; |
|
if (objRef->ObjectType == ObjectTypes.Null) |
|
ins = null; |
|
else |
|
ins = mStack[objRef->Value]; |
|
Free(esp - 1); |
|
Free(esp - 1 - 1); |
|
esp = esp - 1 - 1; |
|
object dele; |
|
var ilMethod = mi as ILMethod; |
|
if (ilMethod != null) |
|
{ |
|
if (ins != null) |
|
{ |
|
dele = ((ILTypeInstance) ins).GetDelegateAdapter(ilMethod); |
|
if (dele == null) |
|
{ |
|
var invokeMethod = type.GetMethod("Invoke", mi.ParameterCount); |
|
if (invokeMethod == null && ilMethod.IsExtend) |
|
{ |
|
invokeMethod = type.GetMethod("Invoke", mi.ParameterCount - 1); |
|
} |
|
dele = domain.DelegateManager.FindDelegateAdapter( |
|
(ILTypeInstance) ins, ilMethod, invokeMethod); |
|
} |
|
} |
|
else |
|
{ |
|
if (ilMethod.DelegateAdapter == null) |
|
{ |
|
var invokeMethod = type.GetMethod("Invoke", mi.ParameterCount); |
|
ilMethod.DelegateAdapter = domain.DelegateManager.FindDelegateAdapter(null, ilMethod, invokeMethod); |
|
} |
|
dele = ilMethod.DelegateAdapter; |
|
} |
|
} |
|
|
|
else |
|
{ |
|
throw new NotImplementedException(); |
|
} |
|
esp = PushObject(esp, mStack, dele); |
|
} |
|
else |
|
{ |
|
intVal = m.ParameterCount; |
|
a = esp - intVal; |
|
obj = null; |
|
bool isValueType = type.IsValueType; |
|
ILIntepreter tmpIntp; |
|
IList<object> tmStack; |
|
if (isValueType && intVal > 0) |
|
{ |
|
tmpIntp = domain.RequestILIntepreter(); |
|
tmpIntp.stack.ResetValueTypePointer(); |
|
esp = tmpIntp.stack.StackBase; |
|
tmStack = tmpIntp.stack.ManagedStack; |
|
} |
|
else |
|
{ |
|
tmpIntp = this; |
|
tmStack = mStack; |
|
} |
|
if (isValueType) |
|
{ |
|
tmpIntp.stack.AllocValueType(esp, type); |
|
objRef = esp + 1; |
|
objRef->ObjectType = ObjectTypes.StackObjectReference; |
|
*(long*)&objRef->Value = (long)esp; |
|
objRef++; |
|
} |
|
else |
|
{ |
|
obj = ((ILType)type).Instantiate(false); |
|
objRef = PushObject(esp, tmStack, obj);//this parameter for constructor |
|
} |
|
esp = objRef; |
|
for (int i = 0; i < intVal; i++) |
|
{ |
|
tmpIntp.CopyToStack(esp, a + i, mStack, tmStack); |
|
esp++; |
|
} |
|
if (((ILMethod)m).ShouldUseRegisterVM) |
|
{ |
|
PrepareRegisterCallStack(esp, tmStack, (ILMethod)m); |
|
esp = tmpIntp.ExecuteR((ILMethod)m, esp, out unhandledException); |
|
} |
|
else |
|
esp = tmpIntp.Execute((ILMethod)m, esp, out unhandledException); |
|
|
|
ValueTypeBasePointer = bp; |
|
for (int i = intVal - 1; i >= 0; i--) |
|
{ |
|
Free(Add(a, i)); |
|
} |
|
if (isValueType) |
|
{ |
|
if (intVal > 0) |
|
{ |
|
stack.AllocValueType(a, type); |
|
CopyStackValueType(esp - 1, a, tmpIntp.stack.ManagedStack, mStack); |
|
domain.FreeILIntepreter(tmpIntp); |
|
} |
|
else |
|
{ |
|
var ins = objRef - 1 - 1; |
|
*a = *ins; |
|
} |
|
esp = a + 1; |
|
} |
|
else |
|
esp = PushObject(a, mStack, obj);//new constructedObj |
|
|
|
} |
|
if (unhandledException) |
|
returned = true; |
|
} |
|
else |
|
{ |
|
CLRMethod cm = (CLRMethod)m; |
|
//Means new object(); |
|
if (cm == null) |
|
{ |
|
esp = PushObject(esp, mStack, new object()); |
|
} |
|
else |
|
{ |
|
if (cm.DeclearingType.IsDelegate) |
|
{ |
|
objRef = GetObjectAndResolveReference(esp - 1 - 1); |
|
var mi = (IMethod)mStack[(esp - 1)->Value]; |
|
object ins; |
|
if (objRef->ObjectType == ObjectTypes.Null) |
|
ins = null; |
|
else |
|
ins = mStack[objRef->Value]; |
|
Free(esp - 1); |
|
Free(esp - 1 - 1); |
|
esp = esp - 1 - 1; |
|
object dele; |
|
var ilMethod = mi as ILMethod; |
|
if (ilMethod != null) |
|
{ |
|
dele = domain.DelegateManager.FindDelegateAdapter((CLRType)cm.DeclearingType, (ILTypeInstance)ins, ilMethod); |
|
} |
|
else |
|
{ |
|
if (ins is ILTypeInstance) |
|
ins = ((ILTypeInstance)ins).CLRInstance; |
|
dele = Delegate.CreateDelegate(cm.DeclearingType.TypeForCLR, ins, ((CLRMethod)mi).MethodInfo); |
|
} |
|
esp = PushObject(esp, mStack, dele); |
|
} |
|
else |
|
{ |
|
var redirect = cm.Redirection; |
|
if (redirect != null) |
|
esp = redirect(this, esp, mStack, cm, true); |
|
else |
|
{ |
|
#if DEBUG && !DISABLE_ILRUNTIME_DEBUG |
|
if (!allowUnboundCLRMethod) |
|
throw new NotSupportedException(cm.ToString() + " is not bound!"); |
|
#endif |
|
object result = cm.Invoke(this, esp, mStack, true); |
|
int paramCount = cm.ParameterCount; |
|
for (int i = 1; i <= paramCount; i++) |
|
{ |
|
Free(esp - i); |
|
} |
|
esp = Minus(esp, paramCount); |
|
esp = PushObject(esp, mStack, result);//new constructedObj |
|
} |
|
} |
|
} |
|
} |
|
} |
|
break; |
|
case OpCodeEnum.Constrained: |
|
{ |
|
type = domain.GetType(ip->TokenInteger); |
|
var m = domain.GetMethod((int)ip->TokenLong); |
|
var pCnt = m.ParameterCount; |
|
objRef = Minus(esp, pCnt + 1); |
|
var insIdx = mStack.Count; |
|
if (objRef->ObjectType < ObjectTypes.Object) |
|
{ |
|
bool moved = false; |
|
//move parameters |
|
for (int i = 0; i < pCnt; i++) |
|
{ |
|
var pPtr = Minus(esp, i + 1); |
|
if (pPtr->ObjectType >= ObjectTypes.Object) |
|
{ |
|
var oldVal = pPtr->Value; |
|
insIdx--; |
|
if (!moved) |
|
{ |
|
pPtr->Value = mStack.Count; |
|
mStack.Add(mStack[oldVal]); |
|
mStack[oldVal] = null; |
|
moved = true; |
|
} |
|
else |
|
{ |
|
mStack[oldVal + 1] = mStack[oldVal]; |
|
mStack[oldVal] = null; |
|
pPtr->Value = oldVal + 1; |
|
} |
|
} |
|
} |
|
if (!moved) |
|
{ |
|
mStack.Add(null); |
|
} |
|
} |
|
else |
|
insIdx = objRef->Value; |
|
objRef2 = GetObjectAndResolveReference(objRef); |
|
if (type != null) |
|
{ |
|
if (type is ILType) |
|
{ |
|
var t = (ILType)type; |
|
if (t.IsEnum) |
|
{ |
|
ILEnumTypeInstance ins = new ILEnumTypeInstance(t); |
|
switch (objRef2->ObjectType) |
|
{ |
|
case ObjectTypes.FieldReference: |
|
{ |
|
var owner = mStack[objRef2->Value] as ILTypeInstance; |
|
int idx = objRef2->ValueLow; |
|
//Free(objRef); |
|
owner.PushToStack(idx, objRef, this, mStack); |
|
ins.AssignFromStack(0, objRef, AppDomain, mStack); |
|
ins.Boxed = true; |
|
} |
|
break; |
|
case ObjectTypes.StaticFieldReference: |
|
{ |
|
var st = AppDomain.GetType(objRef2->Value) as ILType; |
|
int idx = objRef2->ValueLow; |
|
//Free(objRef); |
|
st.StaticInstance.PushToStack(idx, objRef, this, mStack); |
|
ins.AssignFromStack(0, objRef, AppDomain, mStack); |
|
ins.Boxed = true; |
|
} |
|
break; |
|
case ObjectTypes.ArrayReference: |
|
{ |
|
var arr = mStack[objRef2->Value]; |
|
var idx = objRef2->ValueLow; |
|
//Free(objRef); |
|
LoadFromArrayReference(arr, idx, objRef, t, mStack); |
|
ins.AssignFromStack(0, objRef, AppDomain, mStack); |
|
ins.Boxed = true; |
|
} |
|
break; |
|
default: |
|
ins.AssignFromStack(0, objRef2, AppDomain, mStack); |
|
ins.Boxed = true; |
|
break; |
|
} |
|
objRef->ObjectType = ObjectTypes.Object; |
|
objRef->Value = insIdx; |
|
mStack[insIdx] = ins; |
|
|
|
//esp = PushObject(esp - 1, mStack, ins); |
|
} |
|
else if(objRef2->ObjectType != ObjectTypes.ValueTypeObjectReference) |
|
{ |
|
object res = RetriveObject(objRef2, mStack); |
|
//Free(objRef); |
|
objRef->ObjectType = ObjectTypes.Object; |
|
objRef->Value = insIdx; |
|
mStack[insIdx] = res; |
|
//esp = PushObject(objRef, mStack, res, true); |
|
} |
|
} |
|
else |
|
{ |
|
var tt = type.TypeForCLR; |
|
if (tt.IsEnum) |
|
{ |
|
mStack[insIdx] = Enum.ToObject(tt, StackObject.ToObject(objRef2, AppDomain, mStack)); |
|
objRef->ObjectType = ObjectTypes.Object; |
|
objRef->Value = insIdx; |
|
//esp = PushObject(esp - 1, mStack, Enum.ToObject(tt, StackObject.ToObject(obj, AppDomain, mStack)), true); |
|
} |
|
else if (tt.IsPrimitive) |
|
{ |
|
mStack[insIdx] = tt.CheckCLRTypes(StackObject.ToObject(objRef2, AppDomain, mStack)); |
|
objRef->ObjectType = ObjectTypes.Object; |
|
objRef->Value = insIdx; |
|
//esp = PushObject(esp - 1, mStack, tt.CheckCLRTypes(StackObject.ToObject(obj, AppDomain, mStack))); |
|
} |
|
else if (objRef2->ObjectType != ObjectTypes.ValueTypeObjectReference) |
|
{ |
|
object res = RetriveObject(objRef2, mStack); |
|
//Free(objRef); |
|
objRef->ObjectType = ObjectTypes.Object; |
|
objRef->Value = insIdx; |
|
mStack[insIdx] = res; |
|
//esp = PushObject(objRef, mStack, res, true); |
|
} |
|
} |
|
} |
|
else |
|
throw new NullReferenceException(); |
|
} |
|
break; |
|
case OpCodeEnum.Box: |
|
{ |
|
objRef = esp - 1; |
|
type = domain.GetType(ip->TokenInteger); |
|
if (type != null) |
|
{ |
|
if (type is ILType) |
|
{ |
|
if (((ILType)type).IsEnum) |
|
{ |
|
ILEnumTypeInstance ins = new Intepreter.ILEnumTypeInstance((ILType)type); |
|
ins.AssignFromStack(0, objRef, AppDomain, mStack); |
|
ins.Boxed = true; |
|
esp = PushObject(objRef, mStack, ins, true); |
|
} |
|
else |
|
{ |
|
switch (objRef->ObjectType) |
|
{ |
|
case ObjectTypes.Null: |
|
break; |
|
case ObjectTypes.ValueTypeObjectReference: |
|
{ |
|
ILTypeInstance ins = ((ILType)type).Instantiate(false); |
|
ins.AssignFromStack(objRef, domain, mStack); |
|
FreeStackValueType(objRef); |
|
esp = PushObject(objRef, mStack, ins, true); |
|
} |
|
break; |
|
default: |
|
{ |
|
obj = mStack[objRef->Value]; |
|
Free(objRef); |
|
if (type.IsArray) |
|
{ |
|
esp = PushObject(objRef, mStack, obj, true); |
|
} |
|
else |
|
{ |
|
ILTypeInstance ins = (ILTypeInstance)obj; |
|
if (ins != null) |
|
{ |
|
if (ins.IsValueType) |
|
{ |
|
ins.Boxed = true; |
|
} |
|
esp = PushObject(objRef, mStack, ins, true); |
|
} |
|
else |
|
{ |
|
esp = PushNull(objRef); |
|
} |
|
} |
|
} |
|
break; |
|
} |
|
} |
|
} |
|
else |
|
{ |
|
if (type.TypeForCLR.IsPrimitive) |
|
{ |
|
var t = type.TypeForCLR; |
|
if (t == typeof(int)) |
|
{ |
|
switch (objRef->ObjectType) |
|
{ |
|
case ObjectTypes.Integer: |
|
esp = PushObject(objRef, mStack, objRef->Value, true); |
|
break; |
|
case ObjectTypes.Null: |
|
esp = PushObject(objRef, mStack, 0, true); |
|
break; |
|
case ObjectTypes.Object: |
|
break; |
|
default: |
|
throw new NotImplementedException(); |
|
} |
|
} |
|
else if (t == typeof(bool)) |
|
{ |
|
switch (objRef->ObjectType) |
|
{ |
|
case ObjectTypes.Integer: |
|
esp = PushObject(objRef, mStack, (objRef->Value == 1), true); |
|
break; |
|
case ObjectTypes.Null: |
|
esp = PushObject(objRef, mStack, false, true); |
|
break; |
|
case ObjectTypes.Object: |
|
break; |
|
default: |
|
throw new NotImplementedException(); |
|
} |
|
} |
|
else if (t == typeof(byte)) |
|
{ |
|
switch (objRef->ObjectType) |
|
{ |
|
case ObjectTypes.Integer: |
|
esp = PushObject(objRef, mStack, (byte)objRef->Value, true); |
|
break; |
|
case ObjectTypes.Null: |
|
esp = PushObject(objRef, mStack, 0L, true); |
|
break; |
|
case ObjectTypes.Object: |
|
break; |
|
default: |
|
throw new NotImplementedException(); |
|
} |
|
} |
|
else if (t == typeof(short)) |
|
{ |
|
switch (objRef->ObjectType) |
|
{ |
|
case ObjectTypes.Integer: |
|
esp = PushObject(objRef, mStack, (short)objRef->Value, true); |
|
break; |
|
case ObjectTypes.Null: |
|
esp = PushObject(objRef, mStack, (short)0, true); |
|
break; |
|
case ObjectTypes.Object: |
|
break; |
|
default: |
|
throw new NotImplementedException(); |
|
} |
|
} |
|
else if (t == typeof(long)) |
|
{ |
|
switch (objRef->ObjectType) |
|
{ |
|
case ObjectTypes.Long: |
|
esp = PushObject(objRef, mStack, *(long*)&objRef->Value, true); |
|
break; |
|
case ObjectTypes.Null: |
|
esp = PushObject(objRef, mStack, 0L, true); |
|
break; |
|
case ObjectTypes.Object: |
|
break; |
|
default: |
|
throw new NotImplementedException(); |
|
} |
|
} |
|
else if (t == typeof(float)) |
|
{ |
|
switch (objRef->ObjectType) |
|
{ |
|
case ObjectTypes.Float: |
|
esp = PushObject(objRef, mStack, *(float*)&objRef->Value, true); |
|
break; |
|
case ObjectTypes.Null: |
|
esp = PushObject(objRef, mStack, 0f, true); |
|
break; |
|
case ObjectTypes.Object: |
|
break; |
|
default: |
|
throw new NotImplementedException(); |
|
} |
|
} |
|
else if (t == typeof(double)) |
|
{ |
|
switch (objRef->ObjectType) |
|
{ |
|
case ObjectTypes.Double: |
|
esp = PushObject(objRef, mStack, *(double*)&objRef->Value, true); |
|
break; |
|
case ObjectTypes.Null: |
|
esp = PushObject(objRef, mStack, 0.0, true); |
|
break; |
|
case ObjectTypes.Object: |
|
break; |
|
default: |
|
throw new NotImplementedException(); |
|
} |
|
} |
|
else if (t == typeof(char)) |
|
{ |
|
switch (objRef->ObjectType) |
|
{ |
|
case ObjectTypes.Integer: |
|
esp = PushObject(objRef, mStack, (char)objRef->Value, true); |
|
break; |
|
case ObjectTypes.Object: |
|
break; |
|
default: |
|
throw new NotImplementedException(); |
|
} |
|
} |
|
else if (t == typeof(uint)) |
|
{ |
|
switch (objRef->ObjectType) |
|
{ |
|
case ObjectTypes.Integer: |
|
esp = PushObject(objRef, mStack, (uint)objRef->Value, true); |
|
break; |
|
case ObjectTypes.Null: |
|
esp = PushObject(objRef, mStack, (uint)0, true); |
|
break; |
|
case ObjectTypes.Object: |
|
break; |
|
default: |
|
throw new NotImplementedException(); |
|
} |
|
} |
|
else if (t == typeof(ushort)) |
|
{ |
|
switch (objRef->ObjectType) |
|
{ |
|
case ObjectTypes.Integer: |
|
esp = PushObject(objRef, mStack, (ushort)objRef->Value, true); |
|
break; |
|
case ObjectTypes.Null: |
|
esp = PushObject(objRef, mStack, (ushort)0, true); |
|
break; |
|
case ObjectTypes.Object: |
|
break; |
|
default: |
|
throw new NotImplementedException(); |
|
} |
|
} |
|
else if (t == typeof(ulong)) |
|
{ |
|
switch (objRef->ObjectType) |
|
{ |
|
case ObjectTypes.Long: |
|
esp = PushObject(objRef, mStack, *(ulong*)&objRef->Value, true); |
|
break; |
|
case ObjectTypes.Null: |
|
esp = PushObject(objRef, mStack, (ulong)0, true); |
|
break; |
|
case ObjectTypes.Object: |
|
break; |
|
default: |
|
throw new NotImplementedException(); |
|
} |
|
} |
|
else if (t == typeof(sbyte)) |
|
{ |
|
switch (objRef->ObjectType) |
|
{ |
|
case ObjectTypes.Integer: |
|
esp = PushObject(objRef, mStack, (sbyte)objRef->Value, true); |
|
break; |
|
case ObjectTypes.Null: |
|
esp = PushObject(objRef, mStack, (sbyte)0, true); |
|
break; |
|
case ObjectTypes.Object: |
|
break; |
|
default: |
|
throw new NotImplementedException(); |
|
} |
|
} |
|
else |
|
throw new NotImplementedException(); |
|
} |
|
else if (type.TypeForCLR.IsEnum) |
|
{ |
|
esp = PushObject(objRef, mStack, Enum.ToObject(type.TypeForCLR, StackObject.ToObject(objRef, AppDomain, mStack)), true); |
|
} |
|
else |
|
{ |
|
if (objRef->ObjectType == ObjectTypes.ValueTypeObjectReference) |
|
{ |
|
dst = ILIntepreter.ResolveReference(objRef); |
|
var vt = domain.GetTypeByIndex(dst->Value); |
|
if (vt != type) |
|
throw new InvalidCastException(); |
|
object ins = ((CLRType)vt).ValueTypeBinder.ToObject(dst, mStack); |
|
FreeStackValueType(objRef); |
|
esp = PushObject(objRef, mStack, ins, true); |
|
} |
|
//nothing to do for CLR type boxing |
|
} |
|
} |
|
} |
|
else |
|
throw new NullReferenceException(); |
|
} |
|
break; |
|
case OpCodeEnum.Unbox: |
|
case OpCodeEnum.Unbox_Any: |
|
{ |
|
objRef = esp - 1; |
|
if (objRef->ObjectType == ObjectTypes.Object) |
|
{ |
|
obj = mStack[objRef->Value]; |
|
Free(objRef); |
|
if (obj != null) |
|
{ |
|
var t = domain.GetType(ip->TokenInteger); |
|
if (t != null) |
|
{ |
|
clrType = t.TypeForCLR; |
|
bool isEnumObj = obj is ILEnumTypeInstance; |
|
if ((t is CLRType) && clrType.IsPrimitive && !isEnumObj) |
|
{ |
|
if (clrType == typeof(int)) |
|
{ |
|
int value = obj.ToInt32(); |
|
objRef->ObjectType = ObjectTypes.Integer; |
|
objRef->Value = value; |
|
} |
|
else if (clrType == typeof(bool)) |
|
{ |
|
bool value = (bool)obj; |
|
objRef->ObjectType = ObjectTypes.Integer; |
|
objRef->Value = value ? 1 : 0; |
|
} |
|
else if (clrType == typeof(short)) |
|
{ |
|
short value = obj.ToInt16(); |
|
objRef->ObjectType = ObjectTypes.Integer; |
|
objRef->Value = value; |
|
} |
|
else if (clrType == typeof(long)) |
|
{ |
|
long value = obj.ToInt64(); |
|
objRef->ObjectType = ObjectTypes.Long; |
|
*(long*)&objRef->Value = value; |
|
} |
|
else if (clrType == typeof(float)) |
|
{ |
|
float value = obj.ToFloat(); |
|
objRef->ObjectType = ObjectTypes.Float; |
|
*(float*)&objRef->Value = value; |
|
} |
|
else if (clrType == typeof(byte)) |
|
{ |
|
byte value = (byte)obj; |
|
objRef->ObjectType = ObjectTypes.Integer; |
|
objRef->Value = value; |
|
} |
|
else if (clrType == typeof(double)) |
|
{ |
|
double value = obj.ToDouble(); |
|
objRef->ObjectType = ObjectTypes.Double; |
|
*(double*)&objRef->Value = value; |
|
} |
|
else if (clrType == typeof(char)) |
|
{ |
|
char value = (char)obj; |
|
objRef->ObjectType = ObjectTypes.Integer; |
|
*(&objRef->Value) = value; |
|
} |
|
else if (clrType == typeof(uint)) |
|
{ |
|
uint value = (uint)obj; |
|
objRef->ObjectType = ObjectTypes.Integer; |
|
objRef->Value = (int)value; |
|
} |
|
else if (clrType == typeof(ushort)) |
|
{ |
|
ushort value = (ushort)obj; |
|
objRef->ObjectType = ObjectTypes.Integer; |
|
objRef->Value = value; |
|
} |
|
else if (clrType == typeof(ulong)) |
|
{ |
|
ulong value = (ulong)obj; |
|
objRef->ObjectType = ObjectTypes.Long; |
|
*(ulong*)&objRef->Value = value; |
|
} |
|
else if (clrType == typeof(sbyte)) |
|
{ |
|
sbyte value = (sbyte)obj; |
|
objRef->ObjectType = ObjectTypes.Integer; |
|
objRef->Value = value; |
|
} |
|
else |
|
throw new NotImplementedException(); |
|
} |
|
else if (t.IsValueType) |
|
{ |
|
if (obj is ILTypeInstance) |
|
{ |
|
var res = ((ILTypeInstance)obj); |
|
if (res is ILEnumTypeInstance) |
|
{ |
|
res.PushToStack(0, objRef, this, mStack); |
|
} |
|
else |
|
{ |
|
if (res.Boxed) |
|
{ |
|
res = res.Clone(); |
|
res.Boxed = false; |
|
} |
|
PushObject(objRef, mStack, res); |
|
} |
|
} |
|
else |
|
PushObject(objRef, mStack, obj); |
|
} |
|
else |
|
{ |
|
PushObject(objRef, mStack, obj); |
|
} |
|
} |
|
else |
|
throw new TypeLoadException(); |
|
} |
|
else |
|
{ |
|
//Nothing to do with null |
|
|
|
} |
|
} |
|
else if (objRef->ObjectType < ObjectTypes.StackObjectReference) |
|
{ |
|
//Nothing to do with primitive types |
|
} |
|
else if (objRef->ObjectType == ObjectTypes.ValueTypeObjectReference) |
|
{ |
|
//Nothing to do with ValueTypeReference |
|
} |
|
else |
|
throw new InvalidCastException(); |
|
} |
|
break; |
|
case OpCodeEnum.Initobj: |
|
{ |
|
objRef = GetObjectAndResolveReference(esp - 1); |
|
type = domain.GetType(ip->TokenInteger); |
|
if (type is ILType) |
|
{ |
|
ILType it = (ILType)type; |
|
if (it.IsValueType) |
|
{ |
|
switch (objRef->ObjectType) |
|
{ |
|
case ObjectTypes.Null: |
|
throw new NullReferenceException(); |
|
case ObjectTypes.Integer: |
|
case ObjectTypes.Float: |
|
objRef->Value = 0; |
|
break; |
|
case ObjectTypes.Long: |
|
case ObjectTypes.Double: |
|
*(long*)&objRef->Value = 0; |
|
break; |
|
case ObjectTypes.ValueTypeObjectReference: |
|
stack.ClearValueTypeObject(type, ILIntepreter.ResolveReference(objRef)); |
|
break; |
|
case ObjectTypes.Object: |
|
{ |
|
obj = mStack[objRef->Value]; |
|
if (obj != null) |
|
{ |
|
if (obj is ILTypeInstance) |
|
{ |
|
ILTypeInstance instance = obj as ILTypeInstance; |
|
instance.Clear(); |
|
} |
|
else |
|
throw new NotSupportedException(); |
|
} |
|
else |
|
throw new NullReferenceException(); |
|
} |
|
break; |
|
case ObjectTypes.ArrayReference: |
|
{ |
|
var arr = mStack[objRef->Value] as Array; |
|
var idx = objRef->ValueLow; |
|
obj = arr.GetValue(idx); |
|
if (obj == null) |
|
arr.SetValue(it.Instantiate(), idx); |
|
else |
|
{ |
|
if (obj is ILTypeInstance) |
|
{ |
|
ILTypeInstance instance = obj as ILTypeInstance; |
|
instance.Clear(); |
|
} |
|
else |
|
throw new NotImplementedException(); |
|
} |
|
} |
|
break; |
|
case ObjectTypes.FieldReference: |
|
{ |
|
obj = mStack[objRef->Value]; |
|
if (obj != null) |
|
{ |
|
if (obj is ILTypeInstance) |
|
{ |
|
ILTypeInstance instance = obj as ILTypeInstance; |
|
var tar = instance[objRef->ValueLow] as ILTypeInstance; |
|
if (tar != null) |
|
tar.Clear(); |
|
else |
|
throw new NotSupportedException(); |
|
} |
|
else |
|
throw new NotSupportedException(); |
|
} |
|
else |
|
throw new NullReferenceException(); |
|
} |
|
break; |
|
case ObjectTypes.StaticFieldReference: |
|
{ |
|
var t = AppDomain.GetType(objRef->Value); |
|
int idx = objRef->ValueLow; |
|
if (t is ILType) |
|
{ |
|
var tar = ((ILType)t).StaticInstance[idx] as ILTypeInstance; |
|
if (tar != null) |
|
tar.Clear(); |
|
else |
|
throw new NotSupportedException(); |
|
} |
|
else |
|
throw new NotSupportedException(); |
|
} |
|
break; |
|
default: |
|
throw new NotImplementedException(); |
|
} |
|
} |
|
else |
|
{ |
|
PushNull(esp); |
|
switch (objRef->ObjectType) |
|
{ |
|
case ObjectTypes.StaticFieldReference: |
|
{ |
|
var t = AppDomain.GetType(objRef->Value) as ILType; |
|
t.StaticInstance.AssignFromStack(objRef->ValueLow, esp, AppDomain, mStack); |
|
} |
|
break; |
|
case ObjectTypes.FieldReference: |
|
{ |
|
var instance = mStack[objRef->Value] as ILTypeInstance; |
|
instance.AssignFromStack(objRef->ValueLow, esp, AppDomain, mStack); |
|
} |
|
break; |
|
default: |
|
{ |
|
if (objRef->ObjectType >= ObjectTypes.Object) |
|
mStack[objRef->Value] = null; |
|
else |
|
PushNull(objRef); |
|
} |
|
break; |
|
} |
|
} |
|
} |
|
else |
|
{ |
|
if (objRef->ObjectType == ObjectTypes.ValueTypeObjectReference) |
|
{ |
|
stack.ClearValueTypeObject(type, ILIntepreter.ResolveReference(objRef)); |
|
} |
|
else if (objRef->ObjectType == ObjectTypes.FieldReference) |
|
{ |
|
var instance = mStack[objRef->Value] as ILTypeInstance; |
|
if (instance != null) |
|
{ |
|
instance.InitializeField(objRef->ValueLow); |
|
} |
|
else |
|
throw new NotImplementedException(); |
|
} |
|
else if (type.IsPrimitive) |
|
StackObject.Initialized(objRef, type); |
|
else |
|
{ |
|
if (!type.IsValueType) |
|
{ |
|
if (objRef->ObjectType >= ObjectTypes.Object) |
|
mStack[objRef->Value] = null; |
|
else |
|
PushNull(objRef); |
|
} |
|
} |
|
} |
|
|
|
Free(esp - 1); |
|
esp--; |
|
} |
|
break; |
|
case OpCodeEnum.Castclass: |
|
{ |
|
objRef = esp - 1; |
|
var oriRef = objRef; |
|
type = domain.GetType(ip->TokenInteger); |
|
if (type != null) |
|
{ |
|
objRef = GetObjectAndResolveReference(objRef); |
|
if (objRef->ObjectType <= ObjectTypes.Double) |
|
{ |
|
if (objRef->ObjectType != ObjectTypes.Null) |
|
throw new NotImplementedException(); |
|
else |
|
{ |
|
//Nothing to do with null |
|
} |
|
} |
|
else |
|
{ |
|
obj = RetriveObject(objRef, mStack); |
|
Free(oriRef); |
|
|
|
if (obj != null) |
|
{ |
|
if (obj is ILTypeInstance) |
|
{ |
|
if (((ILTypeInstance)obj).CanAssignTo(type)) |
|
{ |
|
esp = PushObject(oriRef, mStack, obj); |
|
} |
|
else |
|
{ |
|
throw new InvalidCastException(string.Format("Cannot Cast {0} to {1}", ((ILTypeInstance)obj).Type.FullName, type.FullName)); |
|
} |
|
} |
|
else |
|
{ |
|
if (type.TypeForCLR.IsAssignableFrom(obj.GetType())) |
|
{ |
|
esp = PushObject(oriRef, mStack, obj, true); |
|
} |
|
else |
|
{ |
|
throw new InvalidCastException(string.Format("Cannot Cast {0} to {1}", obj.GetType().FullName, type.FullName)); |
|
} |
|
} |
|
} |
|
else |
|
{ |
|
#if !DEBUG || DISABLE_ILRUNTIME_DEBUG |
|
oriRef->ObjectType = ObjectTypes.Null; |
|
oriRef->Value = -1; |
|
oriRef->ValueLow = 0; |
|
#endif |
|
} |
|
} |
|
} |
|
else |
|
throw new NullReferenceException(); |
|
} |
|
break; |
|
case OpCodeEnum.Isinst: |
|
{ |
|
objRef = esp - 1; |
|
var oriRef = objRef; |
|
type = domain.GetType(ip->TokenInteger); |
|
if (type != null) |
|
{ |
|
objRef = GetObjectAndResolveReference(objRef); |
|
if (objRef->ObjectType <= ObjectTypes.Double) |
|
{ |
|
var tclr = type.TypeForCLR; |
|
switch (objRef->ObjectType) |
|
{ |
|
case ObjectTypes.Integer: |
|
{ |
|
if (tclr != typeof(int) && tclr != typeof(bool) && tclr != typeof(short) && tclr != typeof(byte) && tclr != typeof(ushort) && tclr != typeof(uint)) |
|
{ |
|
oriRef->ObjectType = ObjectTypes.Null; |
|
oriRef->Value = -1; |
|
oriRef->ValueLow = 0; |
|
} |
|
} |
|
break; |
|
case ObjectTypes.Long: |
|
{ |
|
if (tclr != typeof(long) && tclr != typeof(ulong)) |
|
{ |
|
oriRef->ObjectType = ObjectTypes.Null; |
|
oriRef->Value = -1; |
|
oriRef->ValueLow = 0; |
|
} |
|
} |
|
break; |
|
case ObjectTypes.Float: |
|
{ |
|
if (tclr != typeof(float)) |
|
{ |
|
oriRef->ObjectType = ObjectTypes.Null; |
|
oriRef->Value = -1; |
|
oriRef->ValueLow = 0; |
|
} |
|
} |
|
break; |
|
case ObjectTypes.Double: |
|
{ |
|
if (tclr != typeof(double)) |
|
{ |
|
oriRef->ObjectType = ObjectTypes.Null; |
|
oriRef->Value = -1; |
|
oriRef->ValueLow = 0; |
|
} |
|
} |
|
break; |
|
case ObjectTypes.Null: |
|
oriRef->ObjectType = ObjectTypes.Null; |
|
oriRef->Value = -1; |
|
oriRef->ValueLow = 0; |
|
break; |
|
} |
|
} |
|
else |
|
{ |
|
obj = RetriveObject(objRef, mStack); |
|
Free(oriRef); |
|
|
|
if (obj != null) |
|
{ |
|
if (obj is ILTypeInstance) |
|
{ |
|
if (((ILTypeInstance)obj).CanAssignTo(type)) |
|
{ |
|
esp = PushObject(oriRef, mStack, obj); |
|
} |
|
else |
|
{ |
|
#if !DEBUG || DISABLE_ILRUNTIME_DEBUG |
|
oriRef->ObjectType = ObjectTypes.Null; |
|
oriRef->Value = -1; |
|
oriRef->ValueLow = 0; |
|
#endif |
|
} |
|
} |
|
else |
|
{ |
|
if (type.TypeForCLR.IsAssignableFrom(obj.GetType())) |
|
{ |
|
esp = PushObject(oriRef, mStack, obj, true); |
|
} |
|
else |
|
{ |
|
#if !DEBUG || DISABLE_ILRUNTIME_DEBUG |
|
oriRef->ObjectType = ObjectTypes.Null; |
|
oriRef->Value = -1; |
|
oriRef->ValueLow = 0; |
|
#endif |
|
} |
|
} |
|
} |
|
else |
|
{ |
|
#if !DEBUG || DISABLE_ILRUNTIME_DEBUG |
|
oriRef->ObjectType = ObjectTypes.Null; |
|
oriRef->Value = -1; |
|
oriRef->ValueLow = 0; |
|
#endif |
|
} |
|
} |
|
} |
|
else |
|
throw new NullReferenceException(); |
|
} |
|
break; |
|
#endregion |
|
|
|
#region Array |
|
case OpCodeEnum.Newarr: |
|
{ |
|
var cnt = (esp - 1); |
|
type = domain.GetType(ip->TokenInteger); |
|
object arr = null; |
|
if (type != null) |
|
{ |
|
if (type.TypeForCLR != typeof(ILTypeInstance)) |
|
{ |
|
if (type is CLRType) |
|
{ |
|
arr = ((CLRType)type).CreateArrayInstance(cnt->Value); |
|
} |
|
else |
|
{ |
|
arr = Array.CreateInstance(type.TypeForCLR, cnt->Value); |
|
} |
|
|
|
//Register Type |
|
AppDomain.GetType(arr.GetType()); |
|
} |
|
else |
|
{ |
|
arr = new ILTypeInstance[cnt->Value]; |
|
ILTypeInstance[] ilArr = (ILTypeInstance[])arr; |
|
if (type.IsValueType) |
|
{ |
|
for (int i = 0; i < cnt->Value; i++) |
|
{ |
|
ilArr[i] = ((ILType)type).Instantiate(true); |
|
} |
|
} |
|
} |
|
} |
|
cnt->ObjectType = ObjectTypes.Object; |
|
cnt->Value = mStack.Count; |
|
mStack.Add(arr); |
|
} |
|
break; |
|
case OpCodeEnum.Stelem_Ref: |
|
case OpCodeEnum.Stelem_Any: |
|
{ |
|
val = GetObjectAndResolveReference(esp - 1); |
|
var idx = esp - 1 - 1; |
|
arrRef = esp - 1 - 1 - 1; |
|
Array arr = mStack[arrRef->Value] as Array; |
|
if (arr is object[]) |
|
{ |
|
switch (val->ObjectType) |
|
{ |
|
case ObjectTypes.Null: |
|
arr.SetValue(null, idx->Value); |
|
break; |
|
case ObjectTypes.Object: |
|
ArraySetValue(arr, mStack[val->Value], idx->Value); |
|
break; |
|
case ObjectTypes.Integer: |
|
arr.SetValue(val->Value, idx->Value); |
|
break; |
|
case ObjectTypes.Long: |
|
arr.SetValue(*(long*)&val->Value, idx->Value); |
|
break; |
|
case ObjectTypes.Float: |
|
arr.SetValue(*(float*)&val->Value, idx->Value); |
|
break; |
|
case ObjectTypes.Double: |
|
arr.SetValue(*(double*)&val->Value, idx->Value); |
|
break; |
|
case ObjectTypes.ValueTypeObjectReference: |
|
ArraySetValue(arr, StackObject.ToObject(val, domain, mStack), idx->Value); |
|
FreeStackValueType(esp - 1); |
|
break; |
|
default: |
|
throw new NotImplementedException(); |
|
} |
|
} |
|
else |
|
{ |
|
switch (val->ObjectType) |
|
{ |
|
case ObjectTypes.Object: |
|
ArraySetValue(arr, mStack[val->Value], idx->Value); |
|
break; |
|
case ObjectTypes.Integer: |
|
{ |
|
StoreIntValueToArray(arr, val, idx); |
|
} |
|
break; |
|
case ObjectTypes.Long: |
|
{ |
|
if (arr is long[]) |
|
{ |
|
((long[])arr)[idx->Value] = *(long*)&val->Value; |
|
} |
|
else |
|
{ |
|
((ulong[])arr)[idx->Value] = *(ulong*)&val->Value; |
|
} |
|
} |
|
break; |
|
case ObjectTypes.Float: |
|
{ |
|
((float[])arr)[idx->Value] = *(float*)&val->Value; |
|
} |
|
break; |
|
case ObjectTypes.Double: |
|
{ |
|
((double[])arr)[idx->Value] = *(double*)&val->Value; |
|
} |
|
break; |
|
case ObjectTypes.ValueTypeObjectReference: |
|
ArraySetValue(arr, StackObject.ToObject(val, domain, mStack), idx->Value); |
|
FreeStackValueType(esp - 1); |
|
break; |
|
default: |
|
throw new NotImplementedException(); |
|
} |
|
} |
|
Free(esp - 1); |
|
Free(esp - 1 - 1); |
|
Free(esp - 1 - 1 - 1); |
|
esp = esp - 1 - 1 - 1; |
|
} |
|
break; |
|
|
|
case OpCodeEnum.Ldelem_Ref: |
|
case OpCodeEnum.Ldelem_Any: |
|
{ |
|
var idx = esp - 1; |
|
arrRef = esp - 1 - 1; |
|
Array arr = mStack[arrRef->Value] as Array; |
|
obj = arr.GetValue(idx->Value); |
|
if (obj is CrossBindingAdaptorType) |
|
obj = ((CrossBindingAdaptorType)obj).ILInstance; |
|
Free(esp - 1); |
|
Free(esp - 1 - 1); |
|
|
|
if (obj is ILTypeInstance) |
|
{ |
|
ILTypeInstance ins = (ILTypeInstance)obj; |
|
if (!(ins is DelegateAdapter) && ins.Type.IsValueType && !ins.Boxed) |
|
{ |
|
AllocValueType(arrRef, ins.Type); |
|
dst = ILIntepreter.ResolveReference(arrRef); |
|
ins.CopyValueTypeToStack(dst, mStack); |
|
esp = idx; |
|
} |
|
else |
|
esp = PushObject(esp - 1 - 1, mStack, obj, true); |
|
} |
|
else |
|
esp = PushObject(esp - 1 - 1, mStack, obj, !arr.GetType().GetElementType().IsPrimitive); |
|
} |
|
break; |
|
case OpCodeEnum.Stelem_I1: |
|
{ |
|
val = esp - 1; |
|
var idx = esp - 1 - 1; |
|
arrRef = esp - 1 - 1 - 1; |
|
byte[] arr = mStack[arrRef->Value] as byte[]; |
|
if (arr != null) |
|
{ |
|
arr[idx->Value] = (byte)val->Value; |
|
} |
|
else |
|
{ |
|
bool[] arr2 = mStack[arrRef->Value] as bool[]; |
|
if (arr2 != null) |
|
{ |
|
arr2[idx->Value] = val->Value == 1; |
|
} |
|
else |
|
{ |
|
sbyte[] arr3 = mStack[arrRef->Value] as sbyte[]; |
|
arr3[idx->Value] = (sbyte)val->Value; |
|
} |
|
} |
|
Free(esp - 1); |
|
Free(esp - 1 - 1); |
|
Free(esp - 1 - 1 - 1); |
|
esp = esp - 1 - 1 - 1; |
|
} |
|
break; |
|
case OpCodeEnum.Ldelem_I1: |
|
{ |
|
var idx = esp - 1; |
|
arrRef = esp - 1 - 1; |
|
bool[] arr = mStack[arrRef->Value] as bool[]; |
|
if (arr != null) |
|
intVal = arr[idx->Value] ? 1 : 0; |
|
else |
|
{ |
|
sbyte[] arr2 = mStack[arrRef->Value] as sbyte[]; |
|
intVal = arr2[idx->Value]; |
|
} |
|
|
|
Free(esp - 1); |
|
Free(esp - 1 - 1); |
|
|
|
arrRef->ObjectType = ObjectTypes.Integer; |
|
arrRef->Value = intVal; |
|
esp -= 1; |
|
} |
|
break; |
|
case OpCodeEnum.Ldelem_U1: |
|
{ |
|
var idx = (esp - 1); |
|
arrRef = esp - 1 - 1; |
|
byte[] arr = mStack[arrRef->Value] as byte[]; |
|
if (arr != null) |
|
intVal = arr[idx->Value]; |
|
else |
|
{ |
|
bool[] arr2 = mStack[arrRef->Value] as bool[]; |
|
intVal = arr2[idx->Value] ? 1 : 0; |
|
} |
|
Free(esp - 1); |
|
Free(esp - 1 - 1); |
|
|
|
arrRef->ObjectType = ObjectTypes.Integer; |
|
arrRef->Value = intVal; |
|
esp -= 1; |
|
} |
|
break; |
|
case OpCodeEnum.Stelem_I2: |
|
{ |
|
val = esp - 1; |
|
var idx = esp - 1 - 1; |
|
arrRef = esp - 1 - 1 - 1; |
|
short[] arr = mStack[arrRef->Value] as short[]; |
|
if (arr != null) |
|
{ |
|
arr[idx->Value] = (short)val->Value; |
|
} |
|
else |
|
{ |
|
ushort[] arr2 = mStack[arrRef->Value] as ushort[]; |
|
if (arr2 != null) |
|
{ |
|
arr2[idx->Value] = (ushort)val->Value; |
|
} |
|
else |
|
{ |
|
char[] arr3 = mStack[arrRef->Value] as char[]; |
|
arr3[idx->Value] = (char)val->Value; |
|
} |
|
} |
|
Free(esp - 1); |
|
Free(esp - 1 - 1); |
|
Free(esp - 1 - 1 - 1); |
|
esp = esp - 1 - 1 - 1; |
|
} |
|
break; |
|
case OpCodeEnum.Ldelem_I2: |
|
{ |
|
var idx = (esp - 1)->Value; |
|
arrRef = esp - 1 - 1; |
|
short[] arr = mStack[arrRef->Value] as short[]; |
|
if (arr != null) |
|
{ |
|
intVal = arr[idx]; |
|
} |
|
else |
|
{ |
|
char[] arr2 = mStack[arrRef->Value] as char[]; |
|
intVal = arr2[idx]; |
|
} |
|
Free(esp - 1); |
|
Free(esp - 1 - 1); |
|
|
|
arrRef->ObjectType = ObjectTypes.Integer; |
|
arrRef->Value = intVal; |
|
esp -= 1; |
|
} |
|
break; |
|
case OpCodeEnum.Ldelem_U2: |
|
{ |
|
var idx = (esp - 1)->Value; |
|
arrRef = esp - 1 - 1; |
|
ushort[] arr = mStack[arrRef->Value] as ushort[]; |
|
if (arr != null) |
|
{ |
|
intVal = arr[idx]; |
|
} |
|
else |
|
{ |
|
char[] arr2 = mStack[arrRef->Value] as char[]; |
|
intVal = arr2[idx]; |
|
} |
|
Free(esp - 1); |
|
Free(esp - 1 - 1); |
|
|
|
arrRef->ObjectType = ObjectTypes.Integer; |
|
arrRef->Value = intVal; |
|
esp -= 1; |
|
} |
|
break; |
|
case OpCodeEnum.Stelem_I4: |
|
{ |
|
val = esp - 1; |
|
var idx = esp - 1 - 1; |
|
arrRef = esp - 1 - 1 - 1; |
|
int[] arr = mStack[arrRef->Value] as int[]; |
|
if (arr != null) |
|
{ |
|
arr[idx->Value] = val->Value; |
|
} |
|
else |
|
{ |
|
uint[] arr2 = mStack[arrRef->Value] as uint[]; |
|
arr2[idx->Value] = (uint)val->Value; |
|
} |
|
Free(esp - 1); |
|
Free(esp - 1 - 1); |
|
Free(esp - 1 - 1 - 1); |
|
esp = esp - 1 - 1 - 1; |
|
} |
|
break; |
|
case OpCodeEnum.Ldelem_I4: |
|
{ |
|
var idx = (esp - 1)->Value; |
|
arrRef = esp - 1 - 1; |
|
int[] arr = mStack[arrRef->Value] as int[]; |
|
|
|
Free(esp - 1); |
|
Free(esp - 1 - 1); |
|
|
|
arrRef->ObjectType = ObjectTypes.Integer; |
|
arrRef->Value = arr[idx]; |
|
esp -= 1; |
|
} |
|
break; |
|
case OpCodeEnum.Ldelem_U4: |
|
{ |
|
var idx = (esp - 1)->Value; |
|
arrRef = esp - 1 - 1; |
|
uint[] arr = mStack[arrRef->Value] as uint[]; |
|
|
|
Free(esp - 1); |
|
Free(esp - 1 - 1); |
|
|
|
arrRef->ObjectType = ObjectTypes.Integer; |
|
arrRef->Value = (int)arr[idx]; |
|
esp -= 1; |
|
} |
|
break; |
|
case OpCodeEnum.Stelem_I8: |
|
{ |
|
val = esp - 1; |
|
var idx = esp - 1 - 1; |
|
arrRef = esp - 1 - 1 - 1; |
|
long[] arr = mStack[arrRef->Value] as long[]; |
|
if (arr != null) |
|
{ |
|
arr[idx->Value] = *(long*)&val->Value; |
|
} |
|
else |
|
{ |
|
ulong[] arr2 = mStack[arrRef->Value] as ulong[]; |
|
arr2[idx->Value] = *(ulong*)&val->Value; |
|
} |
|
Free(esp - 1); |
|
Free(esp - 1 - 1); |
|
Free(esp - 1 - 1 - 1); |
|
esp = esp - 1 - 1 - 1; |
|
} |
|
break; |
|
case OpCodeEnum.Ldelem_I8: |
|
{ |
|
var idx = esp - 1; |
|
arrRef = esp - 1 - 1; |
|
long[] arr = mStack[arrRef->Value] as long[]; |
|
long longVal; |
|
if (arr != null) |
|
longVal = arr[idx->Value]; |
|
else |
|
{ |
|
ulong[] arr2 = mStack[arrRef->Value] as ulong[]; |
|
longVal = (long)arr2[idx->Value]; |
|
} |
|
Free(esp - 1); |
|
Free(esp - 1 - 1); |
|
|
|
arrRef->ObjectType = ObjectTypes.Long; |
|
*(long*)&arrRef->Value = longVal; |
|
esp -= 1; |
|
} |
|
break; |
|
case OpCodeEnum.Stelem_R4: |
|
{ |
|
val = esp - 1; |
|
var idx = esp - 1 - 1; |
|
arrRef = esp - 1 - 1 - 1; |
|
float[] arr = mStack[arrRef->Value] as float[]; |
|
arr[idx->Value] = *(float*)&val->Value; |
|
Free(esp - 1); |
|
Free(esp - 1 - 1); |
|
Free(esp - 1 - 1 - 1); |
|
esp = esp - 1 - 1 - 1; |
|
} |
|
break; |
|
case OpCodeEnum.Ldelem_R4: |
|
{ |
|
var idx = (esp - 1)->Value; |
|
arrRef = esp - 1 - 1; |
|
float[] arr = mStack[arrRef->Value] as float[]; |
|
|
|
Free(esp - 1); |
|
Free(esp - 1 - 1); |
|
|
|
arrRef->ObjectType = ObjectTypes.Float; |
|
*(float*)&arrRef->Value = arr[idx]; |
|
esp -= 1; |
|
} |
|
break; |
|
case OpCodeEnum.Stelem_R8: |
|
{ |
|
val = esp - 1; |
|
var idx = esp - 1 - 1; |
|
arrRef = esp - 1 - 1 - 1; |
|
double[] arr = mStack[arrRef->Value] as double[]; |
|
arr[idx->Value] = *(double*)&val->Value; |
|
Free(esp - 1); |
|
Free(esp - 1 - 1); |
|
Free(esp - 1 - 1 - 1); |
|
esp = esp - 1 - 1 - 1; |
|
} |
|
break; |
|
case OpCodeEnum.Ldelem_R8: |
|
{ |
|
var idx = (esp - 1)->Value; |
|
arrRef = esp - 1 - 1; |
|
double[] arr = mStack[arrRef->Value] as double[]; |
|
|
|
Free(esp - 1); |
|
Free(esp - 1 - 1); |
|
|
|
arrRef->ObjectType = ObjectTypes.Double; |
|
*(double*)&arrRef->Value = arr[idx]; |
|
esp -= 1; |
|
} |
|
break; |
|
case OpCodeEnum.Ldlen: |
|
{ |
|
arrRef = esp - 1; |
|
Array arr = mStack[arrRef->Value] as Array; |
|
Free(esp - 1); |
|
|
|
arrRef->ObjectType = ObjectTypes.Integer; |
|
arrRef->Value = arr.Length; |
|
} |
|
break; |
|
case OpCodeEnum.Ldelema: |
|
{ |
|
arrRef = esp - 1 - 1; |
|
var idx = (esp - 1)->Value; |
|
|
|
Array arr = mStack[arrRef->Value] as Array; |
|
Free(esp - 1); |
|
Free(esp - 1 - 1); |
|
|
|
arrRef->ObjectType = ObjectTypes.ArrayReference; |
|
arrRef->Value = mStack.Count; |
|
mStack.Add(arr); |
|
arrRef->ValueLow = idx; |
|
esp--; |
|
} |
|
break; |
|
#endregion |
|
|
|
#region Conversion |
|
case OpCodeEnum.Conv_U1: |
|
case OpCodeEnum.Conv_Ovf_U1: |
|
case OpCodeEnum.Conv_Ovf_U1_Un: |
|
{ |
|
objRef = esp - 1; |
|
switch (objRef->ObjectType) |
|
{ |
|
case ObjectTypes.Long: |
|
case ObjectTypes.Integer: |
|
intVal = (byte)objRef->Value; |
|
break; |
|
case ObjectTypes.Float: |
|
intVal = (byte)*(float*)&objRef->Value; |
|
break; |
|
case ObjectTypes.Double: |
|
intVal = (byte)*(double*)&objRef->Value; |
|
break; |
|
default: |
|
throw new NotImplementedException(); |
|
} |
|
objRef->ObjectType = ObjectTypes.Integer; |
|
objRef->Value = intVal; |
|
objRef->ValueLow = 0; |
|
} |
|
break; |
|
case OpCodeEnum.Conv_I1: |
|
case OpCodeEnum.Conv_Ovf_I1: |
|
case OpCodeEnum.Conv_Ovf_I1_Un: |
|
{ |
|
objRef = esp - 1; |
|
switch (objRef->ObjectType) |
|
{ |
|
case ObjectTypes.Long: |
|
case ObjectTypes.Integer: |
|
intVal = (sbyte)objRef->Value; |
|
break; |
|
case ObjectTypes.Float: |
|
intVal = (sbyte)*(float*)&objRef->Value; |
|
break; |
|
case ObjectTypes.Double: |
|
intVal = (sbyte)*(double*)&objRef->Value; |
|
break; |
|
default: |
|
throw new NotImplementedException(); |
|
} |
|
objRef->ObjectType = ObjectTypes.Integer; |
|
objRef->Value = intVal; |
|
objRef->ValueLow = 0; |
|
} |
|
break; |
|
case OpCodeEnum.Conv_U2: |
|
case OpCodeEnum.Conv_Ovf_U2: |
|
case OpCodeEnum.Conv_Ovf_U2_Un: |
|
{ |
|
objRef = esp - 1; |
|
switch (objRef->ObjectType) |
|
{ |
|
case ObjectTypes.Long: |
|
case ObjectTypes.Integer: |
|
intVal = (ushort)objRef->Value; |
|
break; |
|
case ObjectTypes.Float: |
|
intVal = (ushort)*(float*)&objRef->Value; |
|
break; |
|
case ObjectTypes.Double: |
|
intVal = (ushort)*(double*)&objRef->Value; |
|
break; |
|
default: |
|
throw new NotImplementedException(); |
|
} |
|
objRef->ObjectType = ObjectTypes.Integer; |
|
objRef->Value = intVal; |
|
objRef->ValueLow = 0; |
|
} |
|
break; |
|
case OpCodeEnum.Conv_I2: |
|
case OpCodeEnum.Conv_Ovf_I2: |
|
case OpCodeEnum.Conv_Ovf_I2_Un: |
|
{ |
|
objRef = esp - 1; |
|
switch (objRef->ObjectType) |
|
{ |
|
case ObjectTypes.Long: |
|
case ObjectTypes.Integer: |
|
intVal = (short)(objRef->Value); |
|
break; |
|
case ObjectTypes.Float: |
|
intVal = (short)*(float*)&objRef->Value; |
|
break; |
|
case ObjectTypes.Double: |
|
intVal = (short)*(double*)&objRef->Value; |
|
break; |
|
default: |
|
throw new NotImplementedException(); |
|
} |
|
objRef->ObjectType = ObjectTypes.Integer; |
|
objRef->Value = intVal; |
|
objRef->ValueLow = 0; |
|
} |
|
break; |
|
case OpCodeEnum.Conv_U4: |
|
case OpCodeEnum.Conv_U: |
|
case OpCodeEnum.Conv_Ovf_U4: |
|
case OpCodeEnum.Conv_Ovf_U4_Un: |
|
{ |
|
objRef = esp - 1; |
|
uint uintVal; |
|
switch (objRef->ObjectType) |
|
{ |
|
case ObjectTypes.Long: |
|
uintVal = (uint)*(long*)&objRef->Value; |
|
break; |
|
case ObjectTypes.Integer: |
|
uintVal = (uint)objRef->Value; |
|
break; |
|
case ObjectTypes.Float: |
|
uintVal = (uint)*(float*)&objRef->Value; |
|
break; |
|
case ObjectTypes.Double: |
|
uintVal = (uint)*(double*)&objRef->Value; |
|
break; |
|
default: |
|
throw new NotImplementedException(); |
|
} |
|
objRef->ObjectType = ObjectTypes.Integer; |
|
objRef->Value = (int)uintVal; |
|
objRef->ValueLow = 0; |
|
} |
|
break; |
|
case OpCodeEnum.Conv_I4: |
|
case OpCodeEnum.Conv_I: |
|
case OpCodeEnum.Conv_Ovf_I: |
|
case OpCodeEnum.Conv_Ovf_I_Un: |
|
case OpCodeEnum.Conv_Ovf_I4: |
|
case OpCodeEnum.Conv_Ovf_I4_Un: |
|
{ |
|
objRef = esp - 1; |
|
switch (objRef->ObjectType) |
|
{ |
|
case ObjectTypes.Long: |
|
intVal = (int)*(long*)&objRef->Value; |
|
break; |
|
case ObjectTypes.Float: |
|
intVal = (int)*(float*)&objRef->Value; |
|
break; |
|
case ObjectTypes.Double: |
|
intVal = (int)*(double*)&objRef->Value; |
|
break; |
|
case ObjectTypes.Integer: |
|
intVal = objRef->Value; |
|
break; |
|
default: |
|
throw new NotImplementedException(); |
|
} |
|
objRef->ObjectType = ObjectTypes.Integer; |
|
objRef->Value = intVal; |
|
} |
|
break; |
|
case OpCodeEnum.Conv_I8: |
|
case OpCodeEnum.Conv_Ovf_I8: |
|
case OpCodeEnum.Conv_Ovf_I8_Un: |
|
{ |
|
objRef = esp - 1; |
|
long longVal; |
|
switch (objRef->ObjectType) |
|
{ |
|
case ObjectTypes.Integer: |
|
longVal = objRef->Value; |
|
break; |
|
case ObjectTypes.Long: |
|
ip++; |
|
continue; |
|
case ObjectTypes.Float: |
|
longVal = (long)*(float*)&objRef->Value; |
|
break; |
|
case ObjectTypes.Double: |
|
longVal = (long)*(double*)&objRef->Value; |
|
break; |
|
default: |
|
throw new NotImplementedException(); |
|
} |
|
objRef->ObjectType = ObjectTypes.Long; |
|
*(long*)(&objRef->Value) = longVal; |
|
} |
|
break; |
|
|
|
case OpCodeEnum.Conv_U8: |
|
case OpCodeEnum.Conv_Ovf_U8: |
|
case OpCodeEnum.Conv_Ovf_U8_Un: |
|
{ |
|
objRef = esp - 1; |
|
ulong ulongVal; |
|
switch (objRef->ObjectType) |
|
{ |
|
case ObjectTypes.Integer: |
|
ulongVal = (uint)objRef->Value; |
|
break; |
|
case ObjectTypes.Long: |
|
ip++; |
|
continue; |
|
case ObjectTypes.Float: |
|
ulongVal = (ulong)*(float*)&objRef->Value; |
|
break; |
|
case ObjectTypes.Double: |
|
ulongVal = (ulong)*(double*)&objRef->Value; |
|
break; |
|
default: |
|
throw new NotImplementedException(); |
|
} |
|
objRef->ObjectType = ObjectTypes.Long; |
|
*(ulong*)(&objRef->Value) = ulongVal; |
|
} |
|
break; |
|
case OpCodeEnum.Conv_R4: |
|
{ |
|
objRef = esp - 1; |
|
float floatVal; |
|
switch (objRef->ObjectType) |
|
{ |
|
case ObjectTypes.Long: |
|
floatVal = (float)*(long*)&objRef->Value; |
|
break; |
|
case ObjectTypes.Float: |
|
ip++; |
|
continue; |
|
case ObjectTypes.Double: |
|
floatVal = (float)*(double*)&objRef->Value; |
|
break; |
|
case ObjectTypes.Integer: |
|
floatVal = objRef->Value; |
|
break; |
|
default: |
|
throw new NotImplementedException(); |
|
} |
|
objRef->ObjectType = ObjectTypes.Float; |
|
*(float*)&objRef->Value = floatVal; |
|
} |
|
break; |
|
case OpCodeEnum.Conv_R8: |
|
{ |
|
objRef = esp - 1; |
|
double doubleVal; |
|
switch (objRef->ObjectType) |
|
{ |
|
case ObjectTypes.Long: |
|
doubleVal = (double)*(long*)&objRef->Value; |
|
break; |
|
case ObjectTypes.Float: |
|
doubleVal = *(float*)&objRef->Value; |
|
break; |
|
case ObjectTypes.Integer: |
|
doubleVal = objRef->Value; |
|
break; |
|
case ObjectTypes.Double: |
|
ip++; |
|
continue; |
|
default: |
|
throw new NotImplementedException(); |
|
} |
|
objRef->ObjectType = ObjectTypes.Double; |
|
*(double*)&objRef->Value = doubleVal; |
|
} |
|
break; |
|
case OpCodeEnum.Conv_R_Un: |
|
{ |
|
objRef = esp - 1; |
|
bool isDouble = false; |
|
float floatVal = 0; |
|
double val2 = 0; |
|
switch (objRef->ObjectType) |
|
{ |
|
case ObjectTypes.Long: |
|
val2 = (double)*(ulong*)&objRef->Value; |
|
isDouble = true; |
|
break; |
|
case ObjectTypes.Float: |
|
ip++; |
|
continue; |
|
case ObjectTypes.Integer: |
|
floatVal = (uint)objRef->Value; |
|
break; |
|
case ObjectTypes.Double: |
|
ip++; |
|
continue; |
|
default: |
|
throw new NotImplementedException(); |
|
} |
|
if (isDouble) |
|
{ |
|
objRef->ObjectType = ObjectTypes.Double; |
|
*(double*)&objRef->Value = val2; |
|
} |
|
else |
|
{ |
|
objRef->ObjectType = ObjectTypes.Float; |
|
*(float*)&objRef->Value = floatVal; |
|
} |
|
} |
|
break; |
|
#endregion |
|
|
|
#region Stack operation |
|
case OpCodeEnum.Pop: |
|
{ |
|
Free(esp - 1); |
|
esp--; |
|
} |
|
break; |
|
case OpCodeEnum.Dup: |
|
{ |
|
objRef = esp - 1; |
|
if (objRef->ObjectType == ObjectTypes.ValueTypeObjectReference) |
|
{ |
|
CloneStackValueType(objRef, esp, mStack); |
|
} |
|
else |
|
{ |
|
*esp = *objRef; |
|
if (esp->ObjectType >= ObjectTypes.Object) |
|
{ |
|
esp->Value = mStack.Count; |
|
mStack.Add(mStack[objRef->Value]); |
|
} |
|
} |
|
esp++; |
|
} |
|
break; |
|
#endregion |
|
|
|
case OpCodeEnum.Throw: |
|
{ |
|
objRef = GetObjectAndResolveReference(esp - 1); |
|
var ex = mStack[objRef->Value] as Exception; |
|
Free(objRef); |
|
esp--; |
|
throw ex; |
|
} |
|
case OpCodeEnum.Rethrow: |
|
{ |
|
throw lastCaughtEx; |
|
} |
|
case OpCodeEnum.Nop: |
|
case OpCodeEnum.Volatile: |
|
case OpCodeEnum.Readonly: |
|
break; |
|
default: |
|
throw new NotSupportedException("Not supported opcode " + code); |
|
} |
|
ip++; |
|
} |
|
catch (Exception ex) |
|
{ |
|
if (ehs != null) |
|
{ |
|
int addr = (int)(ip - ptr); |
|
var eh = GetCorrespondingExceptionHandler(ehs, ex, addr, ExceptionHandlerType.Catch, true); |
|
|
|
if (eh == null) |
|
{ |
|
eh = GetCorrespondingExceptionHandler(ehs, ex, addr, ExceptionHandlerType.Catch, false); |
|
} |
|
if (eh != null) |
|
{ |
|
if (ex is ILRuntimeException) |
|
{ |
|
ILRuntimeException ire = (ILRuntimeException)ex; |
|
var inner = ire.InnerException; |
|
inner.Data["ThisInfo"] = ire.ThisInfo; |
|
inner.Data["StackTrace"] = inner.Data.Contains("StackTrace") ? string.Format("{0}\n--- End of stack trace from previous location ---\n{1}", ire.StackTrace, inner.Data["StackTrace"]) : ire.StackTrace; |
|
inner.Data["LocalInfo"] = ire.LocalInfo; |
|
ex = inner; |
|
} |
|
else |
|
{ |
|
var debugger = AppDomain.DebugService; |
|
if (method.HasThis) |
|
ex.Data["ThisInfo"] = debugger.GetThisInfo(this); |
|
else |
|
ex.Data["ThisInfo"] = ""; |
|
ex.Data["StackTrace"] = ex.Data.Contains("StackTrace") ? string.Format("{0}\n--- End of stack trace from previous location ---\n{1}", debugger.GetStackTrace(this), ex.Data["StackTrace"]) : debugger.GetStackTrace(this); |
|
ex.Data["LocalInfo"] = debugger.GetLocalVariableInfo(this); |
|
} |
|
//Clear call stack |
|
while (stack.Frames.Peek().BasePointer != frame.BasePointer) |
|
{ |
|
var f = stack.Frames.Peek(); |
|
esp = stack.PopFrame(ref f, esp); |
|
if (f.Method.ReturnType != AppDomain.VoidType) |
|
{ |
|
Free(esp - 1); |
|
esp--; |
|
} |
|
} |
|
lastCaughtEx = ex; |
|
esp = PushObject(esp, mStack, ex); |
|
unhandledException = false; |
|
var eh2 = FindExceptionHandlerByBranchTarget(addr, eh.HandlerStart, ehs); |
|
if (eh2 != null) |
|
{ |
|
finallyEndAddress = eh.HandlerStart; |
|
ip = ptr + eh2.HandlerStart; |
|
continue; |
|
} |
|
ip = ptr + eh.HandlerStart; |
|
continue; |
|
} |
|
|
|
eh = GetCorrespondingExceptionHandler(ehs, null, addr, ExceptionHandlerType.Fault, false); |
|
if(eh == null) |
|
eh = GetCorrespondingExceptionHandler(ehs, null, addr, ExceptionHandlerType.Finally, false); |
|
if(eh != null) |
|
{ |
|
unhandledException = false; |
|
finallyEndAddress = -1; |
|
lastCaughtEx = ex is ILRuntimeException ? ex : new ILRuntimeException(ex.Message, this, method, ex); |
|
ip = ptr + eh.HandlerStart; |
|
continue; |
|
} |
|
} |
|
if (unhandledException) |
|
{ |
|
throw ex; |
|
} |
|
|
|
unhandledException = true; |
|
returned = true; |
|
#if DEBUG && !DISABLE_ILRUNTIME_DEBUG |
|
if (!AppDomain.DebugService.Break(this, ex)) |
|
#endif |
|
{ |
|
var newEx = new ILRuntimeException(ex.Message, this, method, ex); |
|
throw newEx; |
|
} |
|
} |
|
} |
|
} |
|
#if DEBUG && !NO_PROFILER |
|
if (System.Threading.Thread.CurrentThread.ManagedThreadId == AppDomain.UnityMainThreadID) |
|
#if UNITY_5_5_OR_NEWER |
|
UnityEngine.Profiling.Profiler.EndSample(); |
|
#else |
|
UnityEngine.Profiler.EndSample(); |
|
#endif |
|
#endif |
|
//ClearStack |
|
return stack.PopFrame(ref frame, esp); |
|
} |
|
ExceptionHandler FindExceptionHandlerByBranchTarget(int addr, int branchTarget, ExceptionHandler[] ehs) |
|
{ |
|
ExceptionHandler eh = null; |
|
for (int i = 0; i < ehs.Length; i++) |
|
{ |
|
var e = ehs[i]; |
|
if (addr >= e.TryStart && addr <= e.TryEnd && (branchTarget < e.TryStart || branchTarget > e.TryEnd) && e.HandlerType == ExceptionHandlerType.Finally) |
|
{ |
|
eh = e; |
|
break; |
|
} |
|
} |
|
return eh; |
|
} |
|
void PrepareRegisterCallStack(StackObject* esp, IList<object> mStack, ILMethod method) |
|
{ |
|
var pCnt = method.HasThis ? method.ParameterCount + 1 : method.ParameterCount; |
|
StackObject* basePointer = esp - pCnt; |
|
int mBase = mStack.Count; |
|
int existing = 0; |
|
for (int i = 0; i < pCnt; i++) |
|
{ |
|
StackObject* cur = basePointer + i; |
|
if (cur->ObjectType < ObjectTypes.Object) |
|
{ |
|
mStack.Add(null); |
|
} |
|
else |
|
existing++; |
|
} |
|
if (existing > 0) |
|
{ |
|
mBase = mBase - existing; |
|
for (int i = pCnt - 1; i >= 0; i--) |
|
{ |
|
StackObject* cur = basePointer + i; |
|
if (cur->ObjectType >= ObjectTypes.Object) |
|
{ |
|
mStack[mBase + i] = mStack[cur->Value]; |
|
cur->Value = mBase + i; |
|
} |
|
else |
|
{ |
|
if (cur->ObjectType == ObjectTypes.Null) |
|
{ |
|
cur->ObjectType = ObjectTypes.Object; |
|
cur->Value = mBase + i; |
|
} |
|
mStack[mBase + i] = null; |
|
} |
|
} |
|
} |
|
} |
|
|
|
void DumpStack(StackObject* esp) |
|
{ |
|
AppDomain.DebugService.DumpStack(esp, stack); |
|
} |
|
|
|
void CloneStackValueType(StackObject* src, StackObject* dst, IList<object> mStack) |
|
{ |
|
StackObject* descriptor = ILIntepreter.ResolveReference(src); |
|
stack.AllocValueType(dst, AppDomain.GetTypeByIndex(descriptor->Value)); |
|
StackObject* dstDescriptor = ILIntepreter.ResolveReference(dst); |
|
int cnt = descriptor->ValueLow; |
|
for (int i = 0; i < cnt; i++) |
|
{ |
|
StackObject* val = Minus(descriptor, i + 1); |
|
CopyToValueTypeField(dstDescriptor, i, val, mStack); |
|
} |
|
} |
|
|
|
bool CanCastTo(StackObject* src, StackObject* dst) |
|
{ |
|
var sType = AppDomain.GetTypeByIndex(src->Value); |
|
var dType = AppDomain.GetTypeByIndex(dst->Value); |
|
return sType.CanAssignTo(dType); |
|
|
|
} |
|
|
|
bool CanCopyStackValueType(StackObject* src, StackObject* dst) |
|
{ |
|
if (src->ObjectType == ObjectTypes.ValueTypeObjectReference && dst->ObjectType == ObjectTypes.ValueTypeObjectReference) |
|
{ |
|
StackObject* descriptor = ILIntepreter.ResolveReference(src); |
|
StackObject* dstDescriptor = ILIntepreter.ResolveReference(dst); |
|
return CanCastTo(descriptor, dstDescriptor); |
|
} |
|
else |
|
return false; |
|
} |
|
#if DEBUG |
|
public void CopyStackValueType(StackObject* src, StackObject* dst, IList<object> mStack, bool noCheck = false) |
|
#else |
|
public void CopyStackValueType(StackObject* src, StackObject* dst, IList<object> mStack) |
|
#endif |
|
{ |
|
#if DEBUG |
|
CopyStackValueType(src, dst, mStack, mStack, noCheck); |
|
#else |
|
CopyStackValueType(src, dst, mStack, mStack); |
|
#endif |
|
} |
|
#if DEBUG |
|
public void CopyStackValueType(StackObject* src, StackObject* dst, IList<object> mStack, IList<object> dstmStack, bool noCheck = false) |
|
#else |
|
public void CopyStackValueType(StackObject* src, StackObject* dst, IList<object> mStack, IList<object> dstmStack) |
|
#endif |
|
{ |
|
StackObject* descriptor = ILIntepreter.ResolveReference(src); |
|
StackObject* dstDescriptor = ILIntepreter.ResolveReference(dst); |
|
#if DEBUG |
|
if (!CanCastTo(descriptor, dstDescriptor)) |
|
throw new InvalidCastException(); |
|
#endif |
|
int cnt = descriptor->ValueLow; |
|
for (int i = 0; i < cnt; i++) |
|
{ |
|
StackObject* srcVal = Minus(descriptor, i + 1); |
|
StackObject* dstVal = Minus(dstDescriptor, i + 1); |
|
#if DEBUG |
|
if (!noCheck && srcVal->ObjectType != dstVal->ObjectType) |
|
throw new NotSupportedException(); |
|
#endif |
|
switch (srcVal->ObjectType) |
|
{ |
|
case ObjectTypes.Object: |
|
case ObjectTypes.ArrayReference: |
|
case ObjectTypes.FieldReference: |
|
dstmStack[dstVal->Value] = mStack[srcVal->Value]; |
|
break; |
|
case ObjectTypes.ValueTypeObjectReference: |
|
CopyStackValueType(srcVal, dstVal, mStack, dstmStack); |
|
break; |
|
default: |
|
*dstVal = *srcVal; |
|
break; |
|
} |
|
} |
|
} |
|
|
|
void CopyValueTypeToStack(StackObject* dst, object ins, IList<object> mStack) |
|
{ |
|
if (ins is ILTypeInstance) |
|
{ |
|
((ILTypeInstance)ins).CopyValueTypeToStack(dst, mStack); |
|
} |
|
else |
|
{ |
|
if (ins is CrossBindingAdaptorType) |
|
{ |
|
((CrossBindingAdaptorType)ins).ILInstance.CopyValueTypeToStack(dst, mStack); |
|
} |
|
else |
|
{ |
|
var vb = ((CLRType)domain.GetTypeByIndex(dst->Value)).ValueTypeBinder; |
|
vb.CopyValueTypeToStack(ins, dst, mStack); |
|
} |
|
} |
|
} |
|
|
|
void CopyToValueTypeField(StackObject* obj, int idx, StackObject* val, IList<object> mStack) |
|
{ |
|
StackObject* dst = Minus(obj, idx + 1); |
|
switch (val->ObjectType) |
|
{ |
|
case ObjectTypes.Null: |
|
{ |
|
mStack[dst->Value] = null; |
|
} |
|
break; |
|
case ObjectTypes.Object: |
|
case ObjectTypes.FieldReference: |
|
case ObjectTypes.ArrayReference: |
|
{ |
|
if (dst->ObjectType == ObjectTypes.ValueTypeObjectReference) |
|
{ |
|
var ins = mStack[val->Value]; |
|
dst = ILIntepreter.ResolveReference(dst); |
|
|
|
CopyValueTypeToStack(dst, ins, mStack); |
|
} |
|
else |
|
{ |
|
mStack[dst->Value] = CheckAndCloneValueType(mStack[val->Value], domain); |
|
} |
|
} |
|
break; |
|
case ObjectTypes.ValueTypeObjectReference: |
|
{ |
|
if (dst->ObjectType == ObjectTypes.ValueTypeObjectReference) |
|
{ |
|
CopyStackValueType(val, dst, mStack); |
|
} |
|
else |
|
throw new NotImplementedException(); |
|
} |
|
break; |
|
default: |
|
*dst = *val; |
|
break; |
|
} |
|
} |
|
|
|
void StLocSub(StackObject* esp, StackObject* v, int idx, IList<object> mStack) |
|
{ |
|
switch (esp->ObjectType) |
|
{ |
|
case ObjectTypes.Null: |
|
v->ObjectType = ObjectTypes.Object; |
|
v->Value = idx; |
|
mStack[idx] = null; |
|
break; |
|
case ObjectTypes.Object: |
|
case ObjectTypes.FieldReference: |
|
case ObjectTypes.ArrayReference: |
|
if (v->ObjectType == ObjectTypes.ValueTypeObjectReference) |
|
{ |
|
var obj = mStack[esp->Value]; |
|
if (obj is ILTypeInstance) |
|
{ |
|
var dst = ILIntepreter.ResolveReference(v); |
|
((ILTypeInstance)obj).CopyValueTypeToStack(dst, mStack); |
|
} |
|
else |
|
{ |
|
var dst = ILIntepreter.ResolveReference(v); |
|
var ct = domain.GetTypeByIndex(dst->Value) as CLRType; |
|
var binder = ct.ValueTypeBinder; |
|
binder.CopyValueTypeToStack(obj, dst, mStack); |
|
} |
|
} |
|
else |
|
{ |
|
*v = *esp; |
|
mStack[idx] = CheckAndCloneValueType(mStack[v->Value], domain); |
|
v->Value = idx; |
|
} |
|
Free(esp); |
|
break; |
|
case ObjectTypes.ValueTypeObjectReference: |
|
if (v->ObjectType == ObjectTypes.ValueTypeObjectReference) |
|
{ |
|
CopyStackValueType(esp, v, mStack); |
|
} |
|
else |
|
throw new NotImplementedException(); |
|
FreeStackValueType(esp); |
|
break; |
|
default: |
|
*v = *esp; |
|
mStack[idx] = null; |
|
break; |
|
} |
|
} |
|
|
|
public object RetriveObject(StackObject* esp, IList<object> mStack) |
|
{ |
|
StackObject* objRef = GetObjectAndResolveReference(esp); |
|
if (objRef->ObjectType == ObjectTypes.Null) |
|
return null; |
|
object obj = null; |
|
switch (objRef->ObjectType) |
|
{ |
|
case ObjectTypes.Object: |
|
obj = mStack[objRef->Value]; |
|
break; |
|
case ObjectTypes.FieldReference: |
|
{ |
|
obj = mStack[objRef->Value]; |
|
int idx = objRef->ValueLow; |
|
if (obj is ILTypeInstance) |
|
{ |
|
obj = ((ILTypeInstance)obj)[idx]; |
|
} |
|
else |
|
{ |
|
var t = AppDomain.GetType(obj.GetType()); |
|
obj = ((CLRType)t).GetFieldValue(idx, obj); |
|
} |
|
} |
|
break; |
|
case ObjectTypes.ArrayReference: |
|
{ |
|
Array arr = mStack[objRef->Value] as Array; |
|
int idx = objRef->ValueLow; |
|
obj = arr.GetValue(idx); |
|
} |
|
break; |
|
case ObjectTypes.StaticFieldReference: |
|
{ |
|
var t = AppDomain.GetType(objRef->Value); |
|
int idx = objRef->ValueLow; |
|
if (t is ILType) |
|
{ |
|
obj = ((ILType)t).StaticInstance[idx]; |
|
} |
|
else |
|
{ |
|
obj = ((CLRType)t).GetFieldValue(idx, null); |
|
} |
|
} |
|
break; |
|
case ObjectTypes.ValueTypeObjectReference: |
|
obj = StackObject.ToObject(objRef, domain, mStack); |
|
break; |
|
default: |
|
throw new NotImplementedException(); |
|
} |
|
return obj; |
|
} |
|
|
|
public int RetriveInt32(StackObject* esp, IList<object> mStack) |
|
{ |
|
StackObject* objRef = GetObjectAndResolveReference(esp); |
|
if (objRef->ObjectType == ObjectTypes.Null) |
|
return 0; |
|
object obj = null; |
|
int res = 0; |
|
switch (objRef->ObjectType) |
|
{ |
|
case ObjectTypes.Object: |
|
res = (int)mStack[objRef->Value]; |
|
break; |
|
case ObjectTypes.Integer: |
|
res = objRef->Value; |
|
break; |
|
case ObjectTypes.FieldReference: |
|
{ |
|
obj = mStack[objRef->Value]; |
|
int idx = objRef->ValueLow; |
|
if (obj is ILTypeInstance) |
|
{ |
|
res = ((ILTypeInstance)obj).Fields[idx].Value; |
|
} |
|
else |
|
{ |
|
var t = AppDomain.GetType(obj.GetType()); |
|
StackObject so; |
|
var sop = &so; |
|
if (!((CLRType)t).CopyFieldToStack(idx, obj, this, ref sop, mStack)) |
|
res = (int)((CLRType)t).GetFieldValue(idx, obj); |
|
else |
|
{ |
|
res = so.Value; |
|
} |
|
} |
|
} |
|
break; |
|
case ObjectTypes.ArrayReference: |
|
{ |
|
Array arr = mStack[objRef->Value] as Array; |
|
int idx = objRef->ValueLow; |
|
if (arr is int[]) |
|
res = ((int[])arr)[idx]; |
|
else |
|
{ |
|
res = (int)Convert.ToInt32(arr.GetValue(idx)); |
|
} |
|
} |
|
break; |
|
case ObjectTypes.StaticFieldReference: |
|
{ |
|
var t = AppDomain.GetType(objRef->Value); |
|
int idx = objRef->ValueLow; |
|
if (t is ILType) |
|
{ |
|
res = ((ILType)t).StaticInstance.Fields[idx].Value; |
|
} |
|
else |
|
{ |
|
StackObject so; |
|
var sop = &so; |
|
if (!((CLRType)t).CopyFieldToStack(idx, null, this, ref sop, mStack)) |
|
res = (int)((CLRType)t).GetFieldValue(idx, null); |
|
else |
|
{ |
|
res = so.Value; |
|
} |
|
} |
|
} |
|
break; |
|
default: |
|
throw new NotImplementedException(); |
|
} |
|
return res; |
|
} |
|
|
|
public long RetriveInt64(StackObject* esp, IList<object> mStack) |
|
{ |
|
StackObject* objRef = GetObjectAndResolveReference(esp); |
|
if (objRef->ObjectType == ObjectTypes.Null) |
|
return 0; |
|
object obj = null; |
|
long res = 0; |
|
switch (objRef->ObjectType) |
|
{ |
|
case ObjectTypes.Object: |
|
res = (long)mStack[objRef->Value]; |
|
break; |
|
case ObjectTypes.Long: |
|
res = *(long*)&objRef->Value; |
|
break; |
|
case ObjectTypes.FieldReference: |
|
{ |
|
obj = mStack[objRef->Value]; |
|
int idx = objRef->ValueLow; |
|
StackObject so; |
|
if (obj is ILTypeInstance) |
|
{ |
|
so = ((ILTypeInstance)obj).Fields[idx]; |
|
res = *(long*)&so.Value; |
|
} |
|
else |
|
{ |
|
var t = AppDomain.GetType(obj.GetType()); |
|
var sop = &so; |
|
if (!((CLRType)t).CopyFieldToStack(idx, obj, this, ref sop, mStack)) |
|
res = (long)((CLRType)t).GetFieldValue(idx, obj); |
|
else |
|
{ |
|
res = *(long*)&so.Value; |
|
} |
|
} |
|
} |
|
break; |
|
case ObjectTypes.ArrayReference: |
|
{ |
|
Array arr = mStack[objRef->Value] as Array; |
|
int idx = objRef->ValueLow; |
|
if (arr is long[]) |
|
res = ((long[])arr)[idx]; |
|
else |
|
{ |
|
res = (long)arr.GetValue(idx); |
|
} |
|
} |
|
break; |
|
case ObjectTypes.StaticFieldReference: |
|
{ |
|
var t = AppDomain.GetType(objRef->Value); |
|
int idx = objRef->ValueLow; |
|
StackObject so; |
|
if (t is ILType) |
|
{ |
|
so = ((ILType)t).StaticInstance.Fields[idx]; |
|
res = *(long*)&so.Value; |
|
} |
|
else |
|
{ |
|
var sop = &so; |
|
if (!((CLRType)t).CopyFieldToStack(idx, null, this, ref sop, mStack)) |
|
res = (long)((CLRType)t).GetFieldValue(idx, null); |
|
else |
|
{ |
|
res = *(long*)&so.Value; |
|
} |
|
} |
|
} |
|
break; |
|
default: |
|
throw new NotImplementedException(); |
|
} |
|
return res; |
|
} |
|
|
|
public float RetriveFloat(StackObject* esp, IList<object> mStack) |
|
{ |
|
StackObject* objRef = GetObjectAndResolveReference(esp); |
|
if (objRef->ObjectType == ObjectTypes.Null) |
|
return 0; |
|
object obj = null; |
|
float res = 0; |
|
switch (objRef->ObjectType) |
|
{ |
|
case ObjectTypes.Object: |
|
res = (float)mStack[objRef->Value]; |
|
break; |
|
case ObjectTypes.Float: |
|
res = *(float*)&objRef->Value; |
|
break; |
|
case ObjectTypes.FieldReference: |
|
{ |
|
obj = mStack[objRef->Value]; |
|
int idx = objRef->ValueLow; |
|
StackObject so; |
|
if (obj is ILTypeInstance) |
|
{ |
|
so = ((ILTypeInstance)obj).Fields[idx]; |
|
res = *(float*)&so.Value; |
|
} |
|
else |
|
{ |
|
var t = AppDomain.GetType(obj.GetType()); |
|
var sop = &so; |
|
if (!((CLRType)t).CopyFieldToStack(idx, obj, this, ref sop, mStack)) |
|
res = (float)((CLRType)t).GetFieldValue(idx, obj); |
|
else |
|
{ |
|
res = *(float*)&so.Value; |
|
} |
|
} |
|
} |
|
break; |
|
case ObjectTypes.ArrayReference: |
|
{ |
|
Array arr = mStack[objRef->Value] as Array; |
|
int idx = objRef->ValueLow; |
|
if (arr is float[]) |
|
res = ((float[])arr)[idx]; |
|
else |
|
{ |
|
res = (float)arr.GetValue(idx); |
|
} |
|
} |
|
break; |
|
case ObjectTypes.StaticFieldReference: |
|
{ |
|
var t = AppDomain.GetType(objRef->Value); |
|
int idx = objRef->ValueLow; |
|
StackObject so; |
|
if (t is ILType) |
|
{ |
|
so = ((ILType)t).StaticInstance.Fields[idx]; |
|
res = *(float*)&so.Value; |
|
} |
|
else |
|
{ |
|
var sop = &so; |
|
if (!((CLRType)t).CopyFieldToStack(idx, null, this, ref sop, mStack)) |
|
res = (float)((CLRType)t).GetFieldValue(idx, null); |
|
else |
|
{ |
|
res = *(float*)&so.Value; |
|
} |
|
} |
|
} |
|
break; |
|
default: |
|
throw new NotImplementedException(); |
|
} |
|
return res; |
|
} |
|
|
|
public double RetriveDouble(StackObject* esp, IList<object> mStack) |
|
{ |
|
StackObject* objRef = GetObjectAndResolveReference(esp); |
|
if (objRef->ObjectType == ObjectTypes.Null) |
|
return 0; |
|
object obj = null; |
|
double res = 0; |
|
switch (objRef->ObjectType) |
|
{ |
|
case ObjectTypes.Object: |
|
res = (double)mStack[objRef->Value]; |
|
break; |
|
case ObjectTypes.Double: |
|
res = *(double*)&objRef->Value; |
|
break; |
|
case ObjectTypes.FieldReference: |
|
{ |
|
obj = mStack[objRef->Value]; |
|
int idx = objRef->ValueLow; |
|
StackObject so; |
|
if (obj is ILTypeInstance) |
|
{ |
|
so = ((ILTypeInstance)obj).Fields[idx]; |
|
res = *(double*)&so.Value; |
|
} |
|
else |
|
{ |
|
var t = AppDomain.GetType(obj.GetType()); |
|
var sop = &so; |
|
if (!((CLRType)t).CopyFieldToStack(idx, obj, this, ref sop, mStack)) |
|
res = (double)((CLRType)t).GetFieldValue(idx, obj); |
|
else |
|
{ |
|
res = *(double*)&so.Value; |
|
} |
|
} |
|
} |
|
break; |
|
case ObjectTypes.ArrayReference: |
|
{ |
|
Array arr = mStack[objRef->Value] as Array; |
|
int idx = objRef->ValueLow; |
|
if (arr is double[]) |
|
res = ((double[])arr)[idx]; |
|
else |
|
{ |
|
res = (double)arr.GetValue(idx); |
|
} |
|
} |
|
break; |
|
case ObjectTypes.StaticFieldReference: |
|
{ |
|
var t = AppDomain.GetType(objRef->Value); |
|
int idx = objRef->ValueLow; |
|
StackObject so; |
|
if (t is ILType) |
|
{ |
|
so = ((ILType)t).StaticInstance.Fields[idx]; |
|
res = *(double*)&so.Value; |
|
} |
|
else |
|
{ |
|
var sop = &so; |
|
if (!((CLRType)t).CopyFieldToStack(idx, null, this, ref sop, mStack)) |
|
res = (double)((CLRType)t).GetFieldValue(idx, null); |
|
else |
|
{ |
|
res = *(double*)&so.Value; |
|
} |
|
} |
|
} |
|
break; |
|
default: |
|
throw new NotImplementedException(); |
|
} |
|
return res; |
|
} |
|
|
|
void ArraySetValue(Array arr, object obj, int idx) |
|
{ |
|
if (obj == null) |
|
arr.SetValue(null, idx); |
|
else |
|
{ |
|
arr.SetValue(arr.GetType().GetElementType().CheckCLRTypes(obj), idx); |
|
} |
|
} |
|
|
|
void StoreIntValueToArray(Array arr, StackObject* val, StackObject* idx) |
|
{ |
|
{ |
|
int[] tmp = arr as int[]; |
|
if (tmp != null) |
|
{ |
|
tmp[idx->Value] = val->Value; |
|
return; |
|
} |
|
} |
|
{ |
|
short[] tmp = arr as short[]; |
|
if (tmp != null) |
|
{ |
|
tmp[idx->Value] = (short)val->Value; |
|
return; |
|
} |
|
} |
|
{ |
|
byte[] tmp = arr as byte[]; |
|
if (tmp != null) |
|
{ |
|
tmp[idx->Value] = (byte)val->Value; |
|
return; |
|
} |
|
} |
|
{ |
|
bool[] tmp = arr as bool[]; |
|
if (tmp != null) |
|
{ |
|
tmp[idx->Value] = val->Value == 1; |
|
return; |
|
} |
|
} |
|
{ |
|
uint[] tmp = arr as uint[]; |
|
if (tmp != null) |
|
{ |
|
tmp[idx->Value] = (uint)val->Value; |
|
return; |
|
} |
|
} |
|
{ |
|
ushort[] tmp = arr as ushort[]; |
|
if (tmp != null) |
|
{ |
|
tmp[idx->Value] = (ushort)val->Value; |
|
return; |
|
} |
|
} |
|
{ |
|
char[] tmp = arr as char[]; |
|
if (tmp != null) |
|
{ |
|
tmp[idx->Value] = (char)val->Value; |
|
return; |
|
} |
|
} |
|
{ |
|
sbyte[] tmp = arr as sbyte[]; |
|
if (tmp != null) |
|
{ |
|
tmp[idx->Value] = (sbyte)val->Value; |
|
return; |
|
} |
|
} |
|
throw new NotImplementedException(); |
|
} |
|
|
|
ExceptionHandler GetCorrespondingExceptionHandler(ExceptionHandler[] eh, object obj, int addr, ExceptionHandlerType type, bool explicitMatch) |
|
{ |
|
ExceptionHandler res = null; |
|
int distance = int.MaxValue; |
|
Exception ex = obj is ILRuntimeException ? ((ILRuntimeException)obj).InnerException : obj as Exception; |
|
foreach (var i in eh) |
|
{ |
|
if (i.HandlerType == type) |
|
{ |
|
if (addr >= i.TryStart && addr <= i.TryEnd) |
|
{ |
|
if (CheckExceptionType(i.CatchType, ex, explicitMatch)) |
|
{ |
|
int d = addr - i.TryStart; |
|
if (d < distance) |
|
{ |
|
distance = d; |
|
res = i; |
|
} |
|
} |
|
} |
|
} |
|
} |
|
return res; |
|
} |
|
|
|
void LoadFromFieldReference(object obj, int idx, StackObject* dst, IList<object> mStack) |
|
{ |
|
if (obj is ILTypeInstance) |
|
{ |
|
((ILTypeInstance)obj).PushToStack(idx, dst, this, mStack); |
|
} |
|
else |
|
{ |
|
CLRType t = AppDomain.GetType(obj.GetType()) as CLRType; |
|
if (!t.CopyFieldToStack(idx, obj, this, ref dst, mStack)) |
|
ILIntepreter.PushObject(dst, mStack, t.GetFieldValue(idx, obj)); |
|
} |
|
} |
|
|
|
void StoreValueToFieldReference(ref object obj, int idx, StackObject* val, IList<object> mStack) |
|
{ |
|
if (obj is ILTypeInstance) |
|
{ |
|
((ILTypeInstance)obj).AssignFromStack(idx, val, AppDomain, mStack); |
|
} |
|
else |
|
{ |
|
CLRType t = AppDomain.GetType(obj.GetType()) as CLRType; |
|
//It's impossible to garantee this field reference is a direct reference, it'll cause problem if it's not |
|
//if (!t.AssignFieldFromStack(idx, ref obj, this, val, mStack)) |
|
{ |
|
var v = obj.GetType().CheckCLRTypes(CheckAndCloneValueType(StackObject.ToObject(val, AppDomain, mStack), AppDomain)); |
|
t.SetFieldValue(idx, ref obj, v, true); |
|
} |
|
} |
|
} |
|
|
|
void LoadFromArrayReference(object obj, int idx, StackObject* objRef, IType t, IList<object> mStack, int managedIdx = -1) |
|
{ |
|
var nT = t.TypeForCLR; |
|
LoadFromArrayReference(obj, idx, objRef, nT, mStack, managedIdx); |
|
} |
|
|
|
void LoadFromArrayReference(object obj, int idx, StackObject* objRef, Type nT, IList<object> mStack, int managedIdx = -1) |
|
{ |
|
if (nT.IsPrimitive) |
|
{ |
|
if (nT == typeof(int)) |
|
{ |
|
int[] arr = obj as int[]; |
|
objRef->ObjectType = ObjectTypes.Integer; |
|
objRef->Value = arr[idx]; |
|
objRef->ValueLow = 0; |
|
} |
|
else if (nT == typeof(short)) |
|
{ |
|
short[] arr = obj as short[]; |
|
objRef->ObjectType = ObjectTypes.Integer; |
|
objRef->Value = arr[idx]; |
|
objRef->ValueLow = 0; |
|
} |
|
else if (nT == typeof(long)) |
|
{ |
|
long[] arr = obj as long[]; |
|
objRef->ObjectType = ObjectTypes.Long; |
|
*(long*)&objRef->Value = arr[idx]; |
|
} |
|
else if (nT == typeof(float)) |
|
{ |
|
float[] arr = obj as float[]; |
|
objRef->ObjectType = ObjectTypes.Float; |
|
*(float*)&objRef->Value = arr[idx]; |
|
objRef->ValueLow = 0; |
|
} |
|
else if (nT == typeof(double)) |
|
{ |
|
double[] arr = obj as double[]; |
|
objRef->ObjectType = ObjectTypes.Double; |
|
*(double*)&objRef->Value = arr[idx]; |
|
} |
|
else if (nT == typeof(byte)) |
|
{ |
|
byte[] arr = obj as byte[]; |
|
objRef->ObjectType = ObjectTypes.Integer; |
|
objRef->Value = arr[idx]; |
|
objRef->ValueLow = 0; |
|
} |
|
else if (nT == typeof(char)) |
|
{ |
|
char[] arr = obj as char[]; |
|
objRef->ObjectType = ObjectTypes.Integer; |
|
objRef->Value = arr[idx]; |
|
objRef->ValueLow = 0; |
|
} |
|
else if (nT == typeof(uint)) |
|
{ |
|
uint[] arr = obj as uint[]; |
|
objRef->ObjectType = ObjectTypes.Integer; |
|
*(uint*)&objRef->Value = arr[idx]; |
|
objRef->ValueLow = 0; |
|
} |
|
else if (nT == typeof(sbyte)) |
|
{ |
|
sbyte[] arr = obj as sbyte[]; |
|
objRef->ObjectType = ObjectTypes.Integer; |
|
objRef->Value = arr[idx]; |
|
objRef->ValueLow = 0; |
|
} |
|
else if (nT == typeof(ulong)) |
|
{ |
|
ulong[] arr = obj as ulong[]; |
|
objRef->ObjectType = ObjectTypes.Long; |
|
*(ulong*)&objRef->Value = arr[idx]; |
|
} |
|
else |
|
throw new NotImplementedException(); |
|
} |
|
else |
|
{ |
|
Array arr = obj as Array; |
|
objRef->ObjectType = ObjectTypes.Object; |
|
if (managedIdx >= 0) |
|
{ |
|
objRef->Value = managedIdx; |
|
mStack[managedIdx] = arr.GetValue(idx); |
|
} |
|
else |
|
{ |
|
objRef->Value = mStack.Count; |
|
mStack.Add(arr.GetValue(idx)); |
|
} |
|
objRef->ValueLow = 0; |
|
} |
|
} |
|
|
|
void StoreValueToArrayReference(StackObject* objRef, StackObject* val, IType t, IList<object> mStack) |
|
{ |
|
var nT = t.TypeForCLR; |
|
StoreValueToArrayReference(objRef, val, nT, mStack); |
|
} |
|
|
|
void StoreValueToArrayReference(StackObject* objRef, StackObject* val, Type nT, IList<object> mStack) |
|
{ |
|
if (nT.IsPrimitive) |
|
{ |
|
if (nT == typeof(int)) |
|
{ |
|
int[] arr = mStack[objRef->Value] as int[]; |
|
arr[objRef->ValueLow] = val->Value; |
|
} |
|
else if (nT == typeof(short)) |
|
{ |
|
short[] arr = mStack[objRef->Value] as short[]; |
|
arr[objRef->ValueLow] = (short)val->Value; |
|
} |
|
else if (nT == typeof(long)) |
|
{ |
|
long[] arr = mStack[objRef->Value] as long[]; |
|
arr[objRef->ValueLow] = *(long*)&val->Value; |
|
} |
|
else if (nT == typeof(float)) |
|
{ |
|
float[] arr = mStack[objRef->Value] as float[]; |
|
arr[objRef->ValueLow] = *(float*)&val->Value; |
|
} |
|
else if (nT == typeof(double)) |
|
{ |
|
double[] arr = mStack[objRef->Value] as double[]; |
|
arr[objRef->ValueLow] = *(double*)&val->Value; |
|
} |
|
else if (nT == typeof(byte)) |
|
{ |
|
byte[] arr = mStack[objRef->Value] as byte[]; |
|
arr[objRef->ValueLow] = (byte)val->Value; |
|
} |
|
else if (nT == typeof(char)) |
|
{ |
|
char[] arr = mStack[objRef->Value] as char[]; |
|
arr[objRef->ValueLow] = (char)val->Value; |
|
} |
|
else if (nT == typeof(uint)) |
|
{ |
|
uint[] arr = mStack[objRef->Value] as uint[]; |
|
arr[objRef->ValueLow] = (uint)val->Value; |
|
} |
|
else if (nT == typeof(sbyte)) |
|
{ |
|
sbyte[] arr = mStack[objRef->Value] as sbyte[]; |
|
arr[objRef->ValueLow] = (sbyte)val->Value; |
|
} |
|
else |
|
throw new NotImplementedException(); |
|
} |
|
else |
|
{ |
|
Array arr = mStack[objRef->Value] as Array; |
|
arr.SetValue(StackObject.ToObject(val, domain, mStack), objRef->ValueLow); |
|
} |
|
} |
|
|
|
bool CheckExceptionType(IType catchType, object exception, bool explicitMatch) |
|
{ |
|
if (catchType == null) |
|
return true; |
|
if (catchType is CLRType) |
|
{ |
|
if (explicitMatch) |
|
return exception.GetType() == catchType.TypeForCLR; |
|
else |
|
return catchType.TypeForCLR.IsAssignableFrom(exception.GetType()); |
|
} |
|
else |
|
throw new NotImplementedException(); |
|
} |
|
#if NET_4_6 || NET_STANDARD_2_0 |
|
[System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] |
|
#endif |
|
public static StackObject* ResolveReference(StackObject* esp) |
|
{ |
|
var addr = *(long*)&esp->Value; |
|
return (StackObject*)addr; |
|
} |
|
|
|
#if NET_4_6 || NET_STANDARD_2_0 |
|
[System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] |
|
#endif |
|
public static StackObject* GetObjectAndResolveReference(StackObject* esp) |
|
{ |
|
if (esp->ObjectType == ObjectTypes.StackObjectReference) |
|
{ |
|
return ResolveReference(esp); |
|
} |
|
else |
|
return esp; |
|
} |
|
|
|
StackObject* PushParameters(IMethod method, StackObject* esp, object[] p, bool useRegister) |
|
{ |
|
IList<object> mStack = stack.ManagedStack; |
|
var plist = method.Parameters; |
|
int pCnt = plist != null ? plist.Count : 0; |
|
int pCnt2 = p != null ? p.Length : 0; |
|
if (pCnt != pCnt2) |
|
throw new ArgumentOutOfRangeException("Parameter mismatch"); |
|
if (pCnt2 > 0) |
|
{ |
|
for (int i = 0; i < p.Length; i++) |
|
{ |
|
bool isBox = false; |
|
if (plist != null && i < plist.Count) |
|
isBox = plist[i] == AppDomain.ObjectType; |
|
object obj = p[i]; |
|
if (obj is CrossBindingAdaptorType) |
|
obj = ((CrossBindingAdaptorType)obj).ILInstance; |
|
var res = ILIntepreter.PushObject(esp, mStack, obj, isBox); |
|
if (esp->ObjectType < ObjectTypes.Object && useRegister) |
|
mStack.Add(null); |
|
esp = res; |
|
} |
|
} |
|
return esp; |
|
} |
|
public void CopyToStack(StackObject* dst, StackObject* src, IList<object> mStack) |
|
{ |
|
CopyToStack(dst, src, mStack, mStack); |
|
} |
|
|
|
void CopyToStack(StackObject* dst, StackObject* src, IList<object> mStack, IList<object> dstmStack) |
|
{ |
|
if (src->ObjectType == ObjectTypes.ValueTypeObjectReference) |
|
{ |
|
var descriptor = ResolveReference(src); |
|
var t = domain.GetTypeByIndex(descriptor->Value); |
|
AllocValueType(dst, t); |
|
CopyStackValueType(src, dst, mStack, dstmStack); |
|
} |
|
else |
|
{ |
|
*dst = *src; |
|
if (dst->ObjectType >= ObjectTypes.Object) |
|
{ |
|
dst->Value = dstmStack.Count; |
|
var obj = mStack[src->Value]; |
|
dstmStack.Add(obj); |
|
} |
|
} |
|
} |
|
|
|
internal static object CheckAndCloneValueType(object obj, Enviorment.AppDomain domain) |
|
{ |
|
if (obj != null) |
|
{ |
|
if (obj is ILTypeInstance) |
|
{ |
|
ILTypeInstance ins = obj as ILTypeInstance; |
|
if (ins.IsValueType) |
|
{ |
|
return ins.Clone(); |
|
} |
|
} |
|
else |
|
{ |
|
var type = obj.GetType(); |
|
var typeFlags = type.GetTypeFlags(); |
|
|
|
var isPrimitive = (typeFlags & CLR.Utils.Extensions.TypeFlags.IsPrimitive) != 0; |
|
var isValueType = (typeFlags & CLR.Utils.Extensions.TypeFlags.IsValueType) != 0; |
|
|
|
if (!isPrimitive && isValueType) |
|
{ |
|
var t = domain.GetType(type); |
|
return ((CLRType)t).PerformMemberwiseClone(obj); |
|
} |
|
} |
|
} |
|
return obj; |
|
} |
|
#if NET_4_6 || NET_STANDARD_2_0 |
|
[System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] |
|
#endif |
|
public static StackObject* PushOne(StackObject* esp) |
|
{ |
|
esp->ObjectType = ObjectTypes.Integer; |
|
esp->Value = 1; |
|
return esp + 1; |
|
} |
|
|
|
#if NET_4_6 || NET_STANDARD_2_0 |
|
[System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] |
|
#endif |
|
public static StackObject* PushZero(StackObject* esp) |
|
{ |
|
esp->ObjectType = ObjectTypes.Integer; |
|
esp->Value = 0; |
|
return esp + 1; |
|
} |
|
|
|
#if NET_4_6 || NET_STANDARD_2_0 |
|
[System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] |
|
#endif |
|
public static StackObject* PushNull(StackObject* esp) |
|
{ |
|
esp->ObjectType = ObjectTypes.Null; |
|
esp->Value = -1; |
|
esp->ValueLow = 0; |
|
return esp + 1; |
|
} |
|
|
|
public static void UnboxObject(StackObject* esp, object obj, IList<object> mStack = null, Enviorment.AppDomain domain = null) |
|
{ |
|
if (esp->ObjectType == ObjectTypes.ValueTypeObjectReference && domain != null) |
|
{ |
|
var dst = ILIntepreter.ResolveReference(esp); |
|
var vt = domain.GetTypeByIndex(dst->Value); |
|
|
|
if (obj == null)//Nothing to do |
|
return; |
|
if (obj is ILTypeInstance) |
|
{ |
|
var ins = (ILTypeInstance)obj; |
|
ins.CopyValueTypeToStack(dst, mStack); |
|
} |
|
else if (obj is CrossBindingAdaptorType) |
|
{ |
|
var ins = ((CrossBindingAdaptorType)obj).ILInstance; |
|
ins.CopyValueTypeToStack(dst, mStack); |
|
} |
|
else |
|
{ |
|
((CLRType)vt).ValueTypeBinder.CopyValueTypeToStack(obj, dst, mStack); |
|
} |
|
} |
|
else if(obj == null) |
|
{ |
|
return; |
|
} |
|
else if (obj is int) |
|
{ |
|
esp->ObjectType = ObjectTypes.Integer; |
|
esp->Value = (int)obj; |
|
} |
|
else if (obj is bool) |
|
{ |
|
esp->ObjectType = ObjectTypes.Integer; |
|
esp->Value = (bool)(obj) ? 1 : 0; |
|
} |
|
else if (obj is short) |
|
{ |
|
esp->ObjectType = ObjectTypes.Integer; |
|
esp->Value = (short)obj; |
|
} |
|
else if (obj is long) |
|
{ |
|
esp->ObjectType = ObjectTypes.Long; |
|
*(long*)(&esp->Value) = (long)obj; |
|
} |
|
else if (obj is float) |
|
{ |
|
esp->ObjectType = ObjectTypes.Float; |
|
*(float*)(&esp->Value) = (float)obj; |
|
} |
|
else if (obj is byte) |
|
{ |
|
esp->ObjectType = ObjectTypes.Integer; |
|
esp->Value = (byte)obj; |
|
} |
|
else if (obj is uint) |
|
{ |
|
esp->ObjectType = ObjectTypes.Integer; |
|
esp->Value = (int)(uint)obj; |
|
} |
|
else if (obj is ushort) |
|
{ |
|
esp->ObjectType = ObjectTypes.Integer; |
|
esp->Value = (int)(ushort)obj; |
|
} |
|
else if (obj is char) |
|
{ |
|
esp->ObjectType = ObjectTypes.Integer; |
|
esp->Value = (int)(char)obj; |
|
} |
|
else if (obj is double) |
|
{ |
|
esp->ObjectType = ObjectTypes.Double; |
|
*(double*)(&esp->Value) = (double)obj; |
|
} |
|
else if (obj is ulong) |
|
{ |
|
esp->ObjectType = ObjectTypes.Long; |
|
*(ulong*)(&esp->Value) = (ulong)obj; |
|
} |
|
else if (obj is sbyte) |
|
{ |
|
esp->ObjectType = ObjectTypes.Integer; |
|
esp->Value = (sbyte)obj; |
|
} |
|
else if (obj is Enum) |
|
{ |
|
esp->ObjectType = ObjectTypes.Integer; |
|
esp->Value = Convert.ToInt32(obj); |
|
} |
|
else |
|
throw new NotImplementedException(); |
|
} |
|
|
|
public static StackObject* PushObject(StackObject* esp, IList<object> mStack, object obj, bool isBox = false) |
|
{ |
|
if (obj != null) |
|
{ |
|
if (!isBox) |
|
{ |
|
var typeFlags = obj.GetType().GetTypeFlags(); |
|
|
|
if ((typeFlags & CLR.Utils.Extensions.TypeFlags.IsPrimitive) != 0) |
|
{ |
|
UnboxObject(esp, obj, mStack); |
|
} |
|
else if ((typeFlags & CLR.Utils.Extensions.TypeFlags.IsEnum) != 0) |
|
{ |
|
esp->ObjectType = ObjectTypes.Integer; |
|
esp->Value = Convert.ToInt32(obj); |
|
} |
|
else |
|
{ |
|
esp->ObjectType = ObjectTypes.Object; |
|
esp->Value = mStack.Count; |
|
mStack.Add(obj); |
|
} |
|
} |
|
else |
|
{ |
|
esp->ObjectType = ObjectTypes.Object; |
|
esp->Value = mStack.Count; |
|
mStack.Add(obj); |
|
} |
|
} |
|
else |
|
{ |
|
if (isBox) |
|
{ |
|
esp->ObjectType = ObjectTypes.Object; |
|
esp->Value = mStack.Count; |
|
mStack.Add(obj); |
|
} |
|
else |
|
return PushNull(esp); |
|
} |
|
return esp + 1; |
|
} |
|
|
|
//Don't ask me why add this funky method for this, otherwise Unity won't calculate the right value |
|
#if NET_4_6 || NET_STANDARD_2_0 |
|
[System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] |
|
#endif |
|
public static StackObject* Add(StackObject* a, int b) |
|
{ |
|
return (StackObject*)((long)a + sizeof(StackObject) * b); |
|
} |
|
|
|
#if NET_4_6 || NET_STANDARD_2_0 |
|
[System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] |
|
#endif |
|
public static StackObject* Minus(StackObject* a, int b) |
|
{ |
|
return (StackObject*)((long)a - sizeof(StackObject) * b); |
|
} |
|
|
|
#if NET_4_6 || NET_STANDARD_2_0 |
|
[System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] |
|
#endif |
|
public void Free(StackObject* esp) |
|
{ |
|
switch (esp->ObjectType) |
|
{ |
|
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; |
|
esp->Value = -1; |
|
esp->ValueLow = 0; |
|
#endif |
|
} |
|
public void FreeStackValueType(StackObject* esp) |
|
{ |
|
if (esp->ObjectType == ObjectTypes.ValueTypeObjectReference) |
|
{ |
|
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; |
|
} |
|
} |
|
|
|
public void AllocValueType(StackObject* ptr, IType type) |
|
{ |
|
stack.AllocValueType(ptr, type); |
|
} |
|
} |
|
}
|
|
|