123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555 |
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using ILRuntime.CLR.Method;
- using ILRuntime.CLR.TypeSystem;
- using ILRuntime.CLR.Utils;
- using ILRuntime.Runtime.Intepreter;
- using ILRuntime.Runtime.Stack;
- namespace ILRuntime.Runtime.Enviorment
- {
- public static class PrimitiveConverter<T>
- {
- public static Func<T, int> ToInteger;
- public static Func<int, T> FromInteger;
- public static Func<T, long> ToLong;
- public static Func<long, T> FromLong;
- public static Func<T, float> ToFloat;
- public static Func<float, T> FromFloat;
- public static Func<T, double> ToDouble;
- public static Func<double, T> FromDouble;
- public static int CheckAndInvokeToInteger(T val)
- {
- if (ToInteger != null)
- return ToInteger(val);
- else
- throw new InvalidCastException(string.Format("Cannot cast {0} to System.Int32", typeof(T).FullName));
- }
- public static T CheckAndInvokeFromInteger(int val)
- {
- if (FromInteger != null)
- return FromInteger(val);
- else
- throw new InvalidCastException(string.Format("Cannot cast System.Int32 to {0}", typeof(T).FullName));
- }
- public static long CheckAndInvokeToLong(T val)
- {
- if (ToLong != null)
- return ToLong(val);
- else
- throw new InvalidCastException(string.Format("Cannot cast {0} to System.Int64", typeof(T).FullName));
- }
- public static T CheckAndInvokeFromLong(long val)
- {
- if (FromLong != null)
- return FromLong(val);
- else
- throw new InvalidCastException(string.Format("Cannot cast System.Int64 to {0}", typeof(T).FullName));
- }
- public static float CheckAndInvokeToFloat(T val)
- {
- if (ToFloat != null)
- return ToFloat(val);
- else
- throw new InvalidCastException(string.Format("Cannot cast {0} to System.Single", typeof(T).FullName));
- }
- public static T CheckAndInvokeFromFloat(float val)
- {
- if (FromFloat != null)
- return FromFloat(val);
- else
- throw new InvalidCastException(string.Format("Cannot cast System.Single to {0}", typeof(T).FullName));
- }
- public static double CheckAndInvokeToDouble(T val)
- {
- if (ToDouble != null)
- return ToDouble(val);
- else
- throw new InvalidCastException(string.Format("Cannot cast {0} to System.Double", typeof(T).FullName));
- }
- public static T CheckAndInvokeFromDouble(double val)
- {
- if (FromDouble != null)
- return FromDouble(val);
- else
- throw new InvalidCastException(string.Format("Cannot cast System.Double to {0}", typeof(T).FullName));
- }
- }
- enum InvocationTypes
- {
- Integer,
- Long,
- Float,
- Double,
- Enum,
- ValueType,
- Object,
- }
- public unsafe struct InvocationContext : IDisposable
- {
- StackObject* ebp;
- StackObject* esp;
- AppDomain domain;
- ILIntepreter intp;
- ILMethod method;
- IList<object> mStack;
- bool invocated;
- int paramCnt;
- bool hasReturn;
- bool useRegister;
- static bool defaultConverterIntialized = false;
- internal static void InitializeDefaultConverters()
- {
- if (!defaultConverterIntialized)
- {
- PrimitiveConverter<int>.ToInteger = (a) => a;
- PrimitiveConverter<int>.FromInteger = (a) => a;
- PrimitiveConverter<short>.ToInteger = (a) => a;
- PrimitiveConverter<short>.FromInteger = (a) => (short)a;
- PrimitiveConverter<byte>.ToInteger = (a) => a;
- PrimitiveConverter<byte>.FromInteger = (a) => (byte)a;
- PrimitiveConverter<sbyte>.ToInteger = (a) => a;
- PrimitiveConverter<sbyte>.FromInteger = (a) => (sbyte)a;
- PrimitiveConverter<ushort>.ToInteger = (a) => a;
- PrimitiveConverter<ushort>.FromInteger = (a) => (ushort)a;
- PrimitiveConverter<char>.ToInteger = (a) => a;
- PrimitiveConverter<char>.FromInteger = (a) => (char)a;
- PrimitiveConverter<uint>.ToInteger = (a) => (int)a;
- PrimitiveConverter<uint>.FromInteger = (a) => (uint)a;
- PrimitiveConverter<bool>.ToInteger = (a) => a ? 1 : 0;
- PrimitiveConverter<bool>.FromInteger = (a) => a == 1;
- PrimitiveConverter<long>.ToLong = (a) => a;
- PrimitiveConverter<long>.FromLong = (a) => a;
- PrimitiveConverter<ulong>.ToLong = (a) => (long)a;
- PrimitiveConverter<ulong>.FromLong = (a) => (ulong)a;
- PrimitiveConverter<float>.ToFloat = (a) => a;
- PrimitiveConverter<float>.FromFloat = (a) => a;
- PrimitiveConverter<double>.ToDouble = (a) => a;
- PrimitiveConverter<double>.FromDouble = (a) => a;
- defaultConverterIntialized = true;
- }
- }
- internal static InvocationTypes GetInvocationType<T>()
- {
- var type = typeof(T);
- if (type.IsPrimitive)
- {
- if (type == typeof(int))
- return InvocationTypes.Integer;
- if (type == typeof(short))
- return InvocationTypes.Integer;
- if (type == typeof(bool))
- return InvocationTypes.Integer;
- if (type == typeof(long))
- return InvocationTypes.Long;
- if (type == typeof(float))
- return InvocationTypes.Float;
- if (type == typeof(double))
- return InvocationTypes.Double;
- if (type == typeof(char))
- return InvocationTypes.Integer;
- if (type == typeof(ushort))
- return InvocationTypes.Integer;
- if (type == typeof(uint))
- return InvocationTypes.Integer;
- if (type == typeof(ulong))
- return InvocationTypes.Long;
- if (type == typeof(byte))
- return InvocationTypes.Integer;
- if (type == typeof(sbyte))
- return InvocationTypes.Integer;
- else
- throw new NotImplementedException(string.Format("Not supported type:{0}", type.FullName));
- }
- else if (type.IsEnum)
- {
- if (PrimitiveConverter<T>.ToInteger != null && PrimitiveConverter<T>.FromInteger != null)
- return InvocationTypes.Integer;
- if (PrimitiveConverter<T>.ToLong != null && PrimitiveConverter<T>.FromLong != null)
- return InvocationTypes.Long;
- return InvocationTypes.Enum;
- }
- else if (type.IsValueType)
- return InvocationTypes.ValueType;
- else
- return InvocationTypes.Object;
- }
- internal InvocationContext(ILIntepreter intp, ILMethod method)
- {
- var stack = intp.Stack;
- mStack = stack.ManagedStack;
- esp = stack.StackBase;
- ebp = esp;
- stack.ResetValueTypePointer();
- this.domain = intp.AppDomain;
- this.intp = intp;
- this.method = method;
- invocated = false;
- paramCnt = 0;
- hasReturn = method.ReturnType != domain.VoidType;
- useRegister = method.ShouldUseRegisterVM;
- }
- internal void SetInvoked(StackObject* esp)
- {
- this.esp = esp - 1;
- invocated = true;
- }
- internal StackObject* ESP
- {
- get
- {
- return esp;
- }
- set
- {
- esp = value;
- }
- }
- internal ILIntepreter Intepreter
- {
- get
- {
- return intp;
- }
- }
- internal IList<object> ManagedStack
- {
- get
- {
- return mStack;
- }
- }
- public void PushBool(bool val)
- {
- PushInteger(val ? 1 : 0);
- }
- public void PushInteger<T>(T val)
- {
- PushInteger(PrimitiveConverter<T>.CheckAndInvokeToInteger(val));
- }
- public void PushLong<T>(T val)
- {
- PushInteger(PrimitiveConverter<T>.CheckAndInvokeToLong(val));
- }
- public void PushInteger(int val)
- {
- esp->ObjectType = ObjectTypes.Integer;
- esp->Value = val;
- esp->ValueLow = 0;
- if (useRegister)
- mStack.Add(null);
- esp++;
- paramCnt++;
- }
- public void PushInteger(long val)
- {
- esp->ObjectType = ObjectTypes.Long;
- *(long*)&esp->Value = val;
- if (useRegister)
- mStack.Add(null);
- esp++;
- paramCnt++;
- }
- public void PushFloat<T>(T val)
- {
- PushFloat(PrimitiveConverter<T>.CheckAndInvokeToFloat(val));
- }
- public void PushFloat(float val)
- {
- esp->ObjectType = ObjectTypes.Float;
- *(float*)&esp->Value = val;
- if (useRegister)
- mStack.Add(null);
- esp++;
- paramCnt++;
- }
- public void PushDouble<T>(T val)
- {
- PushDouble(PrimitiveConverter<T>.CheckAndInvokeToDouble(val));
- }
- public void PushDouble(double val)
- {
- esp->ObjectType = ObjectTypes.Double;
- *(double*)&esp->Value = val;
- if (useRegister)
- mStack.Add(null);
- esp++;
- paramCnt++;
- }
- public void PushValueType<T>(ref T obj)
- {
- Type t = typeof(T);
- bool needPush = false;
- StackObject* res = default(StackObject*);
- ValueTypeBinder binder;
- if (domain.ValueTypeBinders.TryGetValue(t, out binder))
- {
- var binderT = binder as ValueTypeBinder<T>;
- if (binderT != null)
- {
- binderT.PushValue(ref obj, intp, esp, mStack);
- if (useRegister)
- mStack.Add(null);
- res = esp + 1;
- }
- else
- needPush = true;
- }
- else
- needPush = true;
- if (needPush)
- {
- res = ILIntepreter.PushObject(esp, mStack, obj, true);
- }
- esp = res;
- paramCnt++;
- }
- public void PushObject(object obj, bool isBox = true)
- {
- 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;
- paramCnt++;
- }
- public void PushReference(int index)
- {
- var dst = ILIntepreter.Add(ebp, index);
- esp->ObjectType = ObjectTypes.StackObjectReference;
- *(long*)&esp->Value = (long)dst;
- if (useRegister)
- mStack.Add(null);
- esp++;
- }
- internal void PushParameter<T>(InvocationTypes type, T val)
- {
- switch (type)
- {
- case InvocationTypes.Integer:
- PushInteger(val);
- break;
- case InvocationTypes.Long:
- PushLong(val);
- break;
- case InvocationTypes.Float:
- PushFloat(val);
- break;
- case InvocationTypes.Double:
- PushDouble(val);
- break;
- case InvocationTypes.Enum:
- PushObject(val, false);
- break;
- case InvocationTypes.ValueType:
- PushValueType(ref val);
- break;
- default:
- PushObject(val);
- break;
- }
- }
- internal T ReadResult<T>(InvocationTypes type)
- {
- switch (type)
- {
- case InvocationTypes.Integer:
- return ReadInteger<T>();
- case InvocationTypes.Long:
- return ReadLong<T>();
- case InvocationTypes.Float:
- return ReadFloat<T>();
- case InvocationTypes.Double:
- return ReadDouble<T>();
- case InvocationTypes.ValueType:
- return ReadValueType<T>();
- default:
- return ReadObject<T>();
- }
- }
- public void Invoke()
- {
- if (invocated)
- throw new NotSupportedException("A invocation context can only be used once");
- invocated = true;
- var cnt = method.HasThis ? method.ParameterCount + 1 : method.ParameterCount;
- if (cnt != paramCnt)
- throw new ArgumentException("Argument count mismatch");
- bool unhandledException;
- if (useRegister)
- esp = intp.ExecuteR(method, esp, out unhandledException);
- else
- esp = intp.Execute(method, esp, out unhandledException);
- esp--;
- }
- void CheckReturnValue()
- {
- if (!invocated)
- throw new NotSupportedException("You have to invocate first before you try to read the return value");
- if (!hasReturn)
- throw new NotSupportedException("The target method does not have a return value");
- }
- public int ReadInteger()
- {
- CheckReturnValue();
- return esp->Value;
- }
- public int ReadInteger(int index)
- {
- var esp = ILIntepreter.Add(ebp, index);
- return esp->Value;
- }
- public T ReadInteger<T>()
- {
- return PrimitiveConverter<T>.CheckAndInvokeFromInteger(ReadInteger());
- }
- public long ReadLong()
- {
- CheckReturnValue();
- return *(long*)&esp->Value;
- }
- public long ReadLong(int index)
- {
- var esp = ILIntepreter.Add(ebp, index);
- return *(long*)&esp->Value;
- }
- public T ReadLong<T>()
- {
- return PrimitiveConverter<T>.CheckAndInvokeFromLong(ReadLong());
- }
- public float ReadFloat()
- {
- CheckReturnValue();
- return *(float*)&esp->Value;
- }
- public float ReadFloat(int index)
- {
- var esp = ILIntepreter.Add(ebp, index);
- return *(float*)&esp->Value;
- }
- public T ReadFloat<T>()
- {
- return PrimitiveConverter<T>.CheckAndInvokeFromFloat(ReadFloat());
- }
- public double ReadDouble()
- {
- CheckReturnValue();
- return *(double*)&esp->Value;
- }
- public double ReaDouble(int index)
- {
- var esp = ILIntepreter.Add(ebp, index);
- return *(double*)&esp->Value;
- }
- public T ReadDouble<T>()
- {
- return PrimitiveConverter<T>.CheckAndInvokeFromDouble(ReadDouble());
- }
- public bool ReadBool()
- {
- CheckReturnValue();
- return esp->Value == 1;
- }
- public bool ReadBool(int index)
- {
- var esp = ILIntepreter.Add(ebp, index);
- return esp->Value == 1;
- }
- public T ReadValueType<T>()
- {
- CheckReturnValue();
- Type t = typeof(T);
- T res = default(T);
- ValueTypeBinder binder;
- if (domain.ValueTypeBinders.TryGetValue(t, out binder))
- {
- var binderT = binder as ValueTypeBinder<T>;
- if (binderT != null)
- {
- binderT.ParseValue(ref res, intp, esp, mStack);
- }
- else
- res = (T)t.CheckCLRTypes(StackObject.ToObject(esp, domain, mStack));
- }
- else
- res = (T)t.CheckCLRTypes(StackObject.ToObject(esp, domain, mStack));
- return res;
- }
- public T ReadObject<T>()
- {
- CheckReturnValue();
- return (T)typeof(T).CheckCLRTypes(StackObject.ToObject(esp, domain, mStack));
- }
- public object ReadObject(Type type)
- {
- CheckReturnValue();
- return type.CheckCLRTypes(StackObject.ToObject(esp, domain, mStack));
- }
- public T ReadObject<T>(int index)
- {
- var esp = ILIntepreter.Add(ebp, index);
- return (T)typeof(T).CheckCLRTypes(StackObject.ToObject(esp, domain, mStack));
- }
- public void Dispose()
- {
- domain.FreeILIntepreter(intp);
- esp = null;
- intp = null;
- domain = null;
- method = null;
- mStack = null;
- }
- }
- }
|