public override InstructionBlockChain CreateAspectInstance()
        {
            var aspectTypeReference = _module.ImportReference(Info.AspectAttribute.AttributeType);

            _aspectField = _module.ImportReference(_stateMachine.AddPublicInstanceField(aspectTypeReference));

            var loadMachine = new VariablePersistable(_stateMachineLocal).Load(true);

            var newObjectAspectBlock = _creator.CreateAndNewUpAspect(Info.AspectAttribute);
            var loadOnStack          = new InstructionBlock("Load on stack", Instruction.Create(OpCodes.Ldloc, newObjectAspectBlock.Variable));
            var storeField           = new InstructionBlock("Store Field", Instruction.Create(OpCodes.Stfld, _aspectField));

            var newObjectAspectBlockChain = new InstructionBlockChain();

            newObjectAspectBlockChain.Add(loadMachine);
            newObjectAspectBlockChain.Add(newObjectAspectBlock);
            newObjectAspectBlockChain.Add(loadOnStack);
            newObjectAspectBlockChain.Add(storeField);

            AspectPersistable = new FieldPersistable(new VariablePersistable(_stateMachineLocal), _aspectField);
            return(newObjectAspectBlockChain);
        }
 public void Add(InstructionBlock block)
 {
     InstructionBlocks.Add(block);
 }
Example #3
0
        protected virtual void WeaveOnException(IList <AspectData> allAspects, Instruction instructionCallStart, Instruction instructionCallEnd, Instruction instructionAfterCall, IPersistable returnValue)
        {
            var realInstructionAfterCall = instructionAfterCall ?? instructionCallEnd.Next;
            var tryLeaveInstruction      = Instruction.Create(OpCodes.Leave, realInstructionAfterCall);

            _ilProcessor.InsertAfter(instructionCallEnd, tryLeaveInstruction);

            var exception = _creator.SaveThrownException();
            var exceptionHandlerCurrent = exception.InsertAfter(tryLeaveInstruction, _ilProcessor);

            var pushException = _creator.LoadValueOnStack(exception);

            exceptionHandlerCurrent = pushException.InsertAfter(exceptionHandlerCurrent, _ilProcessor);

            var setExceptionFromStack =
                _creator.SetMethodExecutionArgsExceptionFromStack(ExecutionArgs);

            exceptionHandlerCurrent = setExceptionFromStack.InsertAfter(exceptionHandlerCurrent, _ilProcessor);

            var returnAfterHandling = new InstructionBlockChain();

            if (returnValue != null)
            {
                returnAfterHandling.Add(returnValue.Load(false, false));
            }
            returnAfterHandling.Add(new InstructionBlock("Return", Instruction.Create(OpCodes.Ret)));

            var indices = allAspects
                          .Select((asp, index) => new { asp, index })
                          .Where(x => (x.asp.AspectMethods & AspectMethods.OnException) != 0)
                          .Select(x => x.index)
                          .Reverse()
                          .ToList();

            foreach (var index in indices)
            {
                var onExceptionAspect = allAspects[index];
                if (HasMultipleAspects)
                {
                    var load = _creator.LoadMethodExecutionArgsTagFromPersistable(ExecutionArgs,
                                                                                  onExceptionAspect.TagPersistable);
                    exceptionHandlerCurrent = load.InsertAfter(exceptionHandlerCurrent, _ilProcessor);
                }

                var callAspectOnException =
                    _creator.CallAspectOnException(onExceptionAspect, ExecutionArgs);
                var nop = new InstructionBlock("Nop", Instruction.Create(OpCodes.Nop));

                var callOnExitsAndReturn = new InstructionBlockChain();
                for (var i = index - 1; i >= 0; --i)
                {
                    var jthAspect = allAspects[i];
                    if ((jthAspect.AspectMethods & AspectMethods.OnExit) == 0)
                    {
                        continue;
                    }
                    if (HasMultipleAspects)
                    {
                        callOnExitsAndReturn.Add(_creator.LoadMethodExecutionArgsTagFromPersistable(ExecutionArgs, jthAspect.TagPersistable));
                    }
                    callOnExitsAndReturn.Add(_creator.CallAspectOnExit(jthAspect, ExecutionArgs));
                }

                if (returnValue != null)
                {
                    callOnExitsAndReturn.Add(_creator.ReadReturnValue(ExecutionArgs, returnValue));
                }

                callOnExitsAndReturn.Add(new InstructionBlock("Leave", Instruction.Create(OpCodes.Leave_S, returnAfterHandling.First)));

                callAspectOnException.Add(_creator.IfFlowBehaviorIsAnyOf(ExecutionArgs, nop.First, callOnExitsAndReturn, 1, 3));

                callAspectOnException.Add(nop);
                callAspectOnException.InsertAfter(exceptionHandlerCurrent, _ilProcessor);
                exceptionHandlerCurrent = callAspectOnException.Last;
            }

            var flowBehaviorHandler = new InstructionBlockChain();

            flowBehaviorHandler.Add(new InstructionBlock("throw", Instruction.Create(OpCodes.Rethrow)));
            flowBehaviorHandler.Add(new InstructionBlock("Leave", Instruction.Create(OpCodes.Leave_S, realInstructionAfterCall)));
            flowBehaviorHandler.InsertAfter(exceptionHandlerCurrent, _ilProcessor);

            returnAfterHandling.InsertAfter(flowBehaviorHandler.Last, _ilProcessor);

            _method.Body.ExceptionHandlers.Add(new ExceptionHandler(ExceptionHandlerType.Catch)
            {
                CatchType    = _creator.GetExceptionTypeReference(),
                TryStart     = instructionCallStart,
                TryEnd       = tryLeaveInstruction.Next,
                HandlerStart = tryLeaveInstruction.Next,
                HandlerEnd   = flowBehaviorHandler.Last.Next
            });
        }
