示例#1
0
        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);
        }
示例#2
0
        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.
        }
示例#3
0
        /// <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));
        }
示例#4
0
        /// <summary>
        /// Returns the MethodReference to the advice method.
        /// </summary>
        /// <param name="visitor">The visitor.</param>
        /// <param name="filterAction">The filteraction.</param>
        /// <param name="parentType">The type containing the original method.</param>
        /// <returns>
        /// The MethodReference to the advice method.
        /// </returns>
        private MethodReference GetMethodToCall(ICecilInliningInstructionVisitor visitor,
                                                FilterAction filterAction, TypeDefinition parentType)
        {
            MethodReference result       = null;
            string          fargTarget   = getTarget(filterAction);
            string          fargSelector = getSelector(filterAction);

            if (fargTarget.Equals(FilterAction.InnerTarget) ||
                fargTarget.Equals(FilterAction.SelfTarget))
            {
                result = CecilUtilities.ResolveMethod(parentType, fargSelector, m_JpcTypes);
                if (result == null)
                {
                    result = CecilUtilities.ResolveMethod(parentType, fargSelector, m_ObjectTypes);
                }
                if (result == null)
                {
                    result = CecilUtilities.ResolveMethod(parentType, fargSelector, m_NoneTypes);
                }
            }
            else
            {
                FieldDefinition target = parentType.Fields.GetField(fargTarget);
                if (target == null)
                {
                    throw new ILWeaverException(String.Format(CultureInfo.CurrentCulture,
                                                              Properties.Resources.FieldNotFound, fargTarget));
                }

                MethodDefinition method = CecilUtilities.ResolveMethod(target.FieldType,
                                                                       fargSelector, m_JpcTypes);

                if (method == null)
                {
                    // try func(Object)
                    method = CecilUtilities.ResolveMethod(target.FieldType, fargSelector, m_ObjectTypes);
                }
                if (method == null)
                {
                    // try func()
                    method = CecilUtilities.ResolveMethod(target.FieldType, fargSelector, m_NoneTypes);
                }

                if (method == null)
                {
                    throw new ILWeaverException(String.Format(CultureInfo.CurrentCulture,
                                                              Properties.Resources.MethodNotFound, target.FieldType, fargSelector));
                }

                return(visitor.TargetAssemblyDefinition.MainModule.Import(method));
            }
            return(result);
        }
示例#5
0
        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)));
        }
示例#6
0
        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)));
                    }
                }
            }
        }
示例#7
0
        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));
            }
        }
示例#8
0
        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)));
            }
        }
示例#9
0
        /// <summary>
        /// Generate the code which has to be inserted at the place of the filter specified by the visitor.
        /// </summary>
        /// <param name="visitor">The visitor.</param>
        /// <param name="filterAction">The filter action.</param>
        /// <param name="originalCall">The original call.</param>
        public override void Weave(ICecilInliningInstructionVisitor visitor, FilterAction filterAction,
                                   MethodDefinition originalCall)
        {
            MethodReference methodToCall;

            // Get JoinPointContext
            VariableDefinition jpcVar = visitor.CreateJoinPointContextLocal();

            // Get the methodReference
            MethodReference methodReference = (MethodReference)originalCall;
            TypeDefinition  parentType      = CecilUtilities.ResolveTypeDefinition(visitor.Method.DeclaringType);

            // Get method to call
            methodToCall = GetMethodToCall(visitor, filterAction, parentType);

            if (methodToCall == null)
            {
                throw new ILWeaverException(String.Format(CultureInfo.CurrentCulture,
                                                          Properties.Resources.AdviceMethodNotFound, getSelector(filterAction), getTarget(filterAction)));
            }

            // Set JoinPointContext
            WeaveStrategyUtilities.SetJoinPointContext(visitor, methodReference, filterAction);

            // Check if it is an innercall and set innercall context:
            if (getTarget(filterAction).Equals(FilterAction.InnerTarget))
            {
                WeaveStrategyUtilities.SetInnerCall(visitor, methodToCall);
            }

            // Do the advice-call
            AdviceActionWeaveStrategy.CallAdvice(visitor, filterAction, parentType, methodToCall, jpcVar);

            // Add nop to enable debugging
            visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Nop));
        }
示例#10
0
        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)));
        }
示例#11
0
        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));
                    }
                }
            }
        }
示例#12
0
        /// <summary>
        /// Generate the code which has to be inserted at the place of the filter specified by the visitor.
        /// </summary>
        /// <param name="visitor">The visitor.</param>
        /// <param name="filterAction">The filter action.</param>
        /// <param name="originalCall">The original call.</param>
        public override void Weave(ICecilInliningInstructionVisitor visitor, FilterAction filterAction,
                                   MethodDefinition originalCall)
        {
            // Get JoinPointContext
            VariableDefinition jpcVar = visitor.CreateJoinPointContextLocal();

            FieldDefinition target = null;

            // Get the methodReference
            MethodReference methodReference = null;

            TypeDefinition parentTypeDefinition = (TypeDefinition)(visitor.Method.DeclaringType);
            TypeReference  parentTypeReference  = visitor.Method.DeclaringType;

            if (parentTypeReference.GenericParameters.Count > 0)
            {
                GenericInstanceType git = new GenericInstanceType(visitor.Method.DeclaringType);

                foreach (GenericParameter gp in originalCall.DeclaringType.GenericParameters)
                {
                    git.GenericArguments.Add(gp);
                }

                parentTypeReference = git;
            }

            // Get the called method
            if (filterAction.Target.Equals(FilterAction.InnerTarget) ||
                filterAction.Target.Equals(FilterAction.SelfTarget))
            {
                if (filterAction.Selector.Equals(originalCall.Name))
                {
                    if (parentTypeReference is GenericInstanceType)
                    {
                        methodReference = new MethodReference(originalCall.Name,
                                                              parentTypeReference, originalCall.ReturnType.ReturnType,
                                                              originalCall.HasThis, originalCall.ExplicitThis,
                                                              originalCall.CallingConvention);
                        methodReference.DeclaringType = parentTypeReference;

                        foreach (ParameterDefinition param in originalCall.Parameters)
                        {
                            methodReference.Parameters.Add(param);
                        }

                        methodReference = visitor.TargetAssemblyDefinition.MainModule.Import(methodReference, parentTypeDefinition);

                        /* This piece of code must solve the following problem:
                         *
                         * class<T> Test
                         * {
                         *    void Func(T a)
                         *    {
                         *       // inner call
                         *       Test<T>.Func(a);
                         *    }
                         * }
                         *
                         * Resolving Test<T> to a GenericInstanceType is no problem
                         * The methodReference must use the GenericInstanceType as its base type
                         * Import the new methodReference before use.
                         */
                    }
                    else
                    {
                        methodReference = originalCall;
                    }
                }
                else
                {
                    methodReference = CecilUtilities.ResolveMethod(parentTypeDefinition,
                                                                   filterAction.Selector, originalCall);
                }
            }
            else
            {
                target = parentTypeDefinition.Fields.GetField(filterAction.Target);
                if (target == null)
                {
                    throw new ILWeaverException(String.Format(CultureInfo.CurrentCulture,
                                                              Properties.Resources.FieldNotFound, filterAction.Target));
                }

                TypeDefinition   fieldType = CecilUtilities.ResolveTypeDefinition(target.FieldType);
                MethodDefinition md        = CecilUtilities.ResolveMethod(fieldType,
                                                                          filterAction.Selector, originalCall);

                if (md == null)
                {
                    throw new ILWeaverException(String.Format(CultureInfo.CurrentCulture,
                                                              "Method {0} not found in {1}", filterAction.Selector, fieldType.FullName));
                }

                methodReference = visitor.TargetAssemblyDefinition.MainModule.Import(md);
            }

            // If there is no method reference, then we cannot dispatch. Raise an exception.
            if (methodReference == null)
            {
                throw new ILWeaverException(String.Format(CultureInfo.CurrentCulture,
                                                          Properties.Resources.MethodNotFound, parentTypeReference.ToString(), filterAction.Selector));
            }


            // Check if it is an innercall and set innercall context:
            if (filterAction.Target.Equals(FilterAction.InnerTarget))
            {
                WeaveStrategyUtilities.SetInnerCall(visitor, methodReference);
            }


            // Generic arguments; add the generic parameters as generic argument to a GenericInstanceMethod
            if (originalCall.GenericParameters.Count > 0)
            {
                // Original call has generics, so add to the new memberreference
                GenericInstanceMethod gim = new GenericInstanceMethod(methodReference);
                foreach (GenericParameter gp in originalCall.GenericParameters)
                {
                    gim.GenericArguments.Add(gp);
                }
                methodReference = gim;
            }

            // Place the arguments on the stack first

            // Place target on the stack
            if (methodReference.HasThis)
            {
                if (filterAction.Target.Equals(FilterAction.InnerTarget) ||
                    filterAction.Target.Equals(FilterAction.SelfTarget))
                {
                    WeaveStrategyUtilities.LoadSelfObject(visitor, jpcVar);
                }
                else
                {
                    visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Ldarg, visitor.Method.This));
                    visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Ldfld, target));
                }
            }

            // Place arguments on the stack
            WeaveStrategyUtilities.LoadArguments(visitor, originalCall, jpcVar);

            // Call the method
            if (filterAction.Target.Equals(FilterAction.InnerTarget) &&
                filterAction.Selector.Equals(originalCall.Name))
            {
                // Because it is an inner call targeting the method itself, we must call the method
                // in the class itself. Therefore we do a Call instead of a Callvirt, to prevent that
                // the call is dispatched to an overriding method in a subclass.
                visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Call, methodReference));
            }
            else if (visitor.CalledMethod.HasThis)
            {
                // Because we dispatch to another method than the original called method, we do a Callvirt
                // so that an overriding method in a subclass may be called.
                visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Callvirt, methodReference));
            }
            else
            {
                // static method cannot be called with Callvirt.
                visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Call, methodReference));
            }

            // Store the return value:
            WeaveStrategyUtilities.StoreReturnValue(visitor, originalCall, jpcVar);

            // Restore arguments:
            WeaveStrategyUtilities.RestoreArguments(visitor, originalCall, jpcVar);
        }
示例#13
0
        /// <summary>
        /// Visits the condition literal.
        /// </summary>
        /// <remarks>
        /// Generate a call to a condition. This is a call to a boolean method.
        /// </remarks>
        /// <param name="conditionLiteral">The condition literal.</param>
        public void VisitConditionLiteral(ConditionLiteral conditionLiteral)
        {
            // Get the condition
            Condition con = GetConditionByName(conditionLiteral.Name);

            if (con == null)
            {
                throw new ILWeaverException(String.Format(CultureInfo.CurrentCulture, Properties.Resources.ConditionNotFound, conditionLiteral.Name));
            }

            // Get the parenttype
            TypeDefinition parentType = CecilUtilities.ResolveTypeDefinition(_visitor.Method.DeclaringType);

            // Get the method
            MethodReference method;
            FieldDefinition target = null;

            // Check if this is an inner or self target.
            if (con.Reference.Target != null &&
                (con.Reference.Target.Equals(Reference.InnerTarget) ||
                 con.Reference.Target.Equals(Reference.SelfTarget)
                ))
            {
                method = CecilUtilities.ResolveMethod(
                    con.Reference.Selector, WeaveType.Name,
                    con.Reference.Assembly, String.Empty);
            }
            else if (con.Reference.Target != null &&
                     (IsInternal(con.Reference.Target) || IsExternal(con.Reference.Target))
                     )
            {
                if (!Method.HasThis)
                {
                    throw new ILWeaverException(String.Format(CultureInfo.CurrentCulture,
                                                              Properties.Resources.StaticReferenceInternalExternal,
                                                              Method.Name,
                                                              Method.DeclaringType.FullName));
                }

                target = parentType.Fields.GetField(con.Reference.Target);

                TypeDefinition   fieldType = CecilUtilities.ResolveTypeDefinition(target.FieldType);
                MethodDefinition md        = CecilUtilities.ResolveMethod(fieldType, con.Reference.Selector, new Type[0]);

                // If method with no parameters cannot be found, try to find method with JPC context as parameter
                if (md == null)
                {
                    md = CecilUtilities.ResolveMethod(fieldType, con.Reference.Selector, m_JpcTypes);
                }

                if (md == null)
                {
                    throw new ILWeaverException(String.Format(CultureInfo.CurrentCulture, Properties.Resources.MethodNotFound2, con.Reference.Selector, con.Reference.Target, fieldType.FullName));
                }

                method = _visitor.TargetAssemblyDefinition.MainModule.Import(md);
            }
            else
            {
                method = CecilUtilities.ResolveMethod(
                    con.Reference.Selector,
                    con.Reference.FullTypeName,
                    con.Reference.Assembly, String.Empty);
            }

            // If we could not find the condition method, throw an exception
            if (method == null)
            {
                throw new ILWeaverException(String.Format(CultureInfo.CurrentCulture,
                                                          Properties.Resources.MethodNotFound,
                                                          con.Reference.Selector,
                                                          con.Reference.FullTypeName,
                                                          con.Reference.Assembly));
            }

            // If it is an inner or self call, we set the InnerCall context
            if (con.Reference.Target != null &&
                (con.Reference.Target.Equals(Reference.InnerTarget) ||
                 con.Reference.Target.Equals(Reference.SelfTarget)
                ))
            {
                // Set innercall context
                if (con.Reference.InnerCallContext >= 0)
                {
                    // Load the this parameter
                    if (!Method.HasThis)
                    {
                        Instructions.Add(Worker.Create(OpCodes.Ldnull));
                    }
                    else
                    {
                        Instructions.Add(Worker.Create(OpCodes.Ldarg, Method.This));
                    }

                    // Load the methodId
                    Instructions.Add(Worker.Create(OpCodes.Ldc_I4, con.Reference.InnerCallContext));

                    // Call the SetInnerCall
                    Instructions.Add(Worker.Create(OpCodes.Call,
                                                   CreateMethodReference(typeof(FilterContext).GetMethod("SetInnerCall",
                                                                                                         new Type[] { typeof(object), typeof(int) }))));
                }

                // Load the this pointer
                Instructions.Add(Worker.Create(OpCodes.Ldarg, Method.This));
            }
            // internal/external and not static:
            else if (target != null && method.HasThis)
            {
                // Load the this pointer
                Instructions.Add(Worker.Create(OpCodes.Ldarg, Method.This));

                // Load the field
                Instructions.Add(Worker.Create(OpCodes.Ldfld, target));
            }
            // else do nothing, because of static call

            // Convert to a method definition so we can inspect the custom attributes
            MethodDefinition methodDef = (MethodDefinition)method;

            if (methodDef != null)
            {
                // Find a custom attribute to use
                foreach (CustomAttribute ca in methodDef.CustomAttributes)
                {
                    // Retrieve the type name of the custom attribute
                    String typeName = ca.Constructor.DeclaringType.ToString();

                    // Check if the custom attribute is called ConditionParameter so we do not activate all kinds of attributes
                    if (typeName.Contains(ConditionParameterName))
                    {
                        // Resolve the CP
                        ConditionParameterAttribute cpa = ResolveConditionParameter(typeName);

                        // Do we have a CPA?
                        if (cpa != null)
                        {
                            // Check if the condition is valid for this code generation
                            if (cpa.IsValidCondition(methodDef))
                            {
                                // Generate the code needed for this condition
                                cpa.Generate(_visitor, Method, methodDef);
                            }
                            else
                            {
                                // Throw an exception since the condition is not valid. We cannot create valid code for this.
                                throw new ILWeaverException(String.Format(CultureInfo.CurrentCulture,
                                                                          Properties.Resources.ConditionParameterInvalid,
                                                                          typeName, methodDef.ToString(), cpa.RequiredCondition));
                            }
                        }
                        else
                        {
                            // Throw an exception, we cannot create the custom attribute
                            throw new ILWeaverException(String.Format(CultureInfo.CurrentCulture,
                                                                      Properties.Resources.ConditionParameterNotFound,
                                                                      typeName));
                        }

                        // Quit the for loop. If there are more custom attributes, we simply skip them.
                        break;
                    }
                }
            }

            // Check if we have to add the JPC
            // Legacy code, should be able to do this using the ConditionParameter?
            if (method.Parameters.Count == 1)
            {
                if (method.Parameters[0].ParameterType.FullName.Equals(typeof(JoinPointContext).FullName))
                {
                    VariableDefinition jpcVar = _visitor.CreateJoinPointContextLocal();
                    Instructions.Add(Worker.Create(OpCodes.Ldloc, jpcVar));
                }
            }

            // Create a call instruction
            Instructions.Add(Worker.Create(OpCodes.Call, TargetAssemblyDefinition.MainModule.Import(method)));
        }
示例#14
0
        public override void Weave(ICecilInliningInstructionVisitor visitor, FilterAction filterAction,
                                   MethodDefinition originalCall)
        {
            // The method we have to call, an Execute(JoinPointContext) function.
            MethodReference methodToCall;

            // Create FilterAction object:
            FilterActionElement filterActionElement;

            filterActionElement = DefaultWeaveStrategy.GetFilterActionElement(visitor.WeaveConfiguration.FilterActions, filterAction.FullName);

            if (filterActionElement == null)
            {
                throw new ILWeaverException(string.Format(CultureInfo.CurrentCulture, Properties.Resources.CouldNotResolveFilterAction, filterAction.FullName));
            }

            // Get JoinPointContext
            VariableDefinition jpcVar = null;

            if (filterActionElement.CreateJPC)
            {
                jpcVar = visitor.CreateJoinPointContextLocal();
            }

            // Get the methodReference
            MethodReference methodReference = (MethodReference)originalCall;

            // TypeDefinition parentType = CecilUtilities.ResolveTypeDefinition(methodReference.DeclaringType);

            // Set JoinPointContext
            if (filterActionElement.CreateJPC)
            {
                WeaveStrategyUtilities.SetJoinPointContext(visitor, methodReference, filterAction);
            }

            TypeReference typeRef =
                CecilUtilities.ResolveType(filterAction.FullName, filterActionElement.Assembly, null);
            TypeDefinition typeDef =
                CecilUtilities.ResolveTypeDefinition(typeRef);
            MethodReference constructor = typeDef.Constructors.GetConstructor(false, new Type[0]);

            if (constructor == null)
            {
                throw new ILWeaverException(String.Format(CultureInfo.CurrentCulture, Properties.Resources.TypeNotFound, filterAction.FullName));
            }

            constructor = visitor.TargetAssemblyDefinition.MainModule.Import(constructor);
            visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Newobj, constructor));

            // Get method to call
            methodToCall = CecilUtilities.ResolveMethod(typeDef, "Execute", new Type[] { typeof(JoinPointContext) });

            // Check for null value
            if (methodToCall == null)
            {
                throw new ILWeaverException(String.Format(CultureInfo.CurrentCulture, Properties.Resources.AdviceMethodNotFound, "Execute", filterAction.FullName));
            }

            methodToCall = visitor.TargetAssemblyDefinition.MainModule.Import(methodToCall);

            // Load the JoinPointObject as the parameter if required
            if (filterActionElement.CreateJPC)
            {
                visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Ldloc, jpcVar));
            }
            else
            {
                visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Ldnull));
            }

            // Do the call
            // We can safely emit a callvirt here. The JITter will make the right call.
            visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Callvirt, methodToCall));
        }