| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625 |
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using System.Reflection;
- using Mono.Cecil;
- using ILRuntime.Runtime.Intepreter.OpCodes;
- using ILRuntime.Runtime.Intepreter;
- using ILRuntime.Runtime.Debugger;
- using ILRuntime.CLR.TypeSystem;
- using ILRuntime.Reflection;
- namespace ILRuntime.CLR.Method
- {
- public class ILMethod : IMethod
- {
- OpCode[] body;
- MethodDefinition def;
- List<IType> parameters;
- ILRuntime.Runtime.Enviorment.AppDomain appdomain;
- ILType declaringType;
- ExceptionHandler[] exceptionHandler;
- KeyValuePair<string, IType>[] genericParameters;
- IType[] genericArguments;
- Dictionary<int, int[]> jumptables;
- bool isDelegateInvoke;
- ILRuntimeMethodInfo refletionMethodInfo;
- ILRuntimeConstructorInfo reflectionCtorInfo;
- int paramCnt, localVarCnt;
- Mono.Collections.Generic.Collection<Mono.Cecil.Cil.VariableDefinition> variables;
- int hashCode = -1;
- static int instance_id = 0x10000000;
- public MethodDefinition Definition { get { return def; } }
- public Dictionary<int, int[]> JumpTables { get { return jumptables; } }
- internal IDelegateAdapter DelegateAdapter { get; set; }
- internal int StartLine { get; set; }
- internal int EndLine { get; set; }
- public MethodInfo ReflectionMethodInfo
- {
- get
- {
- if (IsConstructor)
- throw new NotSupportedException();
- if (refletionMethodInfo == null)
- refletionMethodInfo = new ILRuntimeMethodInfo(this);
- return refletionMethodInfo;
- }
- }
- public ConstructorInfo ReflectionConstructorInfo
- {
- get
- {
- if (!IsConstructor)
- throw new NotSupportedException();
- if (reflectionCtorInfo == null)
- reflectionCtorInfo = new ILRuntimeConstructorInfo(this);
- return reflectionCtorInfo;
- }
- }
- internal ExceptionHandler[] ExceptionHandler
- {
- get
- {
- if (body == null)
- InitCodeBody();
- return exceptionHandler;
- }
- }
- public string Name
- {
- get
- {
- return def.Name;
- }
- }
- public IType DeclearingType
- {
- get
- {
- return declaringType;
- }
- }
- public bool HasThis
- {
- get
- {
- return def.HasThis;
- }
- }
- public int GenericParameterCount
- {
- get
- {
- if (IsGenericInstance)
- return 0;
- return def.GenericParameters.Count;
- }
- }
- public bool IsGenericInstance
- {
- get
- {
- return genericParameters != null;
- }
- }
- public Mono.Collections.Generic.Collection<Mono.Cecil.Cil.VariableDefinition> Variables
- {
- get
- {
- return variables;
- }
- }
- public KeyValuePair<string, IType>[] GenericArguments { get { return genericParameters; } }
- public IType[] GenericArugmentsArray { get { return genericArguments; } }
- public ILMethod(MethodDefinition def, ILType type, ILRuntime.Runtime.Enviorment.AppDomain domain)
- {
- this.def = def;
- declaringType = type;
- if (def.ReturnType.IsGenericParameter)
- {
- ReturnType = FindGenericArgument(def.ReturnType.Name);
- }
- else
- ReturnType = domain.GetType(def.ReturnType, type, this);
- if (type.IsDelegate && def.Name == "Invoke")
- isDelegateInvoke = true;
- this.appdomain = domain;
- paramCnt = def.HasParameters ? def.Parameters.Count : 0;
- #if DEBUG
- if (def.HasBody)
- {
- var sp = DebugService.FindSequencePoint(def.Body.Instructions[0]);
- if (sp != null)
- {
- StartLine = sp.StartLine;
- sp = DebugService.FindSequencePoint(def.Body.Instructions[def.Body.Instructions.Count - 1]);
- if (sp != null)
- {
- EndLine = sp.EndLine;
- }
- }
- }
- #endif
- }
- public IType FindGenericArgument(string name)
- {
- IType res = declaringType.FindGenericArgument(name);
- if (res == null && genericParameters != null)
- {
- foreach (var i in genericParameters)
- {
- if (i.Key == name)
- return i.Value;
- }
- }
- else
- return res;
- return null;
- }
- internal OpCode[] Body
- {
- get
- {
- if (body == null)
- InitCodeBody();
- return body;
- }
- }
- public int LocalVariableCount
- {
- get
- {
- return localVarCnt;
- }
- }
- public bool IsConstructor
- {
- get
- {
- return def.IsConstructor;
- }
- }
- public bool IsDelegateInvoke
- {
- get
- {
- return isDelegateInvoke;
- }
- }
- public bool IsStatic
- {
- get { return def.IsStatic; }
- }
- public int ParameterCount
- {
- get
- {
- return paramCnt;
- }
- }
- public List<IType> Parameters
- {
- get
- {
- if (def.HasParameters && parameters == null)
- {
- InitParameters();
- }
- return parameters;
- }
- }
- public IType ReturnType
- {
- get;
- private set;
- }
- void InitCodeBody()
- {
- if (def.HasBody)
- {
- localVarCnt = def.Body.Variables.Count;
- body = new OpCode[def.Body.Instructions.Count];
- Dictionary<Mono.Cecil.Cil.Instruction, int> addr = new Dictionary<Mono.Cecil.Cil.Instruction, int>();
- for (int i = 0; i < body.Length; i++)
- {
- var c = def.Body.Instructions[i];
- OpCode code = new OpCode();
- code.Code = (OpCodeEnum)c.OpCode.Code;
- addr[c] = i;
- body[i] = code;
- }
- for (int i = 0; i < body.Length; i++)
- {
- var c = def.Body.Instructions[i];
- InitToken(ref body[i], c.Operand, addr);
- }
- for (int i = 0; i < def.Body.ExceptionHandlers.Count; i++)
- {
- var eh = def.Body.ExceptionHandlers[i];
- if (exceptionHandler == null)
- exceptionHandler = new Method.ExceptionHandler[def.Body.ExceptionHandlers.Count];
- ExceptionHandler e = new ExceptionHandler();
- e.HandlerStart = addr[eh.HandlerStart];
- e.HandlerEnd = addr[eh.HandlerEnd] - 1;
- e.TryStart = addr[eh.TryStart];
- e.TryEnd = addr[eh.TryEnd] - 1;
- switch (eh.HandlerType)
- {
- case Mono.Cecil.Cil.ExceptionHandlerType.Catch:
- e.CatchType = appdomain.GetType(eh.CatchType, declaringType, this);
- e.HandlerType = ExceptionHandlerType.Catch;
- break;
- case Mono.Cecil.Cil.ExceptionHandlerType.Finally:
- e.HandlerType = ExceptionHandlerType.Finally;
- break;
- case Mono.Cecil.Cil.ExceptionHandlerType.Fault:
- e.HandlerType = ExceptionHandlerType.Fault;
- break;
- default:
- throw new NotImplementedException();
- }
- exceptionHandler[i] = e;
- //Mono.Cecil.Cil.ExceptionHandlerType.
- }
- //Release Method body to save memory
- variables = def.Body.Variables;
- def.Body = null;
- }
- else
- body = new OpCode[0];
- }
- unsafe void InitToken(ref OpCode code, object token, Dictionary<Mono.Cecil.Cil.Instruction, int> addr)
- {
- switch (code.Code)
- {
- case OpCodeEnum.Leave:
- case OpCodeEnum.Leave_S:
- case OpCodeEnum.Br:
- case OpCodeEnum.Br_S:
- case OpCodeEnum.Brtrue:
- case OpCodeEnum.Brtrue_S:
- case OpCodeEnum.Brfalse:
- case OpCodeEnum.Brfalse_S:
- //比较流程控制
- case OpCodeEnum.Beq:
- case OpCodeEnum.Beq_S:
- case OpCodeEnum.Bne_Un:
- case OpCodeEnum.Bne_Un_S:
- case OpCodeEnum.Bge:
- case OpCodeEnum.Bge_S:
- case OpCodeEnum.Bge_Un:
- case OpCodeEnum.Bge_Un_S:
- case OpCodeEnum.Bgt:
- case OpCodeEnum.Bgt_S:
- case OpCodeEnum.Bgt_Un:
- case OpCodeEnum.Bgt_Un_S:
- case OpCodeEnum.Ble:
- case OpCodeEnum.Ble_S:
- case OpCodeEnum.Ble_Un:
- case OpCodeEnum.Ble_Un_S:
- case OpCodeEnum.Blt:
- case OpCodeEnum.Blt_S:
- case OpCodeEnum.Blt_Un:
- case OpCodeEnum.Blt_Un_S:
- code.TokenInteger = addr[(Mono.Cecil.Cil.Instruction)token];
- break;
- case OpCodeEnum.Ldc_I4:
- code.TokenInteger = (int)token;
- break;
- case OpCodeEnum.Ldc_I4_S:
- code.TokenInteger = (sbyte)token;
- break;
- case OpCodeEnum.Ldc_I8:
- code.TokenLong = (long)token;
- break;
- case OpCodeEnum.Ldc_R4:
- {
- float val = (float)token;
- code.TokenInteger = *(int*)&val;
- }
- break;
- case OpCodeEnum.Ldc_R8:
- {
- double val = (double)token;
- code.TokenLong = *(long*)&val;
- }
- break;
- case OpCodeEnum.Stloc:
- case OpCodeEnum.Stloc_S:
- case OpCodeEnum.Ldloc:
- case OpCodeEnum.Ldloc_S:
- case OpCodeEnum.Ldloca:
- case OpCodeEnum.Ldloca_S:
- {
- Mono.Cecil.Cil.VariableDefinition vd = (Mono.Cecil.Cil.VariableDefinition)token;
- code.TokenInteger = vd.Index;
- }
- break;
- case OpCodeEnum.Ldarg_S:
- case OpCodeEnum.Ldarg:
- case OpCodeEnum.Ldarga:
- case OpCodeEnum.Ldarga_S:
- case OpCodeEnum.Starg:
- case OpCodeEnum.Starg_S:
- {
- Mono.Cecil.ParameterDefinition vd = (Mono.Cecil.ParameterDefinition)token;
- code.TokenInteger = vd.Index;
- if (HasThis)
- code.TokenInteger++;
- }
- break;
- case OpCodeEnum.Call:
- case OpCodeEnum.Newobj:
- case OpCodeEnum.Ldftn:
- case OpCodeEnum.Ldvirtftn:
- case OpCodeEnum.Callvirt:
- {
- bool invalidToken;
- var m = appdomain.GetMethod(token, declaringType, this, out invalidToken);
- if (m != null)
- {
- if (invalidToken)
- code.TokenInteger = m.GetHashCode();
- else
- code.TokenInteger = token.GetHashCode();
- }
- }
- break;
- case OpCodeEnum.Constrained:
- case OpCodeEnum.Box:
- case OpCodeEnum.Unbox_Any:
- case OpCodeEnum.Unbox:
- case OpCodeEnum.Initobj:
- case OpCodeEnum.Isinst:
- case OpCodeEnum.Newarr:
- case OpCodeEnum.Stobj:
- case OpCodeEnum.Ldobj:
- {
- code.TokenInteger = GetTypeTokenHashCode(token);
- }
- break;
- case OpCodeEnum.Stfld:
- case OpCodeEnum.Ldfld:
- case OpCodeEnum.Ldflda:
- {
- code.TokenInteger = appdomain.GetFieldIndex(token, declaringType, this);
- }
- break;
- case OpCodeEnum.Stsfld:
- case OpCodeEnum.Ldsfld:
- case OpCodeEnum.Ldsflda:
- {
- code.TokenLong = appdomain.GetStaticFieldIndex(token, declaringType, this);
- }
- break;
- case OpCodeEnum.Ldstr:
- {
- long hashCode = appdomain.CacheString(token);
- code.TokenLong = hashCode;
- }
- break;
- case OpCodeEnum.Ldtoken:
- {
- if (token is FieldReference)
- {
- code.TokenInteger = 0;
- code.TokenLong = appdomain.GetStaticFieldIndex(token, declaringType, this);
- }
- else if (token is TypeReference)
- {
- code.TokenInteger = 1;
- code.TokenLong = GetTypeTokenHashCode(token);
- }
- else
- throw new NotImplementedException();
- }
- break;
- case OpCodeEnum.Switch:
- {
- PrepareJumpTable(token, addr);
- code.TokenInteger = token.GetHashCode();
- }
- break;
- }
- }
- int GetTypeTokenHashCode(object token)
- {
- var t = appdomain.GetType(token, declaringType, this);
- bool isGenericParameter = CheckHasGenericParamter(token);
- if (t == null && isGenericParameter)
- {
- t = FindGenericArgument(((TypeReference)token).Name);
- }
- if (t != null)
- {
- if (t is ILType)
- {
- if (((ILType)t).TypeReference.HasGenericParameters)
- return t.GetHashCode();
- else
- return ((ILType)t).TypeReference.GetHashCode();
- }
- else if (isGenericParameter)
- {
- return t.GetHashCode();
- }
- else
- return token.GetHashCode();
- }
- return 0;
- }
- bool CheckHasGenericParamter(object token)
- {
- if (token is TypeReference)
- {
- TypeReference _ref = ((TypeReference)token);
- if (_ref.IsGenericParameter)
- return true;
- if (_ref.IsGenericInstance)
- {
- GenericInstanceType gi = (GenericInstanceType)_ref;
- foreach(var i in gi.GenericArguments)
- {
- if (CheckHasGenericParamter(i))
- return true;
- }
- return false;
- }
- else
- return false;
- }
- else
- return false;
- }
- void PrepareJumpTable(object token, Dictionary<Mono.Cecil.Cil.Instruction, int> addr)
- {
- int hashCode = token.GetHashCode();
- if (jumptables == null)
- jumptables = new Dictionary<int, int[]>();
- if (jumptables.ContainsKey(hashCode))
- return;
- Mono.Cecil.Cil.Instruction[] e = token as Mono.Cecil.Cil.Instruction[];
- int[] addrs = new int[e.Length];
- for (int i = 0; i < e.Length; i++)
- {
- addrs[i] = addr[e[i]];
- }
- jumptables[hashCode] = addrs;
- }
- void InitParameters()
- {
- parameters = new List<IType>();
- foreach (var i in def.Parameters)
- {
- IType type = null;
- bool isByRef = false;
- bool isArray = false;
- TypeReference pt = i.ParameterType;
- if (i.ParameterType.IsByReference)
- {
- isByRef = true;
- pt = pt.GetElementType();
- }
- if (i.ParameterType.IsArray)
- {
- isArray = true;
- pt = pt.GetElementType();
- }
- if (pt.IsGenericParameter)
- {
- type = FindGenericArgument(pt.Name);
- if (type == null && def.HasGenericParameters)
- {
- bool found = false;
- foreach (var j in def.GenericParameters)
- {
- if (j.Name == pt.Name)
- {
- found = true;
- break;
- }
- }
- if (found)
- {
- type = new ILGenericParameterType(pt.Name);
- }
- else
- throw new NotSupportedException("Cannot find Generic Parameter " + pt.Name + " in " + def.FullName);
- }
- if (isByRef)
- type = type.MakeByRefType();
- if (isArray)
- type = type.MakeArrayType();
- }
- else
- type = appdomain.GetType(i.ParameterType, declaringType, this);
- parameters.Add(type);
- }
- }
- public IMethod MakeGenericMethod(IType[] genericArguments)
- {
- KeyValuePair<string, IType>[] genericParameters = new KeyValuePair<string, IType>[genericArguments.Length];
- for (int i = 0; i < genericArguments.Length; i++)
- {
- string name = def.GenericParameters[i].Name;
- IType val = genericArguments[i];
- genericParameters[i] = new KeyValuePair<string, IType>(name, val);
- }
- ILMethod m = new ILMethod(def, declaringType, appdomain);
- m.genericParameters = genericParameters;
- m.genericArguments = genericArguments;
- if (m.def.ReturnType.IsGenericParameter)
- {
- m.ReturnType = m.FindGenericArgument(m.def.ReturnType.Name);
- }
- return m;
- }
- public override string ToString()
- {
- StringBuilder sb = new StringBuilder();
- sb.Append(declaringType.FullName);
- sb.Append('.');
- sb.Append(Name);
- sb.Append('(');
- bool isFirst = true;
- if (parameters == null)
- InitParameters();
- for (int i = 0; i < parameters.Count; i++)
- {
- if (isFirst)
- isFirst = false;
- else
- sb.Append(", ");
- sb.Append(parameters[i].Name);
- sb.Append(' ');
- sb.Append(def.Parameters[i].Name);
- }
- sb.Append(')');
- return sb.ToString();
- }
- public override int GetHashCode()
- {
- if (hashCode == -1)
- hashCode = System.Threading.Interlocked.Add(ref instance_id, 1);
- return hashCode;
- }
- }
- }
|