コード例 #1
0
        public void AddOnExceptionCall(
            NamedInstructionBlockChain createAspectInstance,
            InstructionBlockChain callAspectOnException,
            NamedInstructionBlockChain setMethodExecutionArgsExceptionFromStack)
        {
            // add leave
            _markLeaveTryBlock = _processor.Create(OpCodes.Leave, _markEnd2BeforeOnExitCall);
            _processor.InsertBefore(_markEnd2BeforeOnExitCall, _markLeaveTryBlock);

            // add catch handler after leave
            _markExceptionHandlerStart = _processor.Create(OpCodes.Nop);
            _processor.InsertAfter(_markLeaveTryBlock, _markExceptionHandlerStart);
            var current = setMethodExecutionArgsExceptionFromStack.InsertAfter(_markExceptionHandlerStart, _processor);

            current = AddCreateAspectInstance(createAspectInstance, current);
            current = callAspectOnException.InsertAfter(current, _processor);
            _markExceptionHandlerEnd = _processor.Create(OpCodes.Rethrow);
            _processor.InsertAfter(current, _markExceptionHandlerEnd);

            // add exception handler
            _methodBody.ExceptionHandlers.Add(new ExceptionHandler(ExceptionHandlerType.Catch)
            {
                CatchType    = setMethodExecutionArgsExceptionFromStack.TypeReference,
                TryStart     = _markStart4BeforeRealBodyStartExceptionHandler,
                TryEnd       = _markExceptionHandlerStart,
                HandlerStart = _markExceptionHandlerStart,
                HandlerEnd   = _markExceptionHandlerEnd.Next
            });
        }
コード例 #2
0
        public void FixThrowAtEndOfRealBody(
            NamedInstructionBlockChain saveThrownException,
            NamedInstructionBlockChain loadThrownException,
            NamedInstructionBlockChain loadThrownException2)
        {
            // store exception from stack
            var retTemp = _processor.Create(OpCodes.Nop);

            _processor.InsertBefore(_realBodyEnd, retTemp);
            var lastInstruction = saveThrownException.InsertAfter(retTemp, _processor);

            // load exception to stack
            loadThrownException.InsertAfter(lastInstruction, _processor);

            // exception will be thrown at old real body end (maybe in try/catch)

            // after "OnException" load exception again to stack
            var retTemp2 = _processor.Create(OpCodes.Nop);

            _processor.Replace(_markRetNew, retTemp2);
            lastInstruction = loadThrownException2.InsertAfter(retTemp2, _processor);

            // then throw again
            _processor.InsertAfter(lastInstruction, _processor.Create(OpCodes.Throw));
        }
        public NamedInstructionBlockChain CreateMethodExecutionArgsInstance(NamedInstructionBlockChain argumentsArrayChain)
        {
            // instance value
            var instanceVariable        = _creator.CreateVariable(_method.DeclaringType);
            var createThisVariableBlock = _creator.CreateThisVariable(instanceVariable, _method.DeclaringType);

            // 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 methodBaseTypeRef          = _referenceFinder.GetTypeReference(typeof(MethodBase));
            var methodBaseVariable         = _creator.CreateVariable(methodBaseTypeRef);
            var methodBaseGetCurrentMethod = _referenceFinder.GetMethodReference(methodBaseTypeRef,
                                                                                 md => md.Name == "GetCurrentMethod");
            var callGetCurrentMethodBlock = _creator.CallStaticMethod(methodBaseGetCurrentMethod, 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);
        }
コード例 #4
0
        public void AddOnEntryCall(
            NamedInstructionBlockChain createAspectInstance,
            InstructionBlockChain callAspectOnEntry)
        {
            var current = AddCreateAspectInstance(createAspectInstance, _markStart3BeforeOnEntryCall);

            callAspectOnEntry.InsertAfter(current, _processor);
        }
        public NamedInstructionBlockChain CreateMethodExecutionArgsInstance(NamedInstructionBlockChain argumentsArrayChain)
        {
            // instance value
            var instanceVariable = _creator.CreateVariable(CreateVariableName("this"), _method.DeclaringType);
            var createThisVariableBlock = _creator.CreateThisVariable(instanceVariable, _method.DeclaringType);
            
            // MethodExecutionArgs instance
            var onEntryMethodTypeRef =
                _aspectTypeDefinition.Resolve().BaseType.Resolve().Methods.Single(x => x.Name == "OnEntry");
            var firstParameterType = onEntryMethodTypeRef.Parameters.Single().ParameterType;
            var methodExecutionArgsTypeRef = _moduleDefinition.Import(firstParameterType);
            var methodExecutionArgsVariable = _creator.CreateVariable(CreateVariableName("methodExecutionArgs"),
                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 methodBaseTypeRef = _referenceFinder.GetTypeReference(typeof (MethodBase));
            var methodBaseVariable = _creator.CreateVariable(CreateVariableName("methodBase"), methodBaseTypeRef);
            var methodBaseGetCurrentMethod = _referenceFinder.GetMethodReference(methodBaseTypeRef,
                md => md.Name == "GetCurrentMethod");
            var callGetCurrentMethodBlock = _creator.CallStaticMethod(methodBaseGetCurrentMethod, 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;
        }
コード例 #6
0
        protected virtual void WeaveMethodExecutionArgs(NamedInstructionBlockChain arguments)
        {
            var executionArgs = _creator.CreateMethodExecutionArgsInstance(
                arguments,
                _aspects[0].Info.AspectAttribute.AttributeType);

            AddToSetup(executionArgs);
            ExecutionArgs = executionArgs;
        }
コード例 #7
0
        private void HandleReturnValue(bool hasReturnValue, NamedInstructionBlockChain returnValue)
        {
            if (hasReturnValue)
            {
                AddToEnd(_creator.LoadValueOnStack(returnValue));
            }

            AddToEnd(_creator.CreateReturn());
        }
        public NamedInstructionBlockChain SaveReturnValue()
        {
            var returnValueVariable = _creator.CreateVariable(_method.ReturnType);
            var block = new NamedInstructionBlockChain(returnValueVariable, _method.ReturnType);

            var instructions = _creator.SaveReturnValueFromStack(returnValueVariable);

            block.Add(instructions);
            return(block);
        }
コード例 #9
0
        public void AddOnExitCall(
            NamedInstructionBlockChain createAspectInstance,
            InstructionBlockChain callAspectOnExit,
            InstructionBlockChain setMethodExecutionArgsReturnValue)
        {
            var current = setMethodExecutionArgsReturnValue.InsertAfter(_markEnd2BeforeOnExitCall, _processor);

            current = AddCreateAspectInstance(createAspectInstance, current);
            callAspectOnExit.InsertAfter(current, _processor);
        }
コード例 #10
0
        public NamedInstructionBlockChain LoadAspectInstance(CustomAttribute aspect, TypeReference type)
        {
            var caching = aspect.AttributeType.Resolve().CustomAttributes.FirstOrDefault(a => a.AttributeType.FullName == typeof(AspectCachingAttribute).FullName);

            Caching cachingLevel = Caching.None;

            if (caching != null)
            {
                cachingLevel = (Caching)caching.ConstructorArguments.First().Value;
            }

            var aspectTypeReference = _moduleDefinition.ImportReference(_aspectTypeDefinition);
            var aspectVariable      = _creator.CreateVariable(aspectTypeReference);

            if (cachingLevel == Caching.StaticByMethod)
            {
                var typeDef = type.Resolve();
                int i;
                string nameFactory(int index) => $"<{_method.Name}>k_aspectField_{index}";
                bool isNameTaken(int index) => typeDef.Fields.FirstOrDefault(f => f.Name == nameFactory(index)) != null;

                for (i = 1; isNameTaken(i); ++i)
                {
                }

                var field      = new FieldDefinition(nameFactory(i), Mono.Cecil.FieldAttributes.Static | Mono.Cecil.FieldAttributes.Private, aspectTypeReference);
                var staticCtor = _creator.EnsureStaticConstructor(typeDef);
                var processor  = staticCtor.Body.GetILProcessor();
                var first      = staticCtor.Body.Instructions.First();

                var creator = new InstructionBlockCreator(staticCtor, _referenceFinder);
                var aspectStaticVariable = creator.CreateVariable(aspectTypeReference);
                var newObjectAspectBlock = creator.NewObject(aspectStaticVariable, aspectTypeReference, _moduleDefinition, aspect, _aspectCounter);
                foreach (var inst in newObjectAspectBlock.Instructions)
                {
                    processor.InsertBefore(first, inst);
                }
                processor.InsertBefore(first, processor.Create(OpCodes.Ldloc, aspectStaticVariable));
                processor.InsertBefore(first, processor.Create(OpCodes.Stsfld, field));
                var loadAspectFieldBlockChain = new NamedInstructionBlockChain(aspectVariable, aspectTypeReference);
                loadAspectFieldBlockChain.Add(new InstructionBlock("LoadAspectField: ",
                                                                   Instruction.Create(OpCodes.Ldsfld, field),
                                                                   Instruction.Create(OpCodes.Stloc, aspectVariable)));
                type.Resolve().Fields.Add(field);
                return(loadAspectFieldBlockChain);
            }
            else
            {
                var newObjectAspectBlock = _creator.NewObject(aspectVariable,
                                                              aspectTypeReference, _moduleDefinition, aspect, _aspectCounter);
                var newObjectAspectBlockChain = new NamedInstructionBlockChain(aspectVariable, aspectTypeReference);
                newObjectAspectBlockChain.Add(newObjectAspectBlock);
                return(newObjectAspectBlockChain);
            }
        }
        public NamedInstructionBlockChain CreateThisVariable(TypeReference typeReference)
        {
            typeReference = FixTypeReference(typeReference);

            var instanceVariable = _creator.CreateVariable(typeReference);
            var block            = _creator.CreateThisVariable(instanceVariable, typeReference);
            var result           = new NamedInstructionBlockChain(instanceVariable, typeReference);

            result.InstructionBlocks.Add(block);
            return(result);
        }
コード例 #12
0
        public NamedInstructionBlockChain CreateAndNewUpAspect(CustomAttribute aspect)
        {
            var aspectTypeReference  = _moduleDefinition.ImportReference(aspect.AttributeType);
            var aspectLocal          = _creator.CreateVariable(aspectTypeReference);
            var newObjectAspectBlock = _creator.NewObject(aspectLocal, aspectTypeReference, _moduleDefinition, aspect);

            var newObjectAspectBlockChain = new NamedInstructionBlockChain(aspectLocal, aspectTypeReference);

            newObjectAspectBlockChain.Add(newObjectAspectBlock);
            return(newObjectAspectBlockChain);
        }
        public NamedInstructionBlockChain CreateAspectInstance(CustomAttribute aspect)
        {
            var aspectTypeReference  = _moduleDefinition.ImportReference(_aspectTypeDefinition);
            var aspectVariable       = _creator.CreateVariable(aspectTypeReference);
            var newObjectAspectBlock = _creator.NewObject(aspectVariable, aspectTypeReference, _moduleDefinition, aspect, _aspectCounter);

            var newObjectAspectBlockChain = new NamedInstructionBlockChain(aspectVariable, aspectTypeReference);

            newObjectAspectBlockChain.Add(newObjectAspectBlock);
            return(newObjectAspectBlockChain);
        }
コード例 #14
0
        private Instruction AddCreateAspectInstance(NamedInstructionBlockChain createAspectInstance, Instruction current)
        {
            if (_aspectInstanceCreated)
            {
                return(current);
            }

            current = createAspectInstance.InsertAfter(current, _processor);
            _aspectInstanceCreated = true;
            return(current);
        }
コード例 #15
0
        public NamedInstructionBlockChain SaveThrownException()
        {
            var exceptionTypeRef  = _referenceFinder.GetTypeReference(typeof(Exception));
            var exceptionVariable = _creator.CreateVariable(exceptionTypeRef);
            var block             = new NamedInstructionBlockChain(exceptionVariable, exceptionTypeRef);

            var instructions = _creator.AssignValueFromStack(exceptionVariable);

            block.Add(instructions);
            return(block);
        }
        public InstructionBlockChain CallAspectOnException(NamedInstructionBlockChain createAspectInstance,
                                                           NamedInstructionBlockChain newMethodExectionArgsBlockChain)
        {
            var onExceptionMethodRef = _referenceFinder.GetMethodReference(createAspectInstance.TypeReference,
                                                                           md => md.Name == "OnException");
            var callOnExceptionBlock = _creator.CallVoidInstanceMethod(onExceptionMethodRef,
                                                                       createAspectInstance.Variable, newMethodExectionArgsBlockChain.Variable);

            var callAspectOnExceptionBlockChain = new InstructionBlockChain();

            callAspectOnExceptionBlockChain.Add(callOnExceptionBlock);
            return(callAspectOnExceptionBlockChain);
        }
        public InstructionBlockChain SetMethodExecutionArgsReturnValue(
            NamedInstructionBlockChain newMethodExectionArgsBlockChain, NamedInstructionBlockChain loadReturnValue)
        {
            var methodExecutionArgsSetReturnValueMethodRef =
                _referenceFinder.GetMethodReference(newMethodExectionArgsBlockChain.TypeReference,
                                                    md => md.Name == "set_ReturnValue");
            var callSetReturnValueBlock = _creator.CallVoidInstanceMethod(methodExecutionArgsSetReturnValueMethodRef, newMethodExectionArgsBlockChain.Variable, loadReturnValue.Variable);

            var block = new InstructionBlockChain();

            block.Add(callSetReturnValueBlock);
            return(block);
        }
コード例 #18
0
        public void AddOnEntryCall(
            NamedInstructionBlockChain createAspectInstance,
            InstructionBlockChain callAspectOnEntry,
            InstructionBlockChain getSkipVar,
            NamedInstructionBlockChain conditionalExecutionInstance)
        {
            var current = AddCreateAspectInstance(createAspectInstance, _markStart3BeforeOnEntryCall);

            current = callAspectOnEntry.InsertAfter(current, _processor);
            current = getSkipVar.InsertAfter(current, _processor);
            current = conditionalExecutionInstance.InsertAfter(current, _processor);
            _processor.InsertAfter(current, _processor.Create(OpCodes.Brfalse, _markEnd2BeforeOnExitCall));
        }
コード例 #19
0
        public NamedInstructionBlockChain LoadValueOnStack(NamedInstructionBlockChain instructionBlock)
        {
            var block = new NamedInstructionBlockChain(instructionBlock.Variable, instructionBlock.TypeReference);

            if (instructionBlock.Variable == null)
            {
                return(block);
            }

            var loadReturnValueBlock = _creator.PushValueOnStack(instructionBlock.Variable);

            block.Add(loadReturnValueBlock);
            return(block);
        }
コード例 #20
0
        public NamedInstructionBlockChain CreateMethodArgumentsArray()
        {
            //  argument values
            var argumentsTypeReference = _referenceFinder.GetTypeReference(typeof(object[]));
            var argumentsArrayVariable = _creator.CreateVariable(argumentsTypeReference);
            var createObjectArrayWithMethodArgumentsBlock =
                _creator.CreateObjectArrayWithMethodArguments(argumentsArrayVariable,
                                                              _referenceFinder.GetTypeReference(typeof(object)));

            var blockChain = new NamedInstructionBlockChain(argumentsArrayVariable, argumentsTypeReference);

            blockChain.Add(createObjectArrayWithMethodArgumentsBlock);
            return(blockChain);
        }
コード例 #21
0
        public InstructionBlockChain LoadExecuteBodyVariable(NamedInstructionBlockChain newMethodExecutionArgsBlockChain, out NamedInstructionBlockChain executeBodyVariable)
        {
            var getExecuteBody = _referenceFinder.GetMethodReference(newMethodExecutionArgsBlockChain.TypeReference,
                                                                     md => md.Name == "get_ExecuteBody");

            var executeBodyVar = _creator.CreateVariable(getExecuteBody.ReturnType);

            executeBodyVariable = new NamedInstructionBlockChain(executeBodyVar, getExecuteBody.ReturnType);
            var block = _creator.CallInstanceMethod(newMethodExecutionArgsBlockChain.Variable, executeBodyVariable.Variable, getExecuteBody);

            var getExecuteBodyBlockChain = new InstructionBlockChain();

            getExecuteBodyBlockChain.Add(block);
            return(getExecuteBodyBlockChain);
        }
コード例 #22
0
        public InstructionBlockChain CallAspectOnEntry(NamedInstructionBlockChain createAspectInstance,
                                                       NamedInstructionBlockChain newMethodExectionArgsBlockChain)
        {
            var onEntryMethodRef = _referenceFinder.GetMethodReference(createAspectInstance.TypeReference,
                                                                       md => md.Name == "OnEntry");
            var callOnEntryBlock = _creator.CallVoidInstanceMethod(createAspectInstance.Variable, onEntryMethodRef,
                                                                   newMethodExectionArgsBlockChain.Variable);
            var readParameterBlock = _creator.ReadParameterArray(newMethodExectionArgsBlockChain.Variable);

            var callAspectOnEntryBlockChain = new InstructionBlockChain();

            callAspectOnEntryBlockChain.Add(callOnEntryBlock);
            callAspectOnEntryBlockChain.Add(readParameterBlock);
            return(callAspectOnEntryBlockChain);
        }
        public NamedInstructionBlockChain CreateMethodArgumentsArray()
        {
            //  argument values
            var argumentsTypeReference = _referenceFinder.GetTypeReference(typeof (object[]));
            var argumentsArrayVariable = _creator.CreateVariable(CreateVariableName("arguments"),
                argumentsTypeReference);
            var createObjectArrayWithMethodArgumentsBlock =
                _creator.CreateObjectArrayWithMethodArguments(argumentsArrayVariable,
                    _referenceFinder.GetTypeReference(typeof (object)));

            var blockChain = new NamedInstructionBlockChain(argumentsArrayVariable,
                argumentsTypeReference);
            blockChain.Add(createObjectArrayWithMethodArgumentsBlock);
            return blockChain;
        }
        public NamedInstructionBlockChain LoadMethodExecutionArgsTagFromVariable(
            NamedInstructionBlockChain createMethodExecutionArgsInstance,
            VariableDefinition value)
        {
            var objectTypeRef = _referenceFinder.GetTypeReference(typeof(object));

            var setMethod =
                _referenceFinder.GetMethodReference(createMethodExecutionArgsInstance.TypeReference,
                                                    md => md.Name == "set_MethodExecutionTag");
            var call = _creator.CallVoidInstanceMethod(setMethod, createMethodExecutionArgsInstance.Variable, value);

            var block = new NamedInstructionBlockChain(value, objectTypeRef);

            block.Add(call);
            return(block);
        }
コード例 #25
0
        protected override void WeaveMethodExecutionArgs(NamedInstructionBlockChain arguments)
        {
            var executionArgs = _creator.CreateMethodExecutionArgsInstance(
                arguments,
                _aspects[0].Info.AspectAttribute.AttributeType);

            _executionArgsField = _module.ImportReference(_stateMachine.AddPublicInstanceField(executionArgs.Variable.VariableType));
            executionArgs.Add(new InstructionBlock("", Instruction.Create(OpCodes.Ldloc, executionArgs.Variable)));

            var field        = new FieldPersistable(new VariablePersistable(_stateMachineLocal), _executionArgsField);
            var instructions = field.Store(executionArgs.Flatten(), _module.ImportReference(typeof(void)));

            var chain = new InstructionBlockChain();

            chain.Add(instructions);
            AddToSetup(chain);
            ExecutionArgs = field;
        }
        public NamedInstructionBlockChain SetMethodExecutionArgsExceptionFromStack(
            NamedInstructionBlockChain createMethodExecutionArgsInstance)
        {
            var exceptionTypeRef        = _referenceFinder.GetTypeReference(typeof(Exception));
            var exceptionVariable       = _creator.CreateVariable(exceptionTypeRef);
            var assignExceptionVariable = _creator.AssignValueFromStack(exceptionVariable);

            var methodExecutionArgsSetExceptionMethodRef =
                _referenceFinder.GetMethodReference(createMethodExecutionArgsInstance.TypeReference,
                                                    md => md.Name == "set_Exception");
            var callSetExceptionBlock = _creator.CallVoidInstanceMethod(methodExecutionArgsSetExceptionMethodRef, createMethodExecutionArgsInstance.Variable, exceptionVariable);

            var block = new NamedInstructionBlockChain(exceptionVariable, exceptionTypeRef);

            block.Add(assignExceptionVariable);
            block.Add(callSetExceptionBlock);
            return(block);
        }
コード例 #27
0
        public InstructionBlockChain ReadReturnValue(NamedInstructionBlockChain newMethodExecutionArgsBlockChain,
                                                     NamedInstructionBlockChain returnValue)
        {
            if (!_creator.HasReturnValue())
            {
                return(new InstructionBlockChain());
            }

            // VariableDefinition, VariableDefinition, MethodDefinition
            var getReturnValue =
                _referenceFinder.GetMethodReference(newMethodExecutionArgsBlockChain.TypeReference,
                                                    md => md.Name == "get_ReturnValue");

            var readValueBlock = _creator.CallInstanceMethod(newMethodExecutionArgsBlockChain.Variable, returnValue.Variable, getReturnValue);

            var readValueBlockChain = new InstructionBlockChain();

            readValueBlockChain.Add(readValueBlock);
            return(readValueBlockChain);
        }
コード例 #28
0
        public void Unify(
            NamedInstructionBlockChain saveReturnValue, NamedInstructionBlockChain loadReturnValue)
        {
            _methodBody.InitLocals = true;

            _processor.InsertBefore(_realBodyStart, _markStart4BeforeRealBodyStartExceptionHandler);
            _processor.InsertBefore(_markStart4BeforeRealBodyStartExceptionHandler, _markStart3BeforeOnEntryCall);
            _processor.InsertBefore(_markStart3BeforeOnEntryCall, _markStart2BeforeCreateMethodExecutionArgs);
            _processor.InsertBefore(_markStart2BeforeCreateMethodExecutionArgs, _markStart1BeforeCreateArgumentsArray);
            _processor.InsertAfter(_realBodyEnd, _markEnd1NewRealBodyEnd);
            _processor.InsertAfter(_markEnd1NewRealBodyEnd, _markEnd2BeforeOnExitCall);
            _processor.InsertAfter(_markEnd2BeforeOnExitCall, _markRetNew);

            if (!EndsWithThrow)
            {
                saveReturnValue.InsertAfter(_markEnd1NewRealBodyEnd, _processor);
                loadReturnValue.InsertAfter(_markEnd2BeforeOnExitCall, _processor);
            }

            FixRealRetsToBranchToNewRealBodyEnd();
            FixCatchHandlersWithNullEnd();
        }
コード例 #29
0
        private Instruction WeaveOnExit(bool hasReturnValue, NamedInstructionBlockChain returnValue)
        {
            var onExitAspects = _aspects
                                .Where(x => x.AspectMethods.HasFlag(AspectMethods.OnExit))
                                .Reverse()
                                .ToList();

            Instruction instructionAfterCall = null;

            if (hasReturnValue && onExitAspects.Any())
            {
                var loadReturnValue = _creator.LoadValueOnStack(returnValue);

                var setMethodExecutionArgsReturnValue = _creator.SetMethodExecutionArgsReturnValue(
                    ExecutionArgs,
                    loadReturnValue);
                AddToEnd(setMethodExecutionArgsReturnValue);

                instructionAfterCall = setMethodExecutionArgsReturnValue.First;
            }

            foreach (var aspect in onExitAspects)
            {
                if (HasMultipleAspects)
                {
                    AddToEnd(_creator.LoadMethodExecutionArgsTagFromPersistable(ExecutionArgs, aspect.TagPersistable));
                }

                AddToEnd(_creator.CallAspectOnExit(aspect, ExecutionArgs));
            }

            if (hasReturnValue && onExitAspects.Any())
            {
                _creator.ReadReturnValue(ExecutionArgs, returnValue).Append(_ilProcessor);
            }

            return(instructionAfterCall);
        }
コード例 #30
0
        protected override void HandleBody(
            NamedInstructionBlockChain arguments,
            VariableDefinition returnValue,
            out Instruction instructionCallStart,
            out Instruction instructionCallEnd)
        {
            instructionCallEnd = _ilProcessor.Body.Instructions.Last();
            if (instructionCallEnd.OpCode == OpCodes.Ret)
            {
                _ilProcessor.Remove(_ilProcessor.Body.Instructions.Last());

                if (returnValue != null)
                {
                    _ilProcessor.Append(Instruction.Create(OpCodes.Stloc, returnValue));
                }
            }
            else
            {
                Debug.Assert(false, "There should always be an unweaved portion of an async method.");
            }

            instructionCallStart = _ilProcessor.Body.Instructions.First();
            instructionCallEnd   = _ilProcessor.Body.Instructions.Last();
        }
コード例 #31
0
 public void AddOnEntryCall(
     NamedInstructionBlockChain createAspectInstance,
     InstructionBlockChain callAspectOnEntry)
 {
     var current = AddCreateAspectInstance(createAspectInstance, _markStart3BeforeOnEntryCall);
     callAspectOnEntry.InsertAfter(current, _processor);
 }
コード例 #32
0
 public void AddOnExitCall(
     NamedInstructionBlockChain createAspectInstance,
     InstructionBlockChain callAspectOnExit,
     InstructionBlockChain setMethodExecutionArgsReturnValue)
 {
     var current = setMethodExecutionArgsReturnValue.InsertAfter(_markEnd2BeforeOnExitCall, _processor);
     current = AddCreateAspectInstance(createAspectInstance, current);
     callAspectOnExit.InsertAfter(current, _processor);
 }
        public InstructionBlockChain CallAspectOnException(NamedInstructionBlockChain createAspectInstance,
            NamedInstructionBlockChain newMethodExectionArgsBlockChain)
        {
            var onExceptionMethodRef = _referenceFinder.GetMethodReference(createAspectInstance.TypeReference,
                md => md.Name == "OnException");
            var callOnExceptionBlock = _creator.CallVoidInstanceMethod(createAspectInstance.Variable,
                onExceptionMethodRef,
                newMethodExectionArgsBlockChain.Variable);

            var callAspectOnExceptionBlockChain = new InstructionBlockChain();
            callAspectOnExceptionBlockChain.Add(callOnExceptionBlock);
            return callAspectOnExceptionBlockChain;
        }
        public NamedInstructionBlockChain SaveThrownException()
        {
            var exceptionTypeRef = _referenceFinder.GetTypeReference(typeof(Exception));

            if (!_creator.HasThrowAsReturn())
                return new NamedInstructionBlockChain(null, exceptionTypeRef);

            var exceptionVariable = _creator.CreateVariable(CreateVariableName("thrownException"), exceptionTypeRef);
            var block = new NamedInstructionBlockChain(exceptionVariable, exceptionTypeRef);

            var instructions = _creator.AssignValueFromStack(exceptionVariable);
            block.Add(instructions);
            return block;
        }
        public NamedInstructionBlockChain SaveReturnValue()
        {
            if (!_creator.HasReturnValue())
                return new NamedInstructionBlockChain(null, _method.ReturnType);

            var returnValueVariable = _creator.CreateVariable(CreateVariableName("returnValue"), _method.ReturnType);
            var block = new NamedInstructionBlockChain(returnValueVariable, _method.ReturnType);

            var instructions = _creator.SaveReturnValueFromStack(returnValueVariable);
            block.Add(instructions);
            return block;
        } 
コード例 #36
0
 public void AddCreateMethodExecutionArgs(NamedInstructionBlockChain createMethodExecutionArgsInstance)
 {
     createMethodExecutionArgsInstance.InsertAfter(_markStart2BeforeCreateMethodExecutionArgs, _processor);
 }
        public InstructionBlockChain SetMethodExecutionArgsReturnValue(
            NamedInstructionBlockChain newMethodExectionArgsBlockChain, NamedInstructionBlockChain loadReturnValue)
        {
            if (!_creator.HasReturnValue())
                return new InstructionBlockChain();

            var methodExecutionArgsSetReturnValueMethodRef =
                _referenceFinder.GetMethodReference(newMethodExectionArgsBlockChain.TypeReference,
                    md => md.Name == "set_ReturnValue");
            var callSetReturnValueBlock = _creator.CallVoidInstanceMethod(newMethodExectionArgsBlockChain.Variable,
                methodExecutionArgsSetReturnValueMethodRef, loadReturnValue.Variable);

            var block = new InstructionBlockChain();
            block.Add(callSetReturnValueBlock);
            return block;
        }
        public NamedInstructionBlockChain CreateAspectInstance(CustomAttribute aspect)
        {
            var aspectTypeReference = _moduleDefinition.Import(_aspectTypeDefinition);
            var aspectVariable = _creator.CreateVariable(CreateVariableName("aspect"), aspectTypeReference);
            var newObjectAspectBlock = _creator.NewObject(aspectVariable, aspectTypeReference, _moduleDefinition, aspect, _aspectCounter);

            var newObjectAspectBlockChain = new NamedInstructionBlockChain(aspectVariable, aspectTypeReference);
            newObjectAspectBlockChain.Add(newObjectAspectBlock);
            return newObjectAspectBlockChain;
        }
コード例 #39
0
        public void AddOnExceptionCall(
            NamedInstructionBlockChain createAspectInstance,
            InstructionBlockChain callAspectOnException,
            NamedInstructionBlockChain setMethodExecutionArgsExceptionFromStack)
        {
            // add leave
            _markLeaveTryBlock = _processor.Create(OpCodes.Leave, _markEnd2BeforeOnExitCall);
            _processor.InsertBefore(_markEnd2BeforeOnExitCall, _markLeaveTryBlock);

            // add catch handler after leave
            _markExceptionHandlerStart = _processor.Create(OpCodes.Nop);
            _processor.InsertAfter(_markLeaveTryBlock, _markExceptionHandlerStart);
            var current = setMethodExecutionArgsExceptionFromStack.InsertAfter(_markExceptionHandlerStart, _processor);
            current = AddCreateAspectInstance(createAspectInstance, current);
            current = callAspectOnException.InsertAfter(current, _processor);
            _markExceptionHandlerEnd = _processor.Create(OpCodes.Rethrow);
            _processor.InsertAfter(current, _markExceptionHandlerEnd);

            // add exception handler
            _methodBody.ExceptionHandlers.Add(new ExceptionHandler(ExceptionHandlerType.Catch)
            {
                CatchType = setMethodExecutionArgsExceptionFromStack.TypeReference,
                TryStart = _markStart4BeforeRealBodyStartExceptionHandler,
                TryEnd = _markExceptionHandlerStart,
                HandlerStart = _markExceptionHandlerStart,
                HandlerEnd = _markExceptionHandlerEnd.Next
            });
        }
コード例 #40
0
        private Instruction AddCreateAspectInstance(NamedInstructionBlockChain createAspectInstance, Instruction current)
        {
            if (_aspectInstanceCreated)
                return current;

            current = createAspectInstance.InsertAfter(current, _processor);
            _aspectInstanceCreated = true;
            return current;
        }
コード例 #41
0
        public void Unify(
            NamedInstructionBlockChain saveReturnValue,NamedInstructionBlockChain loadReturnValue)
        {
            _methodBody.InitLocals = true;

            _processor.InsertBefore(_realBodyStart, _markStart4BeforeRealBodyStartExceptionHandler);
            _processor.InsertBefore(_markStart4BeforeRealBodyStartExceptionHandler, _markStart3BeforeOnEntryCall);
            _processor.InsertBefore(_markStart3BeforeOnEntryCall, _markStart2BeforeCreateMethodExecutionArgs);
            _processor.InsertBefore(_markStart2BeforeCreateMethodExecutionArgs, _markStart1BeforeCreateArgumentsArray);
            _processor.InsertAfter(_realBodyEnd, _markEnd1NewRealBodyEnd);
            _processor.InsertAfter(_markEnd1NewRealBodyEnd, _markEnd2BeforeOnExitCall);
            _processor.InsertAfter(_markEnd2BeforeOnExitCall, _markRetNew);

            if (!EndsWithThrow)
            {
                saveReturnValue.InsertAfter(_markEnd1NewRealBodyEnd, _processor);
                loadReturnValue.InsertAfter(_markEnd2BeforeOnExitCall, _processor);
            }

            FixRealRetsToBranchToNewRealBodyEnd();
            FixCatchHandlersWithNullEnd();
        }
コード例 #42
0
        public void Weave(
            MethodDefinition method,
            CustomAttribute aspect,
            AspectMethods overriddenAspectMethods,
            ModuleDefinition moduleDefinition)
        {
            if (overriddenAspectMethods == AspectMethods.None)
                return;
            
            var creator = new InstructionBlockChainCreator(method, aspect.AttributeType, moduleDefinition, WeaveCounter);

            _methodBodyChanger = new MethodBodyPatcher(method.Name, method);
            var saveReturnValue = creator.SaveReturnValue();
            var loadReturnValue = creator.LoadValueOnStack(saveReturnValue);
            _methodBodyChanger.Unify(saveReturnValue, loadReturnValue);

            if (WeaveCounter == 0)
                _createArgumentsArray = creator.CreateMethodArgumentsArray();

            var createMethodExecutionArgsInstance = creator.CreateMethodExecutionArgsInstance(_createArgumentsArray);
            _methodBodyChanger.AddCreateMethodExecutionArgs(createMethodExecutionArgsInstance);

            var createAspectInstance = creator.CreateAspectInstance(aspect);
            if (overriddenAspectMethods.HasFlag(AspectMethods.OnEntry))
            {
                var callAspectOnEntry = creator.CallAspectOnEntry(createAspectInstance,
                    createMethodExecutionArgsInstance);
                _methodBodyChanger.AddOnEntryCall(createAspectInstance, callAspectOnEntry);
            }

            if (overriddenAspectMethods.HasFlag(AspectMethods.OnExit))
            {
                var setMethodExecutionArgsReturnValue =
                    creator.SetMethodExecutionArgsReturnValue(createMethodExecutionArgsInstance, loadReturnValue);
                var callAspectOnExit = creator.CallAspectOnExit(createAspectInstance,
                    createMethodExecutionArgsInstance);
                _methodBodyChanger.AddOnExitCall(createAspectInstance, callAspectOnExit,
                    setMethodExecutionArgsReturnValue);
            }

            if (overriddenAspectMethods.HasFlag(AspectMethods.OnException))
            {
                var setMethodExecutionArgsExceptionFromStack =
                    creator.SetMethodExecutionArgsExceptionFromStack(createMethodExecutionArgsInstance);

                var callAspectOnException = creator.CallAspectOnException(createAspectInstance,
                    createMethodExecutionArgsInstance);
                _methodBodyChanger.AddOnExceptionCall(createAspectInstance, callAspectOnException,
                    setMethodExecutionArgsExceptionFromStack);
            }

            if (_methodBodyChanger.EndsWithThrow)
            {
                var saveThrownException = creator.SaveThrownException();
                var loadThrownException = creator.LoadValueOnStack(saveThrownException);
                var loadThrownException2 = creator.LoadValueOnStack(saveThrownException);
                _methodBodyChanger.FixThrowAtEndOfRealBody(
                    saveThrownException, 
                    loadThrownException,
                    loadThrownException2);
            }

            _methodBodyChanger.OptimizeBody();

            WeaveCounter++;
        }
コード例 #43
0
 public void AddCreateMethodExecutionArgs(NamedInstructionBlockChain createMethodExecutionArgsInstance)
 {
     createMethodExecutionArgsInstance.InsertAfter(_markStart2BeforeCreateMethodExecutionArgs, _processor);
 }
        public NamedInstructionBlockChain SetMethodExecutionArgsExceptionFromStack(
            NamedInstructionBlockChain createMethodExecutionArgsInstance)
        {
            var exceptionTypeRef = _referenceFinder.GetTypeReference(typeof (Exception));
            var exceptionVariable = _creator.CreateVariable(CreateVariableName("exception"), exceptionTypeRef);
            var assignExceptionVariable = _creator.AssignValueFromStack(exceptionVariable);

            var methodExecutionArgsSetExceptionMethodRef =
                _referenceFinder.GetMethodReference(createMethodExecutionArgsInstance.TypeReference,
                    md => md.Name == "set_Exception");
            var callSetExceptionBlock = _creator.CallVoidInstanceMethod(createMethodExecutionArgsInstance.Variable,
                methodExecutionArgsSetExceptionMethodRef, exceptionVariable);

            var block = new NamedInstructionBlockChain(exceptionVariable, exceptionTypeRef);
            block.Add(assignExceptionVariable);
            block.Add(callSetExceptionBlock);
            return block;
        }
コード例 #45
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;
        }
        public NamedInstructionBlockChain LoadValueOnStack(NamedInstructionBlockChain instructionBlock)
        {
            var block = new NamedInstructionBlockChain(instructionBlock.Variable, instructionBlock.TypeReference);
            if (instructionBlock.Variable == null)
                return block;

            var loadReturnValueBlock = _creator.PushValueOnStack(instructionBlock.Variable);
            block.Add(loadReturnValueBlock);
            return block;
        }
コード例 #47
0
        public void FixThrowAtEndOfRealBody(
            NamedInstructionBlockChain saveThrownException,
            NamedInstructionBlockChain loadThrownException,
            NamedInstructionBlockChain loadThrownException2)
        {
            // store exception from stack
            var retTemp = _processor.Create(OpCodes.Nop);
            _processor.InsertBefore(_realBodyEnd, retTemp);
            var lastInstruction = saveThrownException.InsertAfter(retTemp, _processor);

            // load exception to stack
            loadThrownException.InsertAfter(lastInstruction, _processor);

            // exception will be thrown at old real body end (maybe in try/catch)

            // after "OnException" load exception again to stack
            var retTemp2 = _processor.Create(OpCodes.Nop);
            _processor.Replace(_markRetNew, retTemp2);
            lastInstruction = loadThrownException2.InsertAfter(retTemp2, _processor);

            // then throw again
            _processor.InsertAfter(lastInstruction, _processor.Create(OpCodes.Throw));
        }
コード例 #48
0
 public void AddCreateArgumentsArray(NamedInstructionBlockChain createArgumentsArray)
 {
     createArgumentsArray.InsertAfter(_markStart1BeforeCreateArgumentsArray, _processor);
 }