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; } } }
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(); } } 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; } }
private void Prewarm(HashSet <ILMethod> alreadyPrewarmed) { if (alreadyPrewarmed != null && alreadyPrewarmed.Add(this) == false) { return; } if (GenericParameterCount > 0 && !IsGenericInstance) { return; } //当前方法用到的IType,提前InitializeMethods()。各个子调用,提前InitParameters() var body = Body; //当前方法用到的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 ct) { var fields = ct.Fields; ILRuntime.CLR.Utils.Extensions.GetTypeFlags(ct.TypeForCLR); } } 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 ilm) { //如果参数alreadyPrewarmed不为空,则不仅prewarm当前方法,还会递归prewarm所有子调用 //如果参数alreadyPrewarmed为空,则只prewarm当前方法 if (alreadyPrewarmed != null) { ilm.Prewarm(alreadyPrewarmed); } } else if (m is CLRMethod clrm) { 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; } } }