123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984 |
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using System.Reflection;
- using ILRuntime.Mono.Cecil;
- using ILRuntime.Runtime;
- using ILRuntime.Runtime.Intepreter.OpCodes;
- using ILRuntime.Runtime.Intepreter;
- using ILRuntime.Runtime.Intepreter.RegisterVM;
- using ILRuntime.Runtime.Debugger;
- using ILRuntime.CLR.TypeSystem;
- using ILRuntime.Reflection;
- namespace ILRuntime.CLR.Method
- {
- public class ILMethod : IMethod
- {
- OpCode[] body;
- OpCodeR[] bodyRegister;
- Dictionary<int, RegisterVMSymbol> registerSymbols;
- bool symbolFixed;
- MethodDefinition def;
- List<IType> parameters;
- ILRuntime.Runtime.Enviorment.AppDomain appdomain;
- ILType declaringType;
- ExceptionHandler[] exceptionHandler, exceptionHandlerR;
- KeyValuePair<string, IType>[] genericParameters;
- IType[] genericArguments;
- Dictionary<int, int[]> jumptables, jumptablesR;
- bool isDelegateInvoke;
- bool jitPending;
- ILRuntimeMethodInfo refletionMethodInfo;
- ILRuntimeConstructorInfo reflectionCtorInfo;
- int paramCnt, localVarCnt, stackRegisterCnt;
- int jitFlags;
- bool jitOnDemand;
- bool jitImmediately;
- int warmupCounter = 0;
- Mono.Collections.Generic.Collection<Mono.Cecil.Cil.VariableDefinition> variables;
- int hashCode = -1;
- static int instance_id = 0x10000000;
- const int JITWarmUpThreshold = 10;
- public bool Compiling { get; set; }
- public bool IsRegisterBodyReady { get { return bodyRegister != null; } }
- public MethodDefinition Definition { get { return def; } }
- public Dictionary<int, int[]> JumpTables { get { return jumptables; } }
- public Dictionary<int, int[]> JumpTablesRegister { get { return jumptablesR; } }
- internal Dictionary<int, RegisterVMSymbol> RegisterVMSymbols { get { return registerSymbols; } }
- internal int JITFlags { get { return jitFlags; } }
- internal bool IsRegisterVMSymbolFixed { get { return symbolFixed; } }
- internal IDelegateAdapter DelegateAdapter { get; set; }
- internal int StartLine { get; set; }
- internal int EndLine { get; set; }
- public ILRuntime.Runtime.Enviorment.AppDomain AppDomain { get { return appdomain; } }
- 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
- {
- return exceptionHandler;
- }
- }
- internal ExceptionHandler[] ExceptionHandlerRegister
- {
- get
- {
- return exceptionHandlerR;
- }
- }
- 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 bool ShouldUseRegisterVM
- {
- get
- {
- if (bodyRegister != null)
- {
- body = null;
- exceptionHandler = null;
- return true;
- }
- else
- {
- if (jitImmediately)
- {
- InitCodeBody(true);
- return true;
- }
- else
- {
- if (jitOnDemand)
- {
- warmupCounter++;
- if (warmupCounter > JITWarmUpThreshold && !jitPending)
- {
- jitPending = true;
- AppDomain.EnqueueJITCompileJob(this);
- }
- }
- return false;
- }
- }
- }
- }
- public ILMethod(MethodDefinition def, ILType type, ILRuntime.Runtime.Enviorment.AppDomain domain, int flags)
- {
- this.def = def;
- declaringType = type;
- this.jitFlags = flags;
- 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(def.HasCustomAttributes)
- {
- for(int i = 0; i < def.CustomAttributes.Count; i++)
- {
- int f;
- if(def.CustomAttributes[i].GetJITFlags(domain, out f))
- {
- this.jitFlags = f;
- break;
- }
- }
- }
- jitImmediately = (jitFlags & ILRuntimeJITFlags.JITImmediately) == ILRuntimeJITFlags.JITImmediately;
- jitOnDemand = (jitFlags & ILRuntimeJITFlags.JITOnDemand) == ILRuntimeJITFlags.JITOnDemand;
- #if DEBUG && !DISABLE_ILRUNTIME_DEBUG
- if (def.HasBody)
- {
- var sp = GetValidSequence(0, 1);
- if (sp != null)
- {
- StartLine = sp.StartLine;
- sp = GetValidSequence(def.Body.Instructions.Count - 1, -1);
- if (sp != null)
- {
- EndLine = sp.EndLine;
- }
- }
- }
- #endif
- }
- public void FixRegisterVMSymbol()
- {
- if (!symbolFixed && registerSymbols != null)
- {
- symbolFixed = true;
- JITCompiler.FixSymbol(registerSymbols);
- }
- }
- Mono.Cecil.Cil.SequencePoint GetValidSequence(int startIdx, int dir)
- {
- var seqMapping = def.DebugInformation.GetSequencePointMapping();
- var cur = DebugService.FindSequencePoint(def.Body.Instructions[startIdx], seqMapping);
- while (cur != null && cur.StartLine == 0x0feefee)
- {
- startIdx += dir;
- if (startIdx >= 0 && startIdx < def.Body.Instructions.Count)
- {
- cur = DebugService.FindSequencePoint(def.Body.Instructions[startIdx], seqMapping);
- }
- else
- break;
- }
- return cur;
- }
- 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(false);
- return body;
- }
- }
- internal OpCodeR[] BodyRegister
- {
- get
- {
- if (bodyRegister == null)
- InitCodeBody(true);
- return bodyRegister;
- }
- }
- public bool HasBody
- {
- get
- {
- return body != null;
- }
- }
- public int LocalVariableCount
- {
- get
- {
- return localVarCnt;
- }
- }
- public int StackRegisterCount
- {
- get
- {
- return stackRegisterCnt;
- }
- }
- public bool IsConstructor
- {
- get
- {
- return def.IsConstructor;
- }
- }
- public bool IsVirtual
- {
- get
- {
- return def.IsVirtual;
- }
- }
- 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;
- }
- public void Prewarm(bool recursive)
- {
- HashSet<ILMethod> alreadyPrewarmed = null;
- if (recursive)
- {
- alreadyPrewarmed = new HashSet<ILMethod>();
- }
- Prewarm(alreadyPrewarmed);
- }
- void PrewarmBody(HashSet<ILMethod> alreadyPrewarmed)
- {
- //当前方法用到的IType,提前InitializeMethods()。各个子调用,提前InitParameters()
- var body = Body;
- foreach (var ins in body)
- {
- switch (ins.Code)
- {
- case OpCodeEnum.Call:
- case OpCodeEnum.Newobj:
- case OpCodeEnum.Ldftn:
- case OpCodeEnum.Ldvirtftn:
- case OpCodeEnum.Callvirt:
- {
- var m = appdomain.GetMethod(ins.TokenInteger);
- if (m is ILMethod)
- {
- ILMethod ilm = (ILMethod)m;
- //如果参数alreadyPrewarmed不为空,则不仅prewarm当前方法,还会递归prewarm所有子调用
- //如果参数alreadyPrewarmed为空,则只prewarm当前方法
- if (alreadyPrewarmed != null)
- {
- ilm.Prewarm(alreadyPrewarmed);
- }
- }
- else if (m is CLRMethod)
- {
- CLRMethod clrm = (CLRMethod)m;
- ILRuntime.CLR.Utils.Extensions.GetTypeFlags(clrm.DeclearingType.TypeForCLR);
- }
- }
- break;
- case OpCodeEnum.Ldfld:
- case OpCodeEnum.Stfld:
- case OpCodeEnum.Ldflda:
- case OpCodeEnum.Ldsfld:
- case OpCodeEnum.Ldsflda:
- case OpCodeEnum.Stsfld:
- case OpCodeEnum.Ldtoken:
- {
- //提前InitializeBaseType()
- var t = appdomain.GetType((int)(ins.TokenLong >> 32));
- if (t != null)
- {
- var baseType = t.BaseType;
- }
- }
- break;
- }
- }
- }
- void PrewarmBodyRegister(HashSet<ILMethod> alreadyPrewarmed)
- {
- //当前方法用到的IType,提前InitializeMethods()。各个子调用,提前InitParameters()
- var body = BodyRegister;
- foreach (var ins in body)
- {
- switch (ins.Code)
- {
- case OpCodeREnum.Call:
- case OpCodeREnum.Newobj:
- case OpCodeREnum.Ldftn:
- case OpCodeREnum.Ldvirtftn:
- case OpCodeREnum.Callvirt:
- {
- var m = appdomain.GetMethod(ins.Operand);
- if (m is ILMethod)
- {
- ILMethod ilm = (ILMethod)m;
- //如果参数alreadyPrewarmed不为空,则不仅prewarm当前方法,还会递归prewarm所有子调用
- //如果参数alreadyPrewarmed为空,则只prewarm当前方法
- if (alreadyPrewarmed != null)
- {
- ilm.Prewarm(alreadyPrewarmed);
- }
- }
- else if (m is CLRMethod)
- {
- CLRMethod clrm = (CLRMethod)m;
- ILRuntime.CLR.Utils.Extensions.GetTypeFlags(clrm.DeclearingType.TypeForCLR);
- }
- }
- break;
- case OpCodeREnum.Ldfld:
- case OpCodeREnum.Stfld:
- case OpCodeREnum.Ldflda:
- case OpCodeREnum.Ldsfld:
- case OpCodeREnum.Ldsflda:
- case OpCodeREnum.Stsfld:
- case OpCodeREnum.Ldtoken:
- {
- //提前InitializeBaseType()
- var t = appdomain.GetType((int)(ins.OperandLong >> 32));
- if (t != null)
- {
- var baseType = t.BaseType;
- }
- }
- break;
- }
- }
- }
- private void Prewarm(HashSet<ILMethod> alreadyPrewarmed)
- {
- if (alreadyPrewarmed != null && alreadyPrewarmed.Add(this) == false)
- return;
- if (GenericParameterCount > 0 && !IsGenericInstance)
- return;
- //当前方法用到的CLR局部变量,提前InitializeFields()、GetTypeFlags()
- for (int i = 0; i < LocalVariableCount; i++)
- {
- var v = Variables[i];
- var vt = v.VariableType;
- IType t;
- if (vt.IsGenericParameter)
- {
- t = FindGenericArgument(vt.Name);
- }
- else
- {
- t = appdomain.GetType(v.VariableType, DeclearingType, this);
- }
- if (t is CLRType)
- {
- CLRType ct = (CLRType)t;
- var fields = ct.Fields;
- ILRuntime.CLR.Utils.Extensions.GetTypeFlags(ct.TypeForCLR);
- }
- }
- if (jitImmediately || jitOnDemand)
- PrewarmBodyRegister(alreadyPrewarmed);
- else
- PrewarmBody(alreadyPrewarmed);
- }
- internal void InitCodeBody(bool register)
- {
- if (def.HasBody)
- {
- localVarCnt = def.Body.Variables.Count;
- Dictionary<Mono.Cecil.Cil.Instruction, int> addr = new Dictionary<Mono.Cecil.Cil.Instruction, int>();
- bool noRelease = false;
- if (register)
- {
- JITCompiler jit = new JITCompiler(appdomain, declaringType, this);
- bodyRegister = jit.Compile(out stackRegisterCnt, out jumptablesR, addr, out registerSymbols);
- }
- else
- {
- InitStackCodeBody(addr);
- if (jitOnDemand)
- noRelease = bodyRegister == null;
- }
- if (def.Body.ExceptionHandlers.Count > 0)
- {
- ExceptionHandler[] ehs;
- if (register)
- {
- if (exceptionHandlerR == null)
- exceptionHandlerR = new Method.ExceptionHandler[def.Body.ExceptionHandlers.Count];
- ehs = exceptionHandlerR;
- }
- else
- {
- if (exceptionHandler == null)
- exceptionHandler = new Method.ExceptionHandler[def.Body.ExceptionHandlers.Count];
- ehs = exceptionHandler;
- }
- for (int i = 0; i < def.Body.ExceptionHandlers.Count; i++)
- {
- var eh = def.Body.ExceptionHandlers[i];
- ExceptionHandler e = new ExceptionHandler();
- e.HandlerStart = addr[eh.HandlerStart];
- e.HandlerEnd = eh.HandlerEnd != null ? addr[eh.HandlerEnd] - 1 : def.Body.Instructions.Count - 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();
- }
- ehs[i] = e;
- }
- //Mono.Cecil.Cil.ExceptionHandlerType.
- }
- variables = def.Body.Variables;
- #if !DEBUG || DISABLE_ILRUNTIME_DEBUG
- //Release Method body to save memory
- if(!noRelease)
- def.Body = null;
- #endif
- }
- else
- body = new OpCode[0];
- }
- void InitStackCodeBody(Dictionary<Mono.Cecil.Cil.Instruction, int> addr)
- {
- body = new OpCode[def.Body.Instructions.Count];
- 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);
- if (i > 0 && c.OpCode.Code == Mono.Cecil.Cil.Code.Callvirt && def.Body.Instructions[i - 1].OpCode.Code == Mono.Cecil.Cil.Code.Constrained)
- {
- body[i - 1].TokenLong = body[i].TokenInteger;
- }
- }
- }
- 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(code.Code == OpCodeEnum.Callvirt && m is ILMethod)
- {
- ILMethod ilm = (ILMethod)m;
- if (!ilm.def.IsAbstract && !ilm.def.IsVirtual && !ilm.DeclearingType.IsInterface)
- code.Code = OpCodeEnum.Call;
- }
- if (invalidToken)
- code.TokenInteger = m.GetHashCode();
- else
- code.TokenInteger = token.GetHashCode();
- }
- else
- {
- //Cannot find method or the method is dummy
- MethodReference _ref = (MethodReference)token;
- int paramCnt = _ref.HasParameters ? _ref.Parameters.Count : 0;
- if (_ref.HasThis)
- paramCnt++;
- code.TokenLong = paramCnt;
- }
- }
- 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.TokenLong = appdomain.GetStaticFieldIndex(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;
- }
- }
- internal 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 || isGenericParameter)
- {
- return t.GetHashCode();
- }
- else
- return token.GetHashCode();
- }
- return 0;
- }
- bool CheckHasGenericParamter(object token)
- {
- if (token is TypeReference)
- {
- TypeReference _ref = ((TypeReference)token);
- if (_ref.IsArray)
- return CheckHasGenericParamter(((ArrayType)_ref).ElementType);
- 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;
- int rank = 1;
- TypeReference pt = i.ParameterType;
- if (pt.IsByReference)
- {
- isByRef = true;
- pt = ((ByReferenceType)pt).ElementType;
- }
- if (pt.IsArray)
- {
- isArray = true;
- rank = ((ArrayType)pt).Rank;
- pt = ((ArrayType)pt).ElementType;
- }
- 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);
- }
- }
- else
- type = appdomain.GetType(pt, declaringType, this);
- if (isArray)
- type = type.MakeArrayType(rank);
- if (isByRef)
- type = type.MakeByRefType();
- 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, jitFlags);
- m.genericParameters = genericParameters;
- m.genericArguments = genericArguments;
- if (m.def.ReturnType.IsGenericParameter)
- {
- m.ReturnType = m.FindGenericArgument(m.def.ReturnType.Name);
- }
- return m;
- }
- string cachedName;
- public override string ToString()
- {
- if (cachedName == null)
- {
- 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].FullName);
- sb.Append(' ');
- sb.Append(def.Parameters[i].Name);
- }
- sb.Append(')');
- cachedName = sb.ToString();
- }
- return cachedName;
- }
- public override int GetHashCode()
- {
- if (hashCode == -1)
- hashCode = System.Threading.Interlocked.Add(ref instance_id, 1);
- return hashCode;
- }
- bool? isExtend;
- public bool IsExtend
- {
- get
- {
- if (isExtend == null)
- {
- isExtend = this.IsExtendMethod();
- }
- return isExtend.Value;
- }
- }
- }
- }
|