public InstructionBlockChain CallMethodWithLocalParameters(MethodDefinition method,
                                                                   MethodDefinition targetMethod, VariableDefinition caller, VariableDefinition resultVariable)
        {
            var chain     = new InstructionBlockChain();
            var variables = new List <VariableDefinition>();

            var index = 0;

            foreach (var parameter in method.Parameters)
            {
                var argIndex = method.IsStatic
                    ? index
                    : index + 1;
                var push = _creator.LoadValueOnStackFromArguments(argIndex);
                chain.Add(new InstructionBlock("push" + index, push.ToList()));

                var variable = _creator.CreateVariable(parameter.ParameterType);
                variables.Add(variable);
                var assign = _creator.AssignValueFromStack(variable);
                chain.Add(assign);

                index++;
            }

            var type = FixTypeReference(targetMethod.DeclaringType);
            var targetMethodReference = FixMethodReference(targetMethod, type);
            var call = caller == null
                ? _creator.CallStaticMethod(targetMethodReference, resultVariable, variables.ToArray())
                : _creator.CallInstanceMethod(targetMethodReference, caller, resultVariable, variables.ToArray());

            chain.Add(call);

            return(chain);
        }
        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
            });
        }
        public InstructionBlockChain CallMethodWithReturn(MethodReference method,
                                                          ILoadable instance,
                                                          IPersistable returnValue,
                                                          params ILoadable[] arguments)
        {
            var type = FixTypeReference(method.DeclaringType);

            method = FixMethodReference(type, method);

            InstructionBlock block;

            if (method.Resolve().IsStatic)
            {
                block = _creator.CallStaticMethod(method, returnValue, arguments);
            }
            else
            {
                block = _creator.CallInstanceMethod(method, instance, returnValue, arguments);
            }

            var chain = new InstructionBlockChain();

            chain.Add(block);
            return(chain);
        }
Пример #4
0
        public InstructionBlockChain CreateReturn()
        {
            var chain = new InstructionBlockChain();

            chain.Add(new InstructionBlock("Return", _creator.CreateReturn()));
            return(chain);
        }
 public void Add(InstructionBlockChain chain)
 {
     foreach (var block in chain.InstructionBlocks)
     {
         Add(block);
     }
 }
        public void AddOnEntryCall(
            NamedInstructionBlockChain createAspectInstance,
            InstructionBlockChain callAspectOnEntry)
        {
            var current = AddCreateAspectInstance(createAspectInstance, _markStart3BeforeOnEntryCall);

            callAspectOnEntry.InsertAfter(current, _processor);
        }
        public void AddOnExitCall(
            NamedInstructionBlockChain createAspectInstance,
            InstructionBlockChain callAspectOnExit,
            InstructionBlockChain setMethodExecutionArgsReturnValue)
        {
            var current = setMethodExecutionArgsReturnValue.InsertAfter(_markEnd2BeforeOnExitCall, _processor);

            current = AddCreateAspectInstance(createAspectInstance, current);
            callAspectOnExit.InsertAfter(current, _processor);
        }
Пример #8
0
        private Instruction AddCreateAspectInstance(InstructionBlockChain createAspectInstance, Instruction current)
        {
            if (_aspectInstanceCreated)
            {
                return(current);
            }

            current = createAspectInstance.InsertAfter(current, _processor);
            _aspectInstanceCreated = true;
            return(current);
        }
Пример #9
0
        public InstructionBlockChain LoadMethodExecutionArgsTagFromPersistable(
            IPersistable createMethodExecutionArgsInstance,
            IPersistable tag)
        {
            var setMethod = _referenceFinder.GetMethodReference(createMethodExecutionArgsInstance.PersistedType,
                                                                md => md.Name == "set_MethodExecutionTag");
            var chain = new InstructionBlockChain();

            chain.Add(_creator.CallVoidInstanceMethod(setMethod, createMethodExecutionArgsInstance, tag));
            return(chain);
        }
Пример #10
0
 protected override void AddToSetup(InstructionBlockChain chain)
 {
     if (_setupPointer == null)
     {
         chain.Prepend(_ilProcessor);
     }
     else
     {
         chain.InsertAfter(_setupPointer, _ilProcessor);
     }
     _setupPointer = chain.Last;
 }
Пример #11
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));
        }
        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);
        }
Пример #13
0
        public InstructionBlockChain CallAspectOnExit(AspectData aspectData,
                                                      IPersistable executionArgs)
        {
            var onExitMethodRef = _referenceFinder.GetMethodReference(aspectData.Info.AspectAttribute.AttributeType,
                                                                      md => md.Name == "OnExit");
            var callOnExitBlock = _creator.CallVoidInstanceMethod(onExitMethodRef,
                                                                  aspectData.AspectPersistable, executionArgs);

            var callAspectOnExitBlockChain = new InstructionBlockChain();

            callAspectOnExitBlockChain.Add(callOnExitBlock);
            return(callAspectOnExitBlockChain);
        }
        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 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);
        }
Пример #16
0
        public InstructionBlockChain ReadReturnValue(IPersistable executionArgs, IPersistable returnValue)
        {
            if (InstructionBlockCreator.IsVoid(_method.ReturnType))
            {
                return(new InstructionBlockChain());
            }

            var getReturnValue = _referenceFinder.GetMethodReference(executionArgs.PersistedType, md => md.Name == "get_ReturnValue");
            var readValueBlock = _creator.CallInstanceMethod(getReturnValue, executionArgs, returnValue);

            var readValueBlockChain = new InstructionBlockChain();

            readValueBlockChain.Add(readValueBlock);
            return(readValueBlockChain);
        }
        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);
        }
Пример #18
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 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);
        }
        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 InstructionBlockChain CallOnExceptionInMoveNext(IPersistable executionArgs, VariableDefinition exceptionLocal)
        {
            var onExceptionMethodRef = _referenceFinder.GetMethodReference(Info.AspectAttribute.AttributeType,
                                                                           md => md.Name == "OnException");

            var setMethod = _referenceFinder.GetMethodReference(executionArgs.PersistedType,
                                                                md => md.Name == "set_Exception");

            var setExceptionOnArgsBlock = _creator.CallVoidMethod(setMethod, GetMoveNextExecutionArgs(executionArgs),
                                                                  new VariablePersistable(exceptionLocal));

            var sm            = StateMachineFromMoveNext;
            var smPersistable = new ThisLoadable(sm);

            var aspectPersistable    = new FieldPersistable(smPersistable, _aspectField.AsDefinedOn(sm));
            var callOnExceptionBlock = _creator.CallVoidMethod(onExceptionMethodRef,
                                                               aspectPersistable, GetMoveNextExecutionArgs(executionArgs));

            var callAspectOnExceptionBlockChain = new InstructionBlockChain();

            callAspectOnExceptionBlockChain.Add(setExceptionOnArgsBlock);
            callAspectOnExceptionBlockChain.Add(callOnExceptionBlock);
            return(callAspectOnExceptionBlockChain);
        }
 public void AddOnEntryCall(
     NamedInstructionBlockChain createAspectInstance,
     InstructionBlockChain callAspectOnEntry)
 {
     var current = AddCreateAspectInstance(createAspectInstance, _markStart3BeforeOnEntryCall);
     callAspectOnEntry.InsertAfter(current, _processor);
 }
Пример #23
0
 private void AddToEnd(InstructionBlockChain chain)
 {
     chain.Append(_ilProcessor);
 }
Пример #24
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
            });
        }
Пример #25
0
        private void WeaveOnEntry(IPersistable returnValue)
        {
            var aspectsWithOnEntry = _aspects
                                     .Select((asp, index) => new { aspect = asp, index })
                                     .Where(x => (x.aspect.AspectMethods & AspectMethods.OnEntry) != 0)
                                     .ToList();

            foreach (var entry in aspectsWithOnEntry)
            {
                var aspect = entry.aspect;
                var call   = _creator.CallAspectOnEntry(aspect, ExecutionArgs);
                AddToSetup(call);

                if (HasMultipleAspects)
                {
                    AddToSetup(_creator.SaveMethodExecutionArgsTagToPersistable(ExecutionArgs, aspect.TagPersistable));
                }

                var nopChain = new InstructionBlockChain();
                nopChain.Add(new InstructionBlock(null, Instruction.Create(OpCodes.Nop)));

                var flowChain   = new InstructionBlockChain();
                var onExitChain = new InstructionBlockChain();

                if (_method.ReturnType.IsByReference)
                {
                    var notSupportedExceptionCtorString =
                        _module.ImportReference(
                            _creator.GetExceptionTypeReference <NotSupportedException>()
                            .Resolve().Methods
                            .FirstOrDefault(m => m.IsConstructor && m.Parameters.Count == 1 && m.Parameters[0].ParameterType.FullName == "System.String"));
                    onExitChain.Add(new InstructionBlock("Throw NotSupported",
                                                         Instruction.Create(OpCodes.Ldstr, "Weaving early return from a method with a byref return type is not supported."),
                                                         Instruction.Create(OpCodes.Newobj, notSupportedExceptionCtorString),
                                                         Instruction.Create(OpCodes.Throw)));
                }
                else
                {
                    for (var i = entry.index - 1; i >= 0; --i)
                    {
                        var onExitAspect = _aspects[i];
                        if ((onExitAspect.AspectMethods & AspectMethods.OnExit) == 0)
                        {
                            continue;
                        }

                        if (HasMultipleAspects)
                        {
                            onExitChain.Add(_creator.LoadMethodExecutionArgsTagFromPersistable(ExecutionArgs, onExitAspect.TagPersistable));
                        }
                        onExitChain.Add(_creator.CallAspectOnExit(onExitAspect, ExecutionArgs));
                    }
                }

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

                onExitChain.Add(new InstructionBlock("Return", Instruction.Create(OpCodes.Ret)));

                flowChain.Add(_creator.IfFlowBehaviorIsAnyOf(ExecutionArgs, nopChain.First, onExitChain, 3));

                flowChain.Add(nopChain);
                AddToSetup(flowChain);
            }
        }
Пример #26
0
 protected virtual void AddToSetup(InstructionBlockChain chain)
 {
     chain.Append(_ilProcessor);
 }
        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 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;
        }
Пример #29
0
        public InstructionBlockChain IfFlowBehaviorIsAnyOf(Func <TypeReference, VariableDefinition> variableFactory, ILoadable args, Instruction nextInstruction, InstructionBlockChain thenBody, params int[] behaviors)
        {
            var typeRef             = args.PersistedType.Resolve();
            var getFlowBehavior     = _referenceFinder.GetMethodReference(typeRef, m => m.Name == "get_FlowBehavior");
            var flowBehaviorLocal   = new VariablePersistable(variableFactory(_moduleDefinition.ImportReference(getFlowBehavior.ReturnType)));
            var flowBehaviorHandler = CallMethodWithReturn(getFlowBehavior, args, flowBehaviorLocal);

            if (behaviors.Length == 0)
            {
                return(flowBehaviorHandler);
            }
            for (var i = 0; i < behaviors.Length - 1; ++i)
            {
                flowBehaviorHandler.Add(flowBehaviorLocal.Load(false, false));
                flowBehaviorHandler.Add(new InstructionBlock("FlowBehavior", Instruction.Create(OpCodes.Ldc_I4, behaviors[i])));
                flowBehaviorHandler.Add(new InstructionBlock("If == then goto the 'then' block", Instruction.Create(OpCodes.Beq_S, thenBody.First)));
            }

            flowBehaviorHandler.Add(flowBehaviorLocal.Load(false, false));
            flowBehaviorHandler.Add(new InstructionBlock("FlowBehavior", Instruction.Create(OpCodes.Ldc_I4, behaviors[behaviors.Length - 1])));
            flowBehaviorHandler.Add(new InstructionBlock("If != then skip", Instruction.Create(OpCodes.Bne_Un, nextInstruction)));

            flowBehaviorHandler.Add(thenBody);

            return(flowBehaviorHandler);
        }
Пример #30
0
 public InstructionBlockChain IfFlowBehaviorIsAnyOf(ILoadable args, Instruction nextInstruction, InstructionBlockChain thenBody, params int[] behaviors)
 {
     return(IfFlowBehaviorIsAnyOf(_creator.CreateVariable, args, nextInstruction, thenBody, behaviors));
 }
        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
            });
        }
        protected override void WeaveOnException(IList <AspectData> allAspects, Instruction instructionCallStart, Instruction instructionCallEnd, Instruction instructionAfterCall, IPersistable returnValue)
        {
            var handler = _moveNext.Body.ExceptionHandlers.FirstOrDefault(IsStateMachineCatchBlock);

            if (handler == null)
            {
                throw new InvalidOperationException($"Async state machine for {_method.FullName} did not catch exceptions in the expected way.");
            }
            var         exceptionLocal = handler.HandlerStart.GetLocalStoredByInstruction(_moveNext.Body.Variables);
            Instruction firstInstructionToSetException = GetFirstInstructionToSetException(handler, out var setResultMethod, out var loadBuilder);
            Instruction exceptionHandlerCurrent        = firstInstructionToSetException.Previous; // Need to start inserting before SetException
            Instruction retInstruction   = handler.HandlerEnd;
            var         processor        = _moveNext.Body.GetILProcessor();
            Instruction gotoSetException = Instruction.Create(OpCodes.Br, firstInstructionToSetException);

            new InstructionBlock("else", gotoSetException).InsertAfter(exceptionHandlerCurrent, processor);

            // Need to replace leave.s with leave since we are adding instructions
            // between here and the destination which may invalidate short form labels.
            for (int i = 0; _moveNext.Body.Instructions[i] != handler.HandlerStart; ++i)
            {
                var inst = _moveNext.Body.Instructions[i];
                if (inst.OpCode == OpCodes.Leave_S)
                {
                    _moveNext.Body.Instructions.RemoveAt(i);
                    _moveNext.Body.Instructions.Insert(i, Instruction.Create(OpCodes.Leave, inst.Operand as Instruction));
                }
            }

            foreach (var onExceptionAspect in allAspects
                     .Where(a => (a.AspectMethods & AspectMethods.OnException) != 0)
                     .Reverse()
                     .OfType <AspectDataOnAsyncMethod>())
            {
                if (HasMultipleAspects)
                {
                    var load = onExceptionAspect.LoadTagInMoveNext(ExecutionArgs);
                    exceptionHandlerCurrent = load.InsertAfter(exceptionHandlerCurrent, processor);
                }

                var callAspectOnException = onExceptionAspect.CallOnExceptionInMoveNext(ExecutionArgs, exceptionLocal);

                if (setResultMethod.Parameters.Count == 1)
                {
                    returnValue = new VariablePersistable(new InstructionBlockCreator(_moveNext, new ReferenceFinder(_module)).CreateVariable(
                                                              ((GenericInstanceType)setResultMethod.DeclaringType).GenericArguments[0]));
                }

                var thenBody = new InstructionBlockChain();
                if (setResultMethod.Parameters.Count == 1)
                {
                    thenBody.Add(_creator.ReadReturnValue(onExceptionAspect.GetMoveNextExecutionArgs(ExecutionArgs), returnValue));
                }
                thenBody.Add(loadBuilder.Clone());
                if (setResultMethod.Parameters.Count == 1)
                {
                    thenBody.Add(returnValue.Load(false));
                }
                thenBody.Add(new InstructionBlock("Call SetResult", Instruction.Create(OpCodes.Call, setResultMethod)));
                thenBody.Add(new InstructionBlock("Leave peacefully", Instruction.Create(OpCodes.Leave, handler.HandlerEnd)));

                var nop = Instruction.Create(OpCodes.Nop);
                callAspectOnException.Add(_creator.IfFlowBehaviorIsAnyOf(
                                              new InstructionBlockCreator(_moveNext, new ReferenceFinder(_module)).CreateVariable,
                                              onExceptionAspect.GetMoveNextExecutionArgs(ExecutionArgs),
                                              nop,
                                              thenBody,
                                              1, 3));
                callAspectOnException.Add(new InstructionBlock("", nop));
                callAspectOnException.InsertAfter(exceptionHandlerCurrent, processor);
                exceptionHandlerCurrent = callAspectOnException.Last;
            }
        }
 public void AddOnExitCall(
     NamedInstructionBlockChain createAspectInstance,
     InstructionBlockChain callAspectOnExit,
     InstructionBlockChain setMethodExecutionArgsReturnValue)
 {
     var current = setMethodExecutionArgsReturnValue.InsertAfter(_markEnd2BeforeOnExitCall, _processor);
     current = AddCreateAspectInstance(createAspectInstance, current);
     callAspectOnExit.InsertAfter(current, _processor);
 }
 public void Add(InstructionBlockChain chain)
 {
     foreach (var block in chain.InstructionBlocks)
         Add(block);
 }