public override void Weave(ICecilInliningInstructionVisitor visitor, FilterAction filterAction, MethodDefinition originalCall) { VariableDefinition jpcVar = visitor.CreateJoinPointContextLocal(); WeaveStrategyUtilities.SetJoinPointContext(visitor, (MethodReference)originalCall, filterAction); MethodBase mi = typeof(CacheAction).GetMethod("getCachedValue", new Type[] { typeof(JoinPointContext) }); MethodReference methodToCall = CecilUtilities.CreateMethodReference(visitor.TargetAssemblyDefinition, mi); visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Ldloc, jpcVar)); visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Call, methodToCall)); Instruction noCache = visitor.Worker.Create(OpCodes.Nop); visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Brfalse, noCache)); // Load JoinPointContext visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Ldloc, jpcVar)); // Get returnvalue visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Callvirt, CecilUtilities.CreateMethodReference(visitor.TargetAssemblyDefinition, CachedMethodDefinition.JoinPointContextGetReturnValue))); // Check if returnvalue is value type, then unbox, else cast if (originalCall.ReturnType.ReturnType.IsValueType || originalCall.ReturnType.ReturnType is GenericParameter) { visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Unbox_Any, originalCall.ReturnType.ReturnType)); } else { visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Castclass, originalCall.ReturnType.ReturnType)); } visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Ret)); visitor.Instructions.Add(noCache); }
public override void Generate(ICecilInliningInstructionVisitor visitor, MethodDefinition originalCall, MethodDefinition conditionMethod) { // We need to get the MethodInfo object and place it on the stack so we can supply it to the FMC. // // Load the current method base. This is a trick in IL (.NET2) to get the MethodBase using lightweight reflection. // See for more information: http://www.interact-sw.co.uk/iangblog/2005/08/31/methodinfofromtoken // In IL code: // ldtoken method void SomeClass::SomeMethod() // call class [mscorlib]System.Reflection.MethodBase [mscorlib]System.Reflection.MethodBase::GetMethodFromHandle(valuetype [mscorlib]System.RuntimeMethodHandle) // visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Ldtoken, visitor.TargetAssemblyDefinition.MainModule.Import(originalCall))); if (originalCall.GenericParameters.Count > 0 || originalCall.DeclaringType.GenericParameters.Count > 0) { // If it is a generic we have to add the declaring type token. This is not directly supported in tools like Reflector. visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Ldtoken, visitor.TargetAssemblyDefinition.MainModule.Import(originalCall.DeclaringType))); visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Call, CecilUtilities.CreateMethodReference(visitor.TargetAssemblyDefinition, CachedMethodDefinition.GetMethodFromHandleExt))); } else { visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Call, CecilUtilities.CreateMethodReference(visitor.TargetAssemblyDefinition, CachedMethodDefinition.GetMethodFromHandle))); } // We now have a MethodBase object on the stack. Return control to the caller and let them call the FMC. }
/// <summary> /// Weaves the error action. /// </summary> /// <param name="visitor">The visitor.</param> /// <param name="filterAction">The filter action.</param> /// <param name="originalCall">The original call.</param> /// <remarks> /// Generate exception throw /// </remarks> /// <example> /// The following construction should be created: /// <code> /// throw new Exception(); /// </code> /// or in IL code: /// <code> /// newobj instance void [mscorlib]System.Exception::.ctor() /// throw /// </code> /// </example> public override void Weave(ICecilInliningInstructionVisitor visitor, FilterAction filterAction, MethodDefinition originalCall) { // Create an exception visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Newobj, CecilUtilities.CreateMethodReference(visitor.TargetAssemblyDefinition, CachedMethodDefinition.ExceptionConstructor))); // Throw the exception visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Throw)); }
public static void SetInnerCall(ICecilInliningInstructionVisitor visitor, MethodReference method) { MethodDefinition methodDef = CecilUtilities.ResolveMethod( visitor.Method.DeclaringType, method.Name, method); // Get the weaveMethod to which the innercall is directed WeaveMethod weaveMethod = visitor.WeaveType.GetMethod(methodDef.ToString()); //if(weaveMethod == null) //{ // // if using MethodReference failed, try using the MethodDefinition (in some cases the ToString // // leads to different signatures). // MethodDefinition methodDef = CecilUtilities.ResolveMethodDefinition(method); // if(methodDef != null) // { // weaveMethod = visitor.WeaveType.GetMethod(method.ToString()); // } if (weaveMethod == null) { // If weave method could not be found, this means that the method // does not have filters woven and so no inner call context needs // to be set. return; } //} // Load the this parameter if (!visitor.Method.HasThis || visitor.Method.DeclaringType.IsValueType) { visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Ldnull)); } else { visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Ldarg, visitor.Method.This)); } // Load the methodId visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Ldc_I4, weaveMethod.Id)); // Call the SetInnerCall visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Call, CecilUtilities.CreateMethodReference(visitor.TargetAssemblyDefinition, CachedMethodDefinition.SetInnerCall))); }
public static void RestoreArguments(ICecilInliningInstructionVisitor visitor, MethodReference originalMethod, VariableDefinition joinPointContextVariable) { foreach (ParameterDefinition param in originalMethod.Parameters) { int ordinal = param.Sequence - 1;// (originalMethod.HasThis ? 1 : 0); //check for reference: if (param.ParameterType.FullName.EndsWith("&")) { if (visitor.FilterType == FilterType.InputFilter) { // // Store value from out/ref into JPC // // Load jpc visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Ldloc, joinPointContextVariable)); // Load ordinal visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Ldc_I4, ordinal)); // Load param visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Ldarg, param)); // Load value visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Ldobj, param.ParameterType)); // If valuetype, box if (param.ParameterType.IsValueType || param.ParameterType is GenericParameter) { visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Box, param.ParameterType)); } // Store value // Call the SetArgumentValue(int16, object) function visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Callvirt, CecilUtilities.CreateMethodReference(visitor.TargetAssemblyDefinition, CachedMethodDefinition.JoinPointContextSetArgumentValue))); } } } }
public static void LoadSelfObject(ICecilInliningInstructionVisitor visitor, VariableDefinition joinPointContextVariable) { if (visitor.FilterType == FilterType.InputFilter) { // Load this visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Ldarg, visitor.Method.This)); } else { // Load JoinPointContext visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Ldloc, joinPointContextVariable)); // Call get_StartTarget in JoinPointContext visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Call, CecilUtilities.CreateMethodReference(visitor.TargetAssemblyDefinition, CachedMethodDefinition.JoinPointContextGetStartTarget))); // Do a cast visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Castclass, visitor.CalledMethod.DeclaringType)); } }
public static void StoreReturnValue(ICecilInliningInstructionVisitor visitor, MethodReference originalCall, VariableDefinition joinPointContextVariable) { // Store returnvalue if (!originalCall.ReturnType.ReturnType.FullName.Equals(CecilUtilities.VoidType)) { // Check if returnvalue is value type, then box if (originalCall.ReturnType.ReturnType.IsValueType || originalCall.ReturnType.ReturnType is GenericParameter) { visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Box, originalCall.ReturnType.ReturnType)); } // Load jpc visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Ldloc, joinPointContextVariable)); // Call set_ReturnValue in JoinPointContext visitor.Instructions.Add(visitor.Worker.Create( OpCodes.Call, CecilUtilities.CreateMethodReference(visitor.TargetAssemblyDefinition, CachedMethodDefinition.JoinPointContextSetReturnValue))); } }
public static void SetJoinPointContext( ICecilInliningInstructionVisitor visitor, MethodReference originalCall, FilterAction filterAction) { VariableDefinition jpcVar = visitor.CreateJoinPointContextLocal(); // Store current target if (filterAction.Target.Equals(FilterAction.InnerTarget) || filterAction.Target.Equals(FilterAction.SelfTarget)) { visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Ldloc, jpcVar)); visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Ldloc, jpcVar)); visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Callvirt, CecilUtilities.CreateMethodReference(visitor.TargetAssemblyDefinition, CachedMethodDefinition.JoinPointContextGetStartTarget))); visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Callvirt, CecilUtilities.CreateMethodReference(visitor.TargetAssemblyDefinition, CachedMethodDefinition.JoinPointContextSetCurrentTarget))); } else if (visitor.Method.HasThis) { TypeDefinition parentType = CecilUtilities.ResolveTypeDefinition(visitor.Method.DeclaringType); FieldDefinition field = parentType.Fields.GetField(filterAction.Target); if (field == null) { throw new ILWeaverException(String.Format(CultureInfo.CurrentCulture, Properties.Resources.FieldNotFound, filterAction.Target)); } visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Ldloc, jpcVar)); visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Ldarg, visitor.Method.This)); visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Ldfld, field)); visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Callvirt, CecilUtilities.CreateMethodReference(visitor.TargetAssemblyDefinition, CachedMethodDefinition.JoinPointContextSetCurrentTarget))); } else { // set to null for static methods visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Ldloc, jpcVar)); visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Ldnull)); visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Callvirt, CecilUtilities.CreateMethodReference(visitor.TargetAssemblyDefinition, CachedMethodDefinition.JoinPointContextSetCurrentTarget))); } // store current selector visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Ldloc, jpcVar)); visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Ldstr, filterAction.Selector)); visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Callvirt, CecilUtilities.CreateMethodReference(visitor.TargetAssemblyDefinition, CachedMethodDefinition.JoinPointContextSetCurrentSelector))); // Store substitution target //if (filterAction.SubstitutionTarget.Equals(FilterAction.InnerTarget) || // filterAction.SubstitutionTarget.Equals(FilterAction.SelfTarget)) //{ // visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Ldloc, jpcVar)); // visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Ldloc, jpcVar)); // visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Callvirt, // CecilUtilities.CreateMethodReference(visitor.TargetAssemblyDefinition, // CachedMethodDefinition.JoinPointContextGetStartTarget))); // visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Callvirt, // CecilUtilities.CreateMethodReference(visitor.TargetAssemblyDefinition, // CachedMethodDefinition.JoinPointContextGetSubstitutionTarget))); //} //else if (visitor.Method.HasThis) //{ // TypeDefinition parentType = CecilUtilities.ResolveTypeDefinition(visitor.Method.DeclaringType); // FieldDefinition field = parentType.Fields.GetField(filterAction.SubstitutionTarget); // if (field == null) // { // throw new ILWeaverException(String.Format(CultureInfo.CurrentCulture, // Properties.Resources.FieldNotFound, filterAction.SubstitutionTarget)); // } // visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Ldloc, jpcVar)); // visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Ldarg, visitor.Method.This)); // visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Ldfld, field)); // visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Callvirt, // CecilUtilities.CreateMethodReference(visitor.TargetAssemblyDefinition, // CachedMethodDefinition.JoinPointContextSetSubstitutionTarget))); //} //else //{ // // set to null for static methods // visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Ldloc, jpcVar)); // visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Ldnull)); // visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Callvirt, // CecilUtilities.CreateMethodReference(visitor.TargetAssemblyDefinition, // CachedMethodDefinition.JoinPointContextSetSubstitutionTarget))); //} // store substitution selector // TODO no longer relevant //visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Ldloc, jpcVar)); //visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Ldstr, filterAction.SubstitutionSelector)); //visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Callvirt, // CecilUtilities.CreateMethodReference(visitor.TargetAssemblyDefinition, // CachedMethodDefinition.JoinPointContextSetSubstitutionSelector))); }
public static void LoadArguments(ICecilInliningInstructionVisitor visitor, MethodReference originalMethod, VariableDefinition joinPointContextVariable) { foreach (ParameterDefinition param in originalMethod.Parameters) { int ordinal = param.Sequence - 1;// -(originalMethod.HasThis ? 1 : 0); //check for reference: if (param.ParameterType.FullName.EndsWith("&")) { if (visitor.FilterType == FilterType.InputFilter) { // For out parameters that are value type, check whether a value was set if ((param.Attributes & Mono.Cecil.ParameterAttributes.Out) == Mono.Cecil.ParameterAttributes.Out && param.ParameterType.IsValueType) { // // Store value from joinpointcontext into out // // Load param visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Ldarg, param)); // Load jpc visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Ldloc, joinPointContextVariable)); // Load the ordinal visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Ldc_I4, ordinal)); // Call the GetArgumentValue(int16) function visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Callvirt, CecilUtilities.CreateMethodReference(visitor.TargetAssemblyDefinition, CachedMethodDefinition.JoinPointContextGetArgumentValue))); // Duplicate value visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Dup)); // Load null visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Ldnull)); // Check equals visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Ceq)); // If not null, branch Instruction falseNop = visitor.Worker.Create(OpCodes.Nop); visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Brfalse, falseNop)); // True branch // Pop unnecessary argument value visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Pop)); // Jump to end (let parameter on the stack Instruction endNop = visitor.Worker.Create(OpCodes.Nop); visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Br, endNop)); // End True branch // False branch // Nop instruction visitor.Instructions.Add(falseNop); // Unbox value visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Unbox_Any, param.ParameterType)); // Store value visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Stobj, param.ParameterType)); // Load param visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Ldarg, param)); // End False branch // End nop instruction visitor.Instructions.Add(endNop); } else { // // Store value from joinpointcontext into out // // Load param visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Ldarg, param)); // Duplicate visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Dup)); // Load jpc visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Ldloc, joinPointContextVariable)); // Load the ordinal visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Ldc_I4, ordinal)); // Call the GetArgumentValue(int16) function visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Callvirt, CecilUtilities.CreateMethodReference(visitor.TargetAssemblyDefinition, CachedMethodDefinition.JoinPointContextGetArgumentValue))); // If valuetype unbox, else cast if (param.ParameterType.IsValueType || param.ParameterType is GenericParameter) { // Unbox value visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Unbox_Any, param.ParameterType)); } else { // Cast visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Castclass, param.ParameterType)); } // Store value visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Stobj, param.ParameterType)); } } } else //not a reference parameter { // Load jpc visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Ldloc, joinPointContextVariable)); // Load the ordinal visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Ldc_I4, ordinal)); // Call the GetArgumentValue(int16) function visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Callvirt, CecilUtilities.CreateMethodReference(visitor.TargetAssemblyDefinition, CachedMethodDefinition.JoinPointContextGetArgumentValue))); // Check if parameter is value type, then unbox if (param.ParameterType.IsValueType || param.ParameterType is GenericParameter) { visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Unbox_Any, param.ParameterType)); } else { visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Castclass, param.ParameterType)); } } } }