using System; using System.Collections.Generic; using System.Linq; using System.Text; using ILRuntime.CLR.TypeSystem; using ILRuntime.CLR.Method; using ILRuntime.Runtime; using ILRuntime.Runtime.Stack; using ILRuntime.Other; using ILRuntime.Runtime.Enviorment; namespace ILRuntime.Runtime.Intepreter { #region Functions class FunctionDelegateAdapter : DelegateAdapter { Func action; static InvocationTypes[] pTypes; static FunctionDelegateAdapter() { pTypes = new InvocationTypes[] { InvocationContext.GetInvocationType(), }; } public FunctionDelegateAdapter() { } private FunctionDelegateAdapter(Enviorment.AppDomain appdomain, ILTypeInstance instance, ILMethod method) : base(appdomain, instance, method) { action = InvokeILMethod; } public override Type NativeDelegateType { get { return typeof(Func); } } public override Delegate Delegate { get { return action; } } unsafe TResult InvokeILMethod() { using (var ctx = BeginInvoke()) { var esp = ILInvoke(ctx.Intepreter, ctx.ESP, ctx.ManagedStack); ctx.SetInvoked(esp); return ctx.ReadResult(pTypes[0]); } } public override IDelegateAdapter Instantiate(Enviorment.AppDomain appdomain, ILTypeInstance instance, ILMethod method) { return new FunctionDelegateAdapter(appdomain, instance, method); } public override IDelegateAdapter Clone() { var res = new FunctionDelegateAdapter(appdomain, instance, method); res.isClone = true; return res; } public override void Combine(Delegate dele) { action += (Func)dele; } public override void Remove(Delegate dele) { action -= (Func)dele; } } class FunctionDelegateAdapter : DelegateAdapter { Func action; static InvocationTypes[] pTypes; static FunctionDelegateAdapter() { pTypes = new InvocationTypes[] { InvocationContext.GetInvocationType(), InvocationContext.GetInvocationType(), }; } public FunctionDelegateAdapter() { } private FunctionDelegateAdapter(Enviorment.AppDomain appdomain, ILTypeInstance instance, ILMethod method) : base(appdomain, instance, method) { action = InvokeILMethod; } public override Type NativeDelegateType { get { return typeof(Func); } } public override Delegate Delegate { get { return action; } } unsafe TResult InvokeILMethod(T1 p1) { using (var ctx = BeginInvoke()) { ctx.PushParameter(pTypes[0], p1); var esp = ILInvoke(ctx.Intepreter, ctx.ESP, ctx.ManagedStack); ctx.SetInvoked(esp); return ctx.ReadResult(pTypes[1]); } } public override IDelegateAdapter Instantiate(Enviorment.AppDomain appdomain, ILTypeInstance instance, ILMethod method) { return new FunctionDelegateAdapter(appdomain, instance, method); } public override IDelegateAdapter Clone() { var res = new FunctionDelegateAdapter(appdomain, instance, method); res.isClone = true; return res; } public override void Combine(Delegate dele) { action += (Func)dele; } public override void Remove(Delegate dele) { action -= (Func)dele; } } class FunctionDelegateAdapter : DelegateAdapter { Func action; static InvocationTypes[] pTypes; static FunctionDelegateAdapter() { pTypes = new InvocationTypes[] { InvocationContext.GetInvocationType(), InvocationContext.GetInvocationType(), InvocationContext.GetInvocationType(), }; } public FunctionDelegateAdapter() { } private FunctionDelegateAdapter(Enviorment.AppDomain appdomain, ILTypeInstance instance, ILMethod method) : base(appdomain, instance, method) { action = InvokeILMethod; } public override Type NativeDelegateType { get { return typeof(Func); } } public override Delegate Delegate { get { return action; } } unsafe TResult InvokeILMethod(T1 p1, T2 p2) { using (var ctx = BeginInvoke()) { ctx.PushParameter(pTypes[0], p1); ctx.PushParameter(pTypes[1], p2); var esp = ILInvoke(ctx.Intepreter, ctx.ESP, ctx.ManagedStack); ctx.SetInvoked(esp); return ctx.ReadResult(pTypes[2]); } } public override IDelegateAdapter Instantiate(Enviorment.AppDomain appdomain, ILTypeInstance instance, ILMethod method) { return new FunctionDelegateAdapter(appdomain, instance, method); } public override IDelegateAdapter Clone() { var res = new FunctionDelegateAdapter(appdomain, instance, method); res.isClone = true; return res; } public override void Combine(Delegate dele) { action += (Func)dele; } public override void Remove(Delegate dele) { action -= (Func)dele; } } class FunctionDelegateAdapter : DelegateAdapter { Func action; static InvocationTypes[] pTypes; static FunctionDelegateAdapter() { pTypes = new InvocationTypes[] { InvocationContext.GetInvocationType(), InvocationContext.GetInvocationType(), InvocationContext.GetInvocationType(), InvocationContext.GetInvocationType(), }; } public FunctionDelegateAdapter() { } private FunctionDelegateAdapter(Enviorment.AppDomain appdomain, ILTypeInstance instance, ILMethod method) : base(appdomain, instance, method) { action = InvokeILMethod; } public override Type NativeDelegateType { get { return typeof(Func); } } public override Delegate Delegate { get { return action; } } unsafe TResult InvokeILMethod(T1 p1, T2 p2, T3 p3) { using (var ctx = BeginInvoke()) { ctx.PushParameter(pTypes[0], p1); ctx.PushParameter(pTypes[1], p2); ctx.PushParameter(pTypes[2], p3); var esp = ILInvoke(ctx.Intepreter, ctx.ESP, ctx.ManagedStack); ctx.SetInvoked(esp); return ctx.ReadResult(pTypes[3]); } } public override IDelegateAdapter Instantiate(Enviorment.AppDomain appdomain, ILTypeInstance instance, ILMethod method) { return new FunctionDelegateAdapter(appdomain, instance, method); } public override IDelegateAdapter Clone() { var res = new FunctionDelegateAdapter(appdomain, instance, method); res.isClone = true; return res; } public override void Combine(Delegate dele) { action += (Func)dele; } public override void Remove(Delegate dele) { action -= (Func)dele; } } class FunctionDelegateAdapter : DelegateAdapter { Func action; static InvocationTypes[] pTypes; static FunctionDelegateAdapter() { pTypes = new InvocationTypes[] { InvocationContext.GetInvocationType(), InvocationContext.GetInvocationType(), InvocationContext.GetInvocationType(), InvocationContext.GetInvocationType(), InvocationContext.GetInvocationType(), }; } public FunctionDelegateAdapter() { } private FunctionDelegateAdapter(Enviorment.AppDomain appdomain, ILTypeInstance instance, ILMethod method) : base(appdomain, instance, method) { action = InvokeILMethod; } public override Type NativeDelegateType { get { return typeof(Func); } } public override Delegate Delegate { get { return action; } } unsafe TResult InvokeILMethod(T1 p1, T2 p2, T3 p3, T4 p4) { using (var ctx = BeginInvoke()) { ctx.PushParameter(pTypes[0], p1); ctx.PushParameter(pTypes[1], p2); ctx.PushParameter(pTypes[2], p3); ctx.PushParameter(pTypes[3], p4); var esp = ILInvoke(ctx.Intepreter, ctx.ESP, ctx.ManagedStack); ctx.SetInvoked(esp); return ctx.ReadResult(pTypes[4]); } } public override IDelegateAdapter Instantiate(Enviorment.AppDomain appdomain, ILTypeInstance instance, ILMethod method) { return new FunctionDelegateAdapter(appdomain, instance, method); } public override IDelegateAdapter Clone() { var res = new FunctionDelegateAdapter(appdomain, instance, method); res.isClone = true; return res; } public override void Combine(Delegate dele) { action += (Func)dele; } public override void Remove(Delegate dele) { action -= (Func)dele; } } #endregion #region Methods class MethodDelegateAdapter : DelegateAdapter { Action action; static InvocationTypes pType; static MethodDelegateAdapter() { pType = InvocationContext.GetInvocationType(); } public MethodDelegateAdapter() { } private MethodDelegateAdapter(Enviorment.AppDomain appdomain, ILTypeInstance instance, ILMethod method) : base(appdomain, instance, method) { action = InvokeILMethod; } public override Type NativeDelegateType { get { return typeof(Action); } } public override Delegate Delegate { get { return action; } } unsafe void InvokeILMethod(T1 p1) { using (var ctx = BeginInvoke()) { ctx.PushParameter(pType, p1); ILInvoke(ctx.Intepreter, ctx.ESP, ctx.ManagedStack); } } public override IDelegateAdapter Instantiate(Enviorment.AppDomain appdomain, ILTypeInstance instance, ILMethod method) { return new MethodDelegateAdapter(appdomain, instance, method); } public override IDelegateAdapter Clone() { var res = new MethodDelegateAdapter(appdomain, instance, method); res.isClone = true; return res; } public override void Combine(Delegate dele) { action += (Action)dele; } public override void Remove(Delegate dele) { action -= (Action)dele; } } class MethodDelegateAdapter : DelegateAdapter { Action action; static InvocationTypes[] pTypes; static MethodDelegateAdapter() { pTypes = new InvocationTypes[] { InvocationContext.GetInvocationType(), InvocationContext.GetInvocationType(), }; } public MethodDelegateAdapter() { } private MethodDelegateAdapter(Enviorment.AppDomain appdomain, ILTypeInstance instance, ILMethod method) : base(appdomain, instance, method) { action = InvokeILMethod; } public override Type NativeDelegateType { get { return typeof(Action); } } public override Delegate Delegate { get { return action; } } unsafe void InvokeILMethod(T1 p1, T2 p2) { using (var ctx = BeginInvoke()) { ctx.PushParameter(pTypes[0], p1); ctx.PushParameter(pTypes[1], p2); ILInvoke(ctx.Intepreter, ctx.ESP, ctx.ManagedStack); } } public override IDelegateAdapter Instantiate(Enviorment.AppDomain appdomain, ILTypeInstance instance, ILMethod method) { return new MethodDelegateAdapter(appdomain, instance, method); } public override IDelegateAdapter Clone() { var res = new MethodDelegateAdapter(appdomain, instance, method); res.isClone = true; return res; } public override void Combine(Delegate dele) { action += (Action)dele; } public override void Remove(Delegate dele) { action -= (Action)dele; } } class MethodDelegateAdapter : DelegateAdapter { Action action; static InvocationTypes[] pTypes; static MethodDelegateAdapter() { pTypes = new InvocationTypes[] { InvocationContext.GetInvocationType(), InvocationContext.GetInvocationType(), InvocationContext.GetInvocationType(), }; } public MethodDelegateAdapter() { } private MethodDelegateAdapter(Enviorment.AppDomain appdomain, ILTypeInstance instance, ILMethod method) : base(appdomain, instance, method) { action = InvokeILMethod; } public override Type NativeDelegateType { get { return typeof(Action); } } public override Delegate Delegate { get { return action; } } unsafe void InvokeILMethod(T1 p1, T2 p2, T3 p3) { using (var ctx = BeginInvoke()) { ctx.PushParameter(pTypes[0], p1); ctx.PushParameter(pTypes[1], p2); ctx.PushParameter(pTypes[2], p3); ILInvoke(ctx.Intepreter, ctx.ESP, ctx.ManagedStack); } } public override IDelegateAdapter Instantiate(Enviorment.AppDomain appdomain, ILTypeInstance instance, ILMethod method) { return new MethodDelegateAdapter(appdomain, instance, method); } public override IDelegateAdapter Clone() { var res = new MethodDelegateAdapter(appdomain, instance, method); res.isClone = true; return res; } public override void Combine(Delegate dele) { action += (Action)dele; } public override void Remove(Delegate dele) { action -= (Action)dele; } } class MethodDelegateAdapter : DelegateAdapter { Action action; static InvocationTypes[] pTypes; static MethodDelegateAdapter() { pTypes = new InvocationTypes[] { InvocationContext.GetInvocationType(), InvocationContext.GetInvocationType(), InvocationContext.GetInvocationType(), InvocationContext.GetInvocationType(), }; } public MethodDelegateAdapter() { } private MethodDelegateAdapter(Enviorment.AppDomain appdomain, ILTypeInstance instance, ILMethod method) : base(appdomain, instance, method) { action = InvokeILMethod; } public override Type NativeDelegateType { get { return typeof(Action); } } public override Delegate Delegate { get { return action; } } unsafe void InvokeILMethod(T1 p1, T2 p2, T3 p3, T4 p4) { using (var ctx = BeginInvoke()) { ctx.PushParameter(pTypes[0], p1); ctx.PushParameter(pTypes[1], p2); ctx.PushParameter(pTypes[2], p3); ctx.PushParameter(pTypes[3], p4); ILInvoke(ctx.Intepreter, ctx.ESP, ctx.ManagedStack); } } public override IDelegateAdapter Instantiate(Enviorment.AppDomain appdomain, ILTypeInstance instance, ILMethod method) { return new MethodDelegateAdapter(appdomain, instance, method); } public override IDelegateAdapter Clone() { var res = new MethodDelegateAdapter(appdomain, instance, method); res.isClone = true; return res; } public override void Combine(Delegate dele) { action += (Action)dele; } public override void Remove(Delegate dele) { action -= (Action)dele; } } #if NET_4_6 || NET_STANDARD_2_0 class MethodDelegateAdapter : DelegateAdapter { Action action; static InvocationTypes[] pTypes; static MethodDelegateAdapter() { pTypes = new InvocationTypes[] { InvocationContext.GetInvocationType(), InvocationContext.GetInvocationType(), InvocationContext.GetInvocationType(), InvocationContext.GetInvocationType(), InvocationContext.GetInvocationType(), }; } public MethodDelegateAdapter() { } private MethodDelegateAdapter(Enviorment.AppDomain appdomain, ILTypeInstance instance, ILMethod method) : base(appdomain, instance, method) { action = InvokeILMethod; } public override Type NativeDelegateType { get { return typeof(Action); } } public override Delegate Delegate { get { return action; } } unsafe void InvokeILMethod(T1 p1, T2 p2, T3 p3, T4 p4, T5 p5) { using (var ctx = BeginInvoke()) { ctx.PushParameter(pTypes[0], p1); ctx.PushParameter(pTypes[1], p2); ctx.PushParameter(pTypes[2], p3); ctx.PushParameter(pTypes[3], p4); ctx.PushParameter(pTypes[4], p5); ILInvoke(ctx.Intepreter, ctx.ESP, ctx.ManagedStack); } } public override IDelegateAdapter Instantiate(Enviorment.AppDomain appdomain, ILTypeInstance instance, ILMethod method) { return new MethodDelegateAdapter(appdomain, instance, method); } public override IDelegateAdapter Clone() { var res = new MethodDelegateAdapter(appdomain, instance, method); res.isClone = true; return res; } public override void Combine(Delegate dele) { action += (Action)dele; } public override void Remove(Delegate dele) { action -= (Action)dele; } } #endif class MethodDelegateAdapter : DelegateAdapter { Action action; public MethodDelegateAdapter() { } protected MethodDelegateAdapter(Enviorment.AppDomain appdomain, ILTypeInstance instance, ILMethod method) : base(appdomain, instance, method) { action = InvokeILMethod; } public override Type NativeDelegateType { get { return typeof(Action); } } public override Delegate Delegate { get { return action; } } unsafe void InvokeILMethod() { using(var ctx = BeginInvoke()) { ILInvoke(ctx.Intepreter, ctx.ESP, ctx.ManagedStack); } } public override IDelegateAdapter Instantiate(Enviorment.AppDomain appdomain, ILTypeInstance instance, ILMethod method) { return new MethodDelegateAdapter(appdomain, instance, method); } public override IDelegateAdapter Clone() { var res = new MethodDelegateAdapter(appdomain, instance, method); res.isClone = true; return res; } public override void Combine(Delegate dele) { action += (Action)dele; } public override void Remove(Delegate dele) { action -= (Action)dele; } } class DummyDelegateAdapter : DelegateAdapter { public DummyDelegateAdapter() { } protected DummyDelegateAdapter(Enviorment.AppDomain appdomain, ILTypeInstance instance, ILMethod method) : base(appdomain, instance, method) { } public override Type NativeDelegateType { get { throw new NotSupportedException(); } } public override Delegate Delegate { get { ThrowAdapterNotFound(method); return null; } } void InvokeILMethod() { if (method.HasThis) appdomain.Invoke(method, instance, null); else appdomain.Invoke(method, null, null); } public override IDelegateAdapter Instantiate(Enviorment.AppDomain appdomain, ILTypeInstance instance, ILMethod method) { return new DummyDelegateAdapter(appdomain, instance, method); } public override IDelegateAdapter Clone() { var res = new DummyDelegateAdapter(appdomain, instance, method); res.isClone = true; return res; } public override void Combine(Delegate dele) { ThrowAdapterNotFound(method); } public override void Remove(Delegate dele) { ThrowAdapterNotFound(method); } } #endregion abstract class DelegateAdapter : ILTypeInstance, IDelegateAdapter { protected ILMethod method; protected ILTypeInstance instance; protected Enviorment.AppDomain appdomain; Dictionary converters; IDelegateAdapter next; protected bool isClone; public abstract Delegate Delegate { get; } public abstract Type NativeDelegateType { get; } public IDelegateAdapter Next { get { return next; } } public ILTypeInstance Instance { get { return instance; } } public ILMethod Method { get { return method; } } protected DelegateAdapter() { } protected DelegateAdapter(Enviorment.AppDomain appdomain, ILTypeInstance instance, ILMethod method) { this.appdomain = appdomain; this.instance = instance; this.method = method; CLRInstance = this; } public override bool IsValueType { get { return false; } } unsafe protected InvocationContext BeginInvoke() { var ctx = appdomain.BeginInvoke(method); *ctx.ESP = default(StackObject); ctx.ESP++;//required to simulate delegate invocation return ctx; } public unsafe StackObject* ILInvoke(ILIntepreter intp, StackObject* esp, IList mStack) { var ebp = esp; esp = ILInvokeSub(intp, esp, mStack); return ClearStack(intp, esp, ebp, mStack); } unsafe StackObject* ILInvokeSub(ILIntepreter intp, StackObject* esp, IList mStack) { var ebp = esp; bool unhandled; if (method.HasThis) esp = ILIntepreter.PushObject(esp, mStack, instance); int paramCnt = method.ParameterCount; if (method.IsExtend && instance != null) { esp = ILIntepreter.PushObject(esp, mStack, instance); paramCnt--; } bool useRegister = method.ShouldUseRegisterVM; for (int i = paramCnt; i > 0; i--) { intp.CopyToStack(esp, Minus(ebp, i), mStack); if (esp->ObjectType < ObjectTypes.Object && useRegister) mStack.Add(null); esp++; } StackObject* ret; if (useRegister) ret = intp.ExecuteR(method, esp, out unhandled); else ret = intp.Execute(method, esp, out unhandled); if (next != null) { if (method.ReturnType != appdomain.VoidType) { intp.Free(ret - 1);//Return value for multicast delegate doesn't make sense, only return the last one's value } DelegateAdapter n = (DelegateAdapter)next; ret = n.ILInvokeSub(intp, ebp, mStack); } return ret; } unsafe StackObject* ClearStack(ILIntepreter intp, StackObject* esp, StackObject* ebp, IList mStack) { int paramCnt = method.ParameterCount; if (method.IsExtend && instance != null)//如果是拓展方法,退一位 { paramCnt--; } object retObj = null; StackObject retSObj = StackObject.Null; bool hasReturn = method.ReturnType != appdomain.VoidType; if (hasReturn) { var ret = esp - 1; retSObj = *ret; if(ret->ObjectType>= ObjectTypes.Object) { retObj = mStack[ret->Value]; if(retObj == null) { retSObj.ObjectType = ObjectTypes.Null; retSObj.Value = -1; retSObj.ValueLow = 0; } intp.Free(ret); } } for (int i = 1; i <= paramCnt; i++) { intp.Free(ebp - i); } var returnVal = Minus(ebp, paramCnt + 1); intp.Free(returnVal);//Free delegateInstance if (hasReturn) { *returnVal = retSObj; if(retObj != null) { returnVal->Value = mStack.Count; mStack.Add(retObj); } returnVal++; } return returnVal; } public abstract IDelegateAdapter Instantiate(Enviorment.AppDomain appdomain, ILTypeInstance instance, ILMethod method); public new abstract IDelegateAdapter Clone(); public bool IsClone { get { return isClone; } } public virtual void Combine(IDelegateAdapter adapter) { if (next != null) next.Combine(adapter); else next = adapter; } public abstract void Combine(Delegate dele); public virtual void Remove(IDelegateAdapter adapter) { if (next != null) { if (next.Equals(adapter)) { next = ((DelegateAdapter)next).next; } else next.Remove(adapter); } } public abstract void Remove(Delegate dele); public virtual bool Equals(IDelegateAdapter adapter) { if (adapter is DelegateAdapter) { DelegateAdapter b = (DelegateAdapter)adapter; return instance == b.instance && method == b.method; } else return false; } public override bool Equals(object obj) { if (obj is DelegateAdapter) { DelegateAdapter b = (DelegateAdapter)obj; return instance == b.instance && method == b.method; } return false; } public virtual bool Equals(Delegate dele) { return Delegate == dele; } public override int GetHashCode() { return base.GetHashCode(); } public override string ToString() { return method.ToString(); } public override bool CanAssignTo(IType type) { if (type.IsDelegate) { var method_count = method.IsExtend ? method.ParameterCount - 1 : method.ParameterCount; var im = type.GetMethod("Invoke", method_count); if (im == null) { return false; } var ret_type = im.ReturnType; if (im.ReturnType != appdomain.VoidType && type.IsGenericInstance) { ret_type = type.GenericArguments[im.ParameterCount].Value; } if (im.IsDelegateInvoke) { if (im.ParameterCount == method_count && ret_type == method.ReturnType) { for (int i = 0; i < im.ParameterCount; i++) { var index = method.IsExtend ? i + 1 : i; if (im.Parameters[i] != method.Parameters[index] && (!(im is CLRMethod) || (im.Parameters[i].TypeForCLR != method.Parameters[index].TypeForCLR))) return false; } return true; } else return false; } else return false; } else return false; } public Delegate GetConvertor(Type type) { if (converters == null) converters = new Dictionary(new ByReferenceKeyComparer()); Delegate res; if (converters.TryGetValue(type, out res)) return res; else { res = appdomain.DelegateManager.ConvertToDelegate(type, this); converters[type] = res; return res; } } unsafe StackObject* Minus(StackObject* a, int b) { return (StackObject*)((long)a - sizeof(StackObject) * b); } public static void ThrowAdapterNotFound(IMethod method) { StringBuilder sb = new StringBuilder(); sb.Append("Cannot find Delegate Adapter for:"); sb.Append(method.ToString()); string clsName, rName; bool isByRef; if (method.ReturnType.Name != "Void" || method.ParameterCount > 0) { sb.AppendLine(", Please add following code:"); if (method.ReturnType.Name == "Void") { sb.Append("appdomain.DelegateManager.RegisterMethodDelegate<"); bool first = true; foreach(var i in method.Parameters) { if (first) { first = false; } else { sb.Append(", "); } i.TypeForCLR.GetClassName(out clsName, out rName, out isByRef); sb.Append(rName); } sb.AppendLine(">();"); } else { sb.Append("appdomain.DelegateManager.RegisterFunctionDelegate<"); bool first = true; foreach (var i in method.Parameters) { if (first) { first = false; } else { sb.Append(", "); } i.TypeForCLR.GetClassName(out clsName, out rName, out isByRef); sb.Append(rName); } if (!first) sb.Append(", "); method.ReturnType.TypeForCLR.GetClassName(out clsName, out rName, out isByRef); sb.Append(rName); sb.AppendLine(">();"); } } throw new KeyNotFoundException(sb.ToString()); } } unsafe interface IDelegateAdapter { Type NativeDelegateType { get; } Delegate Delegate { get; } IDelegateAdapter Next { get; } ILTypeInstance Instance { get; } ILMethod Method { get; } StackObject* ILInvoke(ILIntepreter intp, StackObject* esp, IList mStack); IDelegateAdapter Instantiate(Enviorment.AppDomain appdomain, ILTypeInstance instance, ILMethod method); bool IsClone { get; } IDelegateAdapter Clone(); Delegate GetConvertor(Type type); void Combine(IDelegateAdapter adapter); void Combine(Delegate dele); void Remove(IDelegateAdapter adapter); void Remove(Delegate dele); bool Equals(IDelegateAdapter adapter); bool Equals(Delegate dele); } }