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 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); }
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; }
protected virtual void WeaveMethodExecutionArgs(NamedInstructionBlockChain arguments) { var executionArgs = _creator.CreateMethodExecutionArgsInstance( arguments, _aspects[0].Info.AspectAttribute.AttributeType); AddToSetup(executionArgs); ExecutionArgs = executionArgs; }
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); }
public void AddOnExitCall( NamedInstructionBlockChain createAspectInstance, InstructionBlockChain callAspectOnExit, InstructionBlockChain setMethodExecutionArgsReturnValue) { var current = setMethodExecutionArgsReturnValue.InsertAfter(_markEnd2BeforeOnExitCall, _processor); current = AddCreateAspectInstance(createAspectInstance, current); callAspectOnExit.InsertAfter(current, _processor); }
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); }
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); }
private Instruction AddCreateAspectInstance(NamedInstructionBlockChain createAspectInstance, Instruction current) { if (_aspectInstanceCreated) { return(current); } current = createAspectInstance.InsertAfter(current, _processor); _aspectInstanceCreated = true; return(current); }
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); }
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 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); }
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); }
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); }
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); }
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); }
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 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(); }
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); }
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(); }
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; }
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; }
private Instruction AddCreateAspectInstance(NamedInstructionBlockChain createAspectInstance, Instruction current) { if (_aspectInstanceCreated) return current; current = createAspectInstance.InsertAfter(current, _processor); _aspectInstanceCreated = true; return current; }
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(); }
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++; }
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; }
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; }
public void AddCreateArgumentsArray(NamedInstructionBlockChain createArgumentsArray) { createArgumentsArray.InsertAfter(_markStart1BeforeCreateArgumentsArray, _processor); }