protected override void LoadTargetArgument(PointCut pc, AdviceArgument parameter) { var targetFuncType = _ts.MakeGenericInstanceType( _ts.FuncGeneric2, _ts.ObjectArray, _ts.Object); var targetFuncCtor = targetFuncType.Resolve().Methods.First(m => m.IsConstructor && !m.IsStatic).MakeHostInstanceGeneric(targetFuncType); var targetMethod = _wrapper.MakeCallReference(GetOrCreateUnwrapper().MakeHostInstanceGeneric(_target.DeclaringType)); pc.ThisOrNull().Call(targetFuncCtor, args => args.Load(targetMethod)); }
protected override MethodDefinition FindOrCreateAfterStateMachineMethod() { var afterMethod = _stateMachine.Methods.FirstOrDefault(m => m.Name == Constants.AfterStateMachineMethodName); if (afterMethod == null) { var moveNext = _stateMachine.Methods.First(m => m.Name == "MoveNext"); afterMethod = new MethodDefinition(Constants.AfterStateMachineMethodName, MethodAttributes.Private, _stateMachine.Module.ImportReference(StandardTypes.Void)); afterMethod.Parameters.Add(new ParameterDefinition(_stateMachine.Module.ImportReference(StandardTypes.Object))); _stateMachine.Methods.Add(afterMethod); afterMethod.Mark(WellKnownTypes.DebuggerHiddenAttribute); afterMethod.Body.Instead(pc => pc.Return()); VariableDefinition resvar = null; if (_asyncResult != null) { resvar = new VariableDefinition(_asyncResult); moveNext.Body.Variables.Add(resvar); moveNext.Body.InitLocals = true; } var setResultCall = _builder.Resolve().Methods.First(m => m.Name == "SetResult"); var setResultCallRef = _asyncResult == null ? setResultCall : setResultCall.MakeReference(_builder); moveNext.Body.OnCall(setResultCallRef, il => { il = il.Prev(); var loadArg = new PointCut(args => args.Value(null)); if (_asyncResult != null) { il = il.Store(resvar); loadArg = new PointCut(args => args.Load(resvar).Cast(resvar.VariableType, StandardTypes.Object)); } il = il.ThisOrStatic().Call(afterMethod.MakeReference(_stateMachine.MakeSelfReference()), loadArg); if (_asyncResult != null) { il = il.Load(resvar); } return(il); }); } return(afterMethod); }
private void SetupEntryPoints() { if (_originalEntryPoint != null || _entryPoint != null) { throw new InvalidOperationException("Something went wrong"); } _originalEntryPoint = TargetMethod.IsConstructor && !TargetMethod.IsStatic ? FindBaseClassCtorCall() : GetMethodOriginalEntryPoint(); _entryPoint = OriginalEntryPoint.InsertBefore(OriginalEntryPoint.CreateInstruction(OpCodes.Nop)); }
public static PointCut CreateArray(this PointCut pc, TypeReference elementType, params Action <PointCut>[] elements) { pc = pc.Append(pc.CreateInstruction(OpCodes.Ldc_I4, elements.Length)); pc = pc.Append(pc.CreateInstruction(OpCodes.Newarr, elementType)); for (var i = 0; i < elements.Length; i++) { pc = pc.Append(pc.CreateInstruction(OpCodes.Dup)); SetByIndex(pc, elementType, i, elements[i]); } return(pc); }
private static void InjectInitialization(MethodDefinition initMethod, FieldReference field, PointCut factory ) { initMethod.Body.AfterEntry( e => e .IfEqual( l => l.This().Load(field), r => r.Null(), // (this.)aspect == null pos => pos.This().Store(field, factory) // (this.)aspect = new aspect() ) ); }
private void SetupAroundInfrastructure() { TopWrapper = WrapOriginalMethod(); _lastWrapper = CreateUnwrapMethod(TopWrapper); var topWrapperCut = PointCut.FromEmptyBody(TopWrapper.Body, OpCodes.Ret); //var args = new object[]{ arg1, agr2 } var argsvar = topWrapperCut.CreateVariable(TypeSystem.ObjectArray, null, c => c.LoadCallArgument(TopWrapper.Parameters.ToArray(), TypeSystem.ObjectArray)); // ExecExternalWrapper var resultVar = topWrapperCut.CreateVariable(TypeSystem.Object, null, c => { c.LoadSelfOntoStack(); _topWrapperCallSite = c.InjectMethodCall(_lastWrapper, new object[] { argsvar }); }); //fill ref and out foreach (var param in TopWrapper.Parameters) { var index = TopWrapper.Parameters.IndexOf(param); // todo:: optimize and move to some syntax helper if (param.ParameterType.IsByReference) { topWrapperCut.LoadParameterOntoStack(param, param.ParameterType); topWrapperCut.LoadVariable(argsvar); topWrapperCut.InsertBefore(topWrapperCut.CreateInstruction(OpCodes.Ldc_I4, index)); topWrapperCut.InsertBefore(topWrapperCut.CreateInstruction(OpCodes.Ldelem_Ref)); var elementType = ((ByReferenceType)param.ParameterType).ElementType; topWrapperCut.BoxUnboxTryCastIfNeeded(TypeSystem.Object, elementType); topWrapperCut.SaveIndirect(elementType); } } if (TopWrapper.ReturnType != TypeSystem.Void) { topWrapperCut.LoadVariable(resultVar); topWrapperCut.BoxUnboxTryCastIfNeeded(TypeSystem.Object, TargetMethod.ReturnType); } }
public static void OnLoadField(this MethodBody body, FieldReference field, PointCut pc, Instruction startingFrom = null) { var fieldDef = field.Resolve(); if (fieldDef.IsStatic) { body.OnEveryOccasionOf(i => (i.OpCode == OpCodes.Ldsfld || i.OpCode == OpCodes.Ldsflda) && i.Operand is FieldReference f && f.DeclaringType.Match(field.DeclaringType) && f.Resolve() == fieldDef , pc, startingFrom); } else { body.OnEveryOccasionOf(i => (i.OpCode == OpCodes.Ldfld || i.OpCode == OpCodes.Ldflda) && i.Operand is FieldReference f && f.DeclaringType.Match(field.DeclaringType) && f.Resolve() == fieldDef , pc, startingFrom); } }
protected virtual void LoadInjectionsArgument(PointCut pc, AdviceArgument parameter) { var elements = _injection.Triggers.Select <CustomAttribute, Action <PointCut> >(ca => il => { var ctor = ca.Constructor.Resolve(); void ctorParams(PointCut ilc) => ca.ConstructorArguments.Select(caa => ilc.Value(caa)).ToArray(); il.Call(ctor, ctorParams); if (ca.Properties.Any() || ca.Fields.Any()) { var catype = ca.AttributeType.Resolve(); var attrvar = new VariableDefinition(_ts.Import(ca.AttributeType)); _target.Body.Variables.Add(attrvar); _target.Body.InitLocals = true; il.Store(attrvar); foreach (var namedArg in ca.Properties) { var prop = catype.Properties.First(p => p.Name == namedArg.Name).SetMethod; il.Load(attrvar); il.Call(prop, ilp => ilp.Value(namedArg.Argument)); } foreach (var namedArg in ca.Fields) { var field = catype.Fields.First(p => p.Name == namedArg.Name); il.Load(attrvar); il.Store(field, ilf => ilf.Value(namedArg.Argument)); } il.Load(attrvar); } } ).ToArray(); pc.CreateArray(_ts.Attribute, elements); }
public PointCut CreateNewAroundPoint() { if (_topWrapperCallSite == null) { SetupAroundInfrastructure(); } var newWrapper = CopyMethodDefinition(AroundWrappedMethodPrefix + _wrapperNo + "_" + TopWrapper.Name, TargetMethod.Attributes, TypeSystem.Object); newWrapper.NoInlining = false; MarkDebuggerHidden(newWrapper); MarkCompilerGenerated(newWrapper); TargetMethod.DeclaringType.Methods.Add(newWrapper); var argsParam = new ParameterDefinition(TypeSystem.ObjectArray); newWrapper.Parameters.Add(argsParam); var tempPc = PointCut.FromEmptyBody(newWrapper.Body, OpCodes.Ret); //if (_topWrapper.ReturnType == TypeSystem.Void) // tempPc.CreateVariableFromStack(TypeSystem.Object); //else if (_topWrapper.ReturnType.IsValueType) // tempPc.InsertBefore(tempPc.CreateInstruction(OpCodes.Box, TargetMethod.Module.Import(_topWrapper.ReturnType))); var newWapperPoint = new WrapperPointCut(argsParam, _lastWrapper, ILProcessorFactory.GetOrCreateProcessor(newWrapper.Body), newWrapper.Body.Instructions.First()); _lastWrapper = newWrapper; _wrapperNo++; //substiture top wrapper's call _topWrapperCallSite.InjectionPoint.Operand = newWrapper; return(newWapperPoint); }
public static void OnStoreVar(this MethodBody body, VariableReference variable, PointCut pc, Instruction startingFrom = null) { body.OnEveryOccasionOf(i => ((i.OpCode == OpCodes.Stloc || i.OpCode == OpCodes.Stloc_S) && ((i.Operand is int n && n == variable.Index) || (i.Operand is VariableDefinition v && v.Index == variable.Index))) || (variable.Index == 0 && i.OpCode == OpCodes.Stloc_0) || (variable.Index == 1 && i.OpCode == OpCodes.Stloc_1) || (variable.Index == 2 && i.OpCode == OpCodes.Stloc_2) || (variable.Index == 3 && i.OpCode == OpCodes.Stloc_3) , pc, startingFrom); }
public static void OnEveryOccasionOf(this MethodBody body, Func <Instruction, bool> predicate, PointCut pc, Instruction startingFrom = null) { var insts = body.Instructions; var start = startingFrom == null ? 0 : insts.IndexOf(startingFrom); var icol = insts.Skip(start).ToArray(); foreach (var curi in icol) { if (predicate(curi)) { new Cut(body, curi).Here(pc); } } }
private MethodDefinition CreateUnwrapMethod(MethodDefinition originalMethod) { var unwrapMethod = CopyMethodDefinition(AroundUnwrappedMethodPrefix + originalMethod.Name, originalMethod.Attributes, TypeSystem.Object); unwrapMethod.NoInlining = false; MarkDebuggerHidden(unwrapMethod); MarkCompilerGenerated(unwrapMethod); originalMethod.DeclaringType.Methods.Add(unwrapMethod); var argsParam = new ParameterDefinition(TypeSystem.MakeArrayType(TypeSystem.Object)); unwrapMethod.Parameters.Add(argsParam); var unwrapPoint = PointCut.FromEmptyBody(unwrapMethod.Body, OpCodes.Ret); unwrapPoint.LoadSelfOntoStack(); var vars = new List <VariableDefinition>(); foreach (var parameter in originalMethod.Parameters) { var varType = parameter.ParameterType; if (varType.IsByReference) { varType = ((ByReferenceType)varType).ElementType; } vars.Add( unwrapPoint.CreateVariable(varType, null, c => { c.LoadParameterOntoStack(argsParam); c.InsertBefore(c.CreateInstruction(OpCodes.Ldc_I4, originalMethod.Parameters.IndexOf(parameter))); c.InsertBefore(c.CreateInstruction(OpCodes.Ldelem_Ref)); c.BoxUnboxTryCastIfNeeded(TypeSystem.Object, varType); })); } foreach (var parameter in originalMethod.Parameters) { unwrapPoint.LoadVariable(vars[originalMethod.Parameters.IndexOf(parameter)], parameter.ParameterType); } unwrapPoint.InsertBefore(unwrapPoint.CreateInstruction(OpCodes.Call, TargetMethod.Module.Import(TargetMethod))); if (originalMethod.ReturnType == TypeSystem.Void) { unwrapPoint.LoadValueOntoStack <object>(null); } else if (originalMethod.ReturnType.IsValueType) { unwrapPoint.InsertBefore(unwrapPoint.CreateInstruction(OpCodes.Box, TargetMethod.Module.Import(originalMethod.ReturnType))); } foreach (var parameter in originalMethod.Parameters) { var index = originalMethod.Parameters.IndexOf(parameter); unwrapPoint.LoadParameterOntoStack(argsParam); unwrapPoint.InsertBefore(unwrapPoint.CreateInstruction(OpCodes.Ldc_I4, index)); unwrapPoint.LoadVariable(vars[index], TypeSystem.Object); unwrapPoint.InsertBefore(unwrapPoint.CreateInstruction(OpCodes.Stelem_Ref)); } return(unwrapMethod); }
protected abstract void InsertStateMachineCall(PointCut code);
protected virtual void LoadTypeArgument(PointCut pc, AdviceArgument parameter) { pc.TypeOf(_target.DeclaringType); }
protected virtual void LoadReturnTypeArgument(PointCut pc, AdviceArgument parameter) { pc.TypeOf(_target.ReturnType); }
public static void AfterEntry(this MethodBody body, PointCut action) { new Cut(body, GetCodeStart(body)) .Prev() .Here(action); }
protected virtual void LoadTargetArgument(PointCut pc, AdviceArgument parameter) { pc.Null(); }
protected override void LoadReturnTypeArgument(PointCut pc, AdviceArgument parameter) { pc.TypeOf(_stateMachine.Interfaces.First(i => i.Name.StartsWith("IEnumerable`1"))); }
protected override void LoadReturnValueArgument(PointCut pc, AdviceArgument parameter) { pc.This(); }
protected override void LoadArgumentsArgument(PointCut pc, AdviceArgument parameter) { pc.Load(_wrapper.Parameters[0]); }
public static Cut LoadAspect(this Cut cut, AspectDefinition aspect, MethodDefinition method, PointCut accessor) { FieldReference aspectField; if (method.IsStatic || aspect.Scope == Scope.Global) { aspectField = GetGlobalAspectField(aspect); } else { aspectField = GetInstanceAspectField(aspect, method.DeclaringType, cut); cut = cut.Here(accessor); } return(cut.Load(aspectField)); }
public static void Append(this MethodBody body, PointCut action) { var cut = new Cut(body, entry: false, exit: true); cut.Here(action); }
protected virtual void LoadAttributesArgument(PointCut pc, AdviceArgument parameter) { pc.Null(); }
protected virtual void LoadReturnValueArgument(PointCut pc, AdviceArgument parameter) { pc.Null(); }
protected virtual void LoadNameArgument(PointCut pc, AdviceArgument parameter) { pc.Value(_target.Name); }
private void SetupTaskContinuation() { if (_returnPoint != null || _originalReturnPoint != null) { throw new InvalidOperationException("Something went wrong"); } var helper = GetOrCreateHelperClass(); var continuation = new MethodDefinition( string.Format(ContinuationMethodName, TargetMethod.Name), MethodAttributes.Assembly, TargetMethod.Module.TypeSystem.Void); helper.Methods.Add(continuation); var tcsType = ModuleContext.TypeSystem.TaskCompletionGeneric.MakeGenericType(_completionResultType); var taskTypedType = continuation.Module.Import(_hasResult ? TargetMethod.ReturnType : ModuleContext.TypeSystem.Task); var taskParameter = new ParameterDefinition(null, ParameterAttributes.None, taskTypedType); continuation.Parameters.Add(taskParameter); var tcsField = new FieldDefinition(string.Format(ContinuationFieldName, TargetMethod.Name), FieldAttributes.Public, tcsType); helper.Fields.Add(tcsField); var proc = ILProcessorFactory.GetOrCreateProcessor(continuation.Body); var ret = proc.Create(OpCodes.Ret); proc.Append(ret); var pointcut = new PointCut(proc, ret); pointcut.LoadParameterOntoStack(taskParameter); pointcut.InjectMethodCall(ModuleContext.TypeSystem.Task.Resolve().Properties.First(p => p.Name == "IsCompleted").GetMethod, new object[] { }); pointcut.TestValueOnStack(true, doIfTrue: pc => { pc.LoadParameterOntoStack(taskParameter); pc.InjectMethodCall(ModuleContext.TypeSystem.Task.Resolve().Properties.First(p => p.Name == "IsFaulted").GetMethod, new object[] { }); pc.TestValueOnStack(false, doIfTrue: pct => { if (_hasResult) { _resultVar = pct.CreateVariable(_completionResultType, loadData: c => { c.LoadParameterOntoStack(taskParameter); c.InjectMethodCall(taskTypedType.Resolve().Properties.First(p => p.Name == "Result").GetMethod.MakeGeneric(taskTypedType), new object[] { }); }); } var syncReturnPc = pct.InsertBefore(pct.CreateInstruction(OpCodes.Nop)); _returnPoint = new AsyncPointCut(_helperThisRefFiled, _helperArgumentsFiled, proc, syncReturnPc.InjectionPoint); var setresultMethod = tcsType.Resolve().Methods.First(m => m.Name == "SetResult").MakeGeneric(tcsType); pct.LoadSelfOntoStack(); pct.LoadField(tcsField); pct.InjectMethodCall(setresultMethod, new object[] { _resultVar ?? Markers.DefaultMarker }); }); }, doIfFalse: pc => { var setresultMethod = tcsType.Resolve().Methods.First(m => m.Name == "SetResult").MakeGeneric(tcsType); pc.LoadSelfOntoStack(); pc.LoadField(tcsField); pc.InjectMethodCall(setresultMethod, new object[] { Markers.DefaultMarker }); }); VariableDefinition taskResult = null; if (_isVoid) { taskResult = OriginalEntryPoint.CreateVariable(ModuleContext.TypeSystem.Task); } else { taskResult = OriginalEntryPoint.CreateVariable(TargetMethod.ReturnType); } var processor = ILProcessorFactory.GetOrCreateProcessor(TargetMethod.Body); var singleReturnPoint = processor.Create(OpCodes.Nop); _originalReturnPoint = new PointCut(processor, SetupSingleReturnPoint(processor.Create(OpCodes.Br, singleReturnPoint), taskResult)); //todo:: optimize if (_isVoid) { AsyncVoidRewriter.Rewrite(_originalReturnPoint, TargetMethod, taskResult); } processor.SafeAppend(singleReturnPoint); PointCut continuationPoint = null; if (!_isVoid) { continuationPoint = new PointCut(processor, processor.SafeAppend(processor.CreateOptimized(OpCodes.Ldloc, taskResult.Index))); processor.SafeAppend(processor.Create(OpCodes.Ret)); } else { continuationPoint = new PointCut(processor, processor.SafeAppend(processor.Create(OpCodes.Ret))); } // var tcs = new TaskContinuationSource<TResult>(); var tcsctor = tcsType.Resolve().Methods.First(m => m.IsConstructor && !m.IsStatic).MakeGeneric(tcsType); var tcsVar = continuationPoint.CreateVariable(tcsType, null, c => c.InjectMethodCall(tcsctor)); // var helper = new Helper(); var helperVar = continuationPoint.CreateVariable(helper, null, c => c.InjectMethodCall(helper.Methods.First(m => m.IsConstructor && !m.IsStatic))); // var args = new object[] { param1, param2 ... }; var argsvar = continuationPoint.CreateVariable(new ArrayType(TargetMethod.Module.TypeSystem.Object), null, c => c.LoadCallArgument(TargetMethod.Parameters.ToArray(), new ArrayType(TargetMethod.Module.TypeSystem.Object))); //helper.this_ref = this continuationPoint.LoadVariable(helperVar); continuationPoint.SetField(_helperThisRefFiled, c => c.LoadSelfOntoStack()); // helper.args = args continuationPoint.LoadVariable(helperVar); continuationPoint.SetField(_helperArgumentsFiled, c => c.LoadVariable(argsvar)); // helper.continuationSource = tcs continuationPoint.LoadVariable(helperVar); continuationPoint.SetField(tcsField, c => c.LoadVariable(tcsVar)); // task.ContinueWith(new Action<TResult>(helper.Continuation)) continuationPoint.LoadVariable(helperVar); continuationPoint.InsertBefore(continuationPoint.CreateInstruction(OpCodes.Ldftn, continuation)); var actionTr = continuation.Module.Import(ModuleContext.TypeSystem.ActionGeneric.MakeGenericType(taskTypedType)); var contActionCtor = continuation.Module.Import(actionTr.Resolve().Methods.First(m => m.IsConstructor && !m.IsStatic)) .MakeGeneric(actionTr); var actionVar = continuationPoint.CreateVariable(actionTr, null, c => c.InsertBefore(continuationPoint.CreateInstruction(OpCodes.Newobj, (MethodReference)c.CreateMemberReference(contActionCtor)))); MethodReference contWithMethod = continuation.Module.Import(taskTypedType.Resolve().Methods.First(m => m.Name == "ContinueWith" && m.Parameters.Count == 1)); if (_hasResult) { contWithMethod = contWithMethod.MakeGeneric(taskTypedType); } continuationPoint.LoadVariable(taskResult); continuationPoint.InjectMethodCall(contWithMethod, new object[] { actionVar }); continuationPoint.InsertBefore(continuationPoint.CreateInstruction(OpCodes.Pop)); // task = tcs.Task if (!_isVoid) { var getTask = continuation.Module.Import(tcsType.Resolve().Properties.First(p => p.Name == "Task").GetMethod) .MakeGeneric(tcsType); continuationPoint.SetVariable(taskResult, c => { c.LoadVariable(tcsVar); c.InjectMethodCall(getTask); }); } }
protected virtual void LoadReturnValueArgument(PointCut pc, AdviceArgument parameter) { _log.LogWarning(CompilationMessage.From($"Advice {_effect.Type.ToString()} does not support {parameter.Source.ToString()} argument and will always return null", _effect.Method)); pc.Null(); }
public static void Rewrite(PointCut asyncVoidPc, MethodDefinition asyncVoidMethod, VariableDefinition taskVar) { asyncVoidMethod.Body.SimplifyMacros(); var asyncVoidMBType = asyncVoidMethod.Module.Import(typeof(AsyncVoidMethodBuilder)); var asyncTaskMBType = asyncVoidMethod.Module.Import(typeof(AsyncTaskMethodBuilder)); asyncVoidMethod.Body.Variables.First(v => v.VariableType.IsTypeOf(asyncVoidMBType)).VariableType = asyncTaskMBType; Instruction loadStateMachineInst = null; FieldReference builderField = null; foreach (var inst in asyncVoidMethod.Body.Instructions) { var method = inst.Operand as MethodReference; if (method != null && method.DeclaringType.IsTypeOf(asyncVoidMBType)) { var newMethod = asyncVoidMethod.Module.Import(asyncTaskMBType.Resolve().Methods.First(m => m.Name == method.Name)); if (method.IsGenericInstance) { newMethod = newMethod.MakeGeneric(newMethod.DeclaringType, ((IGenericInstance)method).GenericArguments.ToArray()); } inst.Operand = newMethod; if (method.Name == "Create") { loadStateMachineInst = inst.Previous; builderField = (FieldReference)inst.Next.Operand; } } } var stateMachine = builderField.DeclaringType.Resolve(); stateMachine.Fields.First(v => v.FieldType.IsTypeOf(asyncVoidMBType)).FieldType = asyncTaskMBType; foreach (var md in stateMachine.Methods) { RewriteMethod(md); } var getTask = asyncTaskMBType.Resolve().Properties.First(p => p.Name == "Task").GetMethod; if (loadStateMachineInst == null || builderField == null) { throw new NotSupportedException("Unsupported state machine implementation"); } asyncVoidPc.SetVariable(taskVar, c => { c.InsertBefore(c.CreateInstruction(loadStateMachineInst.OpCode, (VariableDefinition)loadStateMachineInst.Operand)); c.InsertBefore(c.CreateInstruction(OpCodes.Ldflda, builderField)); c.InjectMethodCall(getTask); }); asyncVoidMethod.Body.OptimizeMacros(); }
protected virtual void LoadMethodArgument(PointCut pc, AdviceArgument parameter) { pc.MethodOf(_target).Cast(_ts.MethodBase); }
public static PointCut GetByIndex(this PointCut pc, TypeReference elementType, int index) { pc = pc.Append(pc.CreateInstruction(OpCodes.Ldc_I4, index)); pc = pc.Append(pc.CreateInstruction(GetLoadOpcode(elementType))); return(pc); }