Example #4
0
        protected virtual void HandleBody(
            NamedInstructionBlockChain arguments,
            VariableDefinition returnValue,
            out Instruction instructionCallStart,
            out Instruction instructionCallEnd)
        {
            VariableDefinition thisVariable = null;

            if (!_method.IsStatic)
            {
                var thisVariableBlock = _creator.CreateThisVariable(_method.DeclaringType);
                thisVariableBlock.Append(_ilProcessor);
                thisVariable = thisVariableBlock.Variable;
            }

            InstructionBlockChain callSourceMethod;

            ILoadable[] args = null;
            var         allowChangingInputArguments = _aspects.Any(x => x.Info.AllowChangingInputArguments);

            if (allowChangingInputArguments)
            {
                // get arguments from ExecutionArgs because they could have been changed in aspect code
                args = _method.Parameters
                       .Select((x, i) => new ArrayElementLoadable(arguments.Variable, i, x, _method.Body.GetILProcessor(), _creator))
                       .Cast <ILoadable>()
                       .ToArray();

                callSourceMethod = _creator.CallMethodWithReturn(
                    _clonedMethod,
                    thisVariable == null ? null : new VariablePersistable(thisVariable),
                    returnValue == null ? null : new VariablePersistable(returnValue),
                    args);
            }
            else
            {
                callSourceMethod = _creator.CallMethodWithLocalParameters(
                    _method,
                    _clonedMethod,
                    thisVariable == null ? null : new VariablePersistable(thisVariable),
                    returnValue == null ? null : new VariablePersistable(returnValue));
            }

            if (allowChangingInputArguments)
            {
                // write byref variables back for origin source method
                var copyBackInstructions = new List <Instruction>();
                foreach (var parameter in _method.Parameters.Where(x => x.ParameterType.IsByReference))
                {
                    var arg = args[parameter.Index];
                    copyBackInstructions.Add(_ilProcessor.Create(OpCodes.Ldarg, parameter));

                    var loadBlock = arg.Load(false, true);
                    copyBackInstructions.AddRange(loadBlock.Instructions);

                    var storeOpCode = parameter.ParameterType.MetadataType.GetStIndCode();
                    copyBackInstructions.Add(_ilProcessor.Create(storeOpCode));
                }

                if (copyBackInstructions.Any())
                {
                    var copyBackBlock = new InstructionBlock("Copy back ref values", copyBackInstructions);
                    callSourceMethod.Add(copyBackBlock);
                }
            }

            callSourceMethod.Append(_ilProcessor);
            instructionCallStart = callSourceMethod.First;
            instructionCallEnd   = callSourceMethod.Last;
        }
Example #5
0
        public NamedInstructionBlockChain CreateMethodExecutionArgsInstance(
            NamedInstructionBlockChain argumentsArrayChain,
            TypeReference anyAspectTypeDefinition)
        {
            // instance value
            var createThisVariableBlock = CreateThisVariable();

            // MethodExecutionArgs instance
            var onEntryMethodTypeRef =
                anyAspectTypeDefinition.Resolve().BaseType.Resolve().Methods.Single(x => x.Name == "OnEntry");
            var firstParameterType         = onEntryMethodTypeRef.Parameters.Single().ParameterType;
            var methodExecutionArgsTypeRef = _moduleDefinition.ImportReference(firstParameterType);

            var methodExecutionArgsVariable       = _creator.CreateVariable(methodExecutionArgsTypeRef);
            var newObjectMethodExecutionArgsBlock = _creator.NewObject(
                methodExecutionArgsVariable,
                methodExecutionArgsTypeRef,
                _moduleDefinition);

            InstructionBlock callSetInstanceBlock = null;

            if (!_method.IsStatic)
            {
                var methodExecutionArgsSetInstanceMethodRef =
                    _referenceFinder.GetMethodReference(methodExecutionArgsTypeRef, md => md.Name == "set_Instance");
                callSetInstanceBlock = _creator.CallVoidInstanceMethod(methodExecutionArgsSetInstanceMethodRef,
                                                                       new VariablePersistable(methodExecutionArgsVariable),
                                                                       new VariablePersistable(createThisVariableBlock.Variable));
            }

            var methodExecutionArgsSetArgumentsMethodRef =
                _referenceFinder.GetMethodReference(methodExecutionArgsTypeRef, md => md.Name == "set_Arguments");
            var callSetArgumentsBlock = _creator.CallVoidInstanceMethod(methodExecutionArgsSetArgumentsMethodRef,
                                                                        new VariablePersistable(methodExecutionArgsVariable),
                                                                        new VariablePersistable(argumentsArrayChain.Variable));

            var methodBaseTypeRef          = _referenceFinder.GetTypeReference(typeof(MethodBase));
            var methodBaseVariable         = _creator.CreateVariable(methodBaseTypeRef);
            var methodBaseGetCurrentMethod = _referenceFinder.GetMethodReference(methodBaseTypeRef,
                                                                                 md => md.Name == "GetCurrentMethod");
            var callGetCurrentMethodBlock = _creator.CallStaticMethod(methodBaseGetCurrentMethod, new VariablePersistable(methodBaseVariable));

            var methodExecutionArgsSetMethodBaseMethodRef =
                _referenceFinder.GetMethodReference(methodExecutionArgsTypeRef, md => md.Name == "set_Method");
            var callSetMethodBlock = _creator.CallVoidInstanceMethod(methodExecutionArgsSetMethodBaseMethodRef,
                                                                     new VariablePersistable(methodExecutionArgsVariable),
                                                                     new VariablePersistable(methodBaseVariable));

            var newMethodExecutionArgsBlockChain = new NamedInstructionBlockChain(methodExecutionArgsVariable,
                                                                                  methodExecutionArgsTypeRef);

            newMethodExecutionArgsBlockChain.Add(newObjectMethodExecutionArgsBlock);
            newMethodExecutionArgsBlockChain.Add(callSetArgumentsBlock);
            newMethodExecutionArgsBlockChain.Add(callGetCurrentMethodBlock);
            newMethodExecutionArgsBlockChain.Add(callSetMethodBlock);
            if (callSetInstanceBlock != null)
            {
                newMethodExecutionArgsBlockChain.Add(createThisVariableBlock);
                newMethodExecutionArgsBlockChain.Add(callSetInstanceBlock);
            }

            return(newMethodExecutionArgsBlockChain);
        }
        private static List <Instruction> CreateMethodCallInstructions(
            MethodReference methodReference,
            ILoadable instance,
            IPersistable returnValue,
            params ILoadable[] arguments)
        {
            InstructionBlock loadVariableInstruction = null;

            if (instance != null)
            {
                loadVariableInstruction = instance.Load(true, false);
            }

            var loadArgumentsInstructions = new List <Instruction>();
            var parameterCount            = 0;

            foreach (var argument in arguments)
            {
                var paramIsByRef = methodReference.Parameters[parameterCount].ParameterType.IsByReference;

                loadArgumentsInstructions.AddRange(argument.Load(false, false).Instructions);
                var varType = argument.PersistedType;
                if (varType.IsByReference && !paramIsByRef)
                {
                    varType = ((ByReferenceType)varType).ElementType;
                    loadArgumentsInstructions.Add(Instruction.Create(OpCodes.Ldobj, varType));
                }

                var parameter = methodReference.Parameters[parameterCount];
                if (parameter.ParameterType.FullName != varType.FullName)
                {
                    if (varType.IsValueType || varType.IsGenericParameter)
                    {
                        loadArgumentsInstructions.Add(Instruction.Create(OpCodes.Box, varType));
                    }
                }
                parameterCount++;
            }

            var methodDefinition      = methodReference.Resolve();
            var methodCallInstruction = Instruction.Create(
                methodDefinition.IsVirtual
                    ? OpCodes.Callvirt
                    : OpCodes.Call,
                methodReference);

            var methodReturnsVoid         = IsVoid(methodDefinition.ReturnType);
            var returnValueShouldBeStored = (returnValue != null);

            List <Instruction> HandleReturnValue(List <Instruction> methodWork)
            {
                if (methodReturnsVoid && returnValueShouldBeStored)
                {
                    throw new InvalidOperationException("Method has no return value");
                }
                if (!methodReturnsVoid && !returnValueShouldBeStored)
                {
                    methodWork.Add(Instruction.Create(OpCodes.Pop));
                    return(methodWork);
                }
                if (methodReturnsVoid && !returnValueShouldBeStored)
                {
                    return(methodWork);
                }
                // Therefore, !methodReturnsVoid && returnValueShouldBeStored

                var castToType   = returnValue.PersistedType;
                var castFromType = methodDefinition.ReturnType;

                if (castToType.FullName != castFromType.FullName)
                {
                    if (castToType.IsByReference)
                    {
                        castToType = ((ByReferenceType)castToType).ElementType;
                    }

                    if (castFromType.IsByReference)
                    {
                        castFromType = ((ByReferenceType)castFromType).ElementType;
                    }
                    methodWork.AddRange(CastValueCurrentlyOnStack(castFromType, castToType));
                }
                return(returnValue.Store(new InstructionBlock("", methodWork), castToType).Instructions.ToList());
            }

            var instructions = new List <Instruction>();

            if (loadVariableInstruction != null)
            {
                instructions.AddRange(loadVariableInstruction.Instructions);
            }
            instructions.AddRange(loadArgumentsInstructions);
            instructions.Add(methodCallInstruction);
            return(HandleReturnValue(instructions));
        }
 public void Add(InstructionBlock block)
 {
     InstructionBlocks.Add(block);
 }
Example #8
0
 InstructionBlock IPersistable.Store(InstructionBlock loadNewValueOntoStack, TypeReference typeOnStack) => Persistable.Store(loadNewValueOntoStack, typeOnStack);
        public NamedInstructionBlockChain CreateMethodExecutionArgsInstance(NamedInstructionBlockChain argumentsArrayChain, TypeReference weavingType)
        {
            // instance value
            var objectType              = _referenceFinder.GetTypeReference(typeof(object));
            var instanceVariable        = _creator.CreateVariable(objectType);
            var createThisVariableBlock = _creator.CreateThisVariable(instanceVariable, objectType);

            // MethodExecutionArgs instance
            var onEntryMethodTypeRef =
                _aspectTypeDefinition.Resolve().BaseType.Resolve().Methods.Single(x => x.Name == "OnEntry");
            var firstParameterType                = onEntryMethodTypeRef.Parameters.Single().ParameterType;
            var methodExecutionArgsTypeRef        = _moduleDefinition.ImportReference(firstParameterType);
            var methodExecutionArgsVariable       = _creator.CreateVariable(methodExecutionArgsTypeRef);
            var newObjectMethodExecutionArgsBlock = _creator.NewObject(
                methodExecutionArgsVariable,
                methodExecutionArgsTypeRef,
                _moduleDefinition,
                _aspectCounter);

            InstructionBlock callSetInstanceBlock = null;

            if (!_method.IsStatic)
            {
                var methodExecutionArgsSetInstanceMethodRef =
                    _referenceFinder.GetMethodReference(methodExecutionArgsTypeRef, md => md.Name == "set_Instance");
                callSetInstanceBlock = _creator.CallVoidInstanceMethod(methodExecutionArgsVariable,
                                                                       methodExecutionArgsSetInstanceMethodRef, instanceVariable);
            }

            var methodExecutionArgsSetArgumentsMethodRef =
                _referenceFinder.GetMethodReference(methodExecutionArgsTypeRef, md => md.Name == "set_Arguments");
            var callSetArgumentsBlock = _creator.CallVoidInstanceMethod(methodExecutionArgsVariable,
                                                                        methodExecutionArgsSetArgumentsMethodRef, argumentsArrayChain.Variable);

            var methodInfoField    = _creator.StoreMethodInfoInStaticField(_method, weavingType);
            var methodBaseVariable = _creator.CreateVariable(_referenceFinder.GetTypeReference(typeof(MethodInfo)));

            var callGetCurrentMethodBlock = new InstructionBlock("CallGetCurrentMethod: ",
                                                                 Instruction.Create(OpCodes.Ldsfld, methodInfoField),
                                                                 Instruction.Create(OpCodes.Stloc, methodBaseVariable));

            var methodExecutionArgsSetMethodBaseMethodRef =
                _referenceFinder.GetMethodReference(methodExecutionArgsTypeRef, md => md.Name == "set_Method");
            var callSetMethodBlock = _creator.CallVoidInstanceMethod(methodExecutionArgsVariable,
                                                                     methodExecutionArgsSetMethodBaseMethodRef, methodBaseVariable);

            var newMethodExectionArgsBlockChain = new NamedInstructionBlockChain(methodExecutionArgsVariable,
                                                                                 methodExecutionArgsTypeRef);

            newMethodExectionArgsBlockChain.Add(newObjectMethodExecutionArgsBlock);
            newMethodExectionArgsBlockChain.Add(callSetArgumentsBlock);
            newMethodExectionArgsBlockChain.Add(callGetCurrentMethodBlock);
            newMethodExectionArgsBlockChain.Add(callSetMethodBlock);
            if (callSetInstanceBlock != null)
            {
                newMethodExectionArgsBlockChain.Add(createThisVariableBlock);
                newMethodExectionArgsBlockChain.Add(callSetInstanceBlock);
            }

            return(newMethodExectionArgsBlockChain);
        }