public void RewriteVirtualMethod() { var methodInfo = typeof(ExampleClassChild).GetMethod(nameof(ExampleClassChild.VirtualTestMethod), BindingFlags.Public | BindingFlags.Instance); var context = new ShimContext(); var rewrite = ILRewriter.ILRewriter.Rewrite(methodInfo, context); var result = (int)rewrite.Invoke(null, new object[] { new ExampleClassChild(2), 3, context }); Assert.Equal(12, result); }
public void RewriteStaticMethod() { var methodInfo = typeof(ExampleClass).GetMethod(nameof(ExampleClass.StaticTestMethod), BindingFlags.Public | BindingFlags.Static); var context = new ShimContext(); var rewrite = ILRewriter.ILRewriter.Rewrite(methodInfo, context); var result = (int)rewrite.Invoke(null, new object[] { 3, context }); Assert.Equal(6, result); }
public void RewriteInstanceMethod() { var methodInfo = typeof(ExampleClass).GetMethod(nameof(ExampleClass.InstanceTestMethod), BindingFlags.Public | BindingFlags.Instance); var context = new ShimContext(); var rewrite = ILRewriter.ILRewriter.Rewrite(methodInfo, context); //This is not possible with the current generator //var result = (int)rewrite.Invoke(new TestClass(2), new object[] { 3, new ShimContext() }); var result = (int)rewrite.Invoke(null, new object[] { new ExampleClass(2), 3, context }); Assert.Equal(6, result); }
public void RewriteConstructor() { var info = typeof(ExampleClass).GetConstructor(new[] { typeof(int) }); var context = new ShimContext(); var rewrite = ILRewriter.ILRewriter.Rewrite(info, context); var exampleClass = new ExampleClass(2); rewrite.Invoke(null, new object[] { exampleClass, 3, context }); Assert.Equal(3, exampleClass.Factor); info = typeof(ExampleStruct).GetConstructor(new[] { typeof(int) }); rewrite = ILRewriter.ILRewriter.Rewrite(info, new ShimContext()); var dele = (ExampleStructConstructor)rewrite.CreateDelegate(typeof(ExampleStructConstructor)); var exampleStruct = new ExampleStruct(2); dele(ref exampleStruct, 3, context); Assert.Equal(3, exampleStruct.Factor); }
public virtual void TearDown() { HttpContextFake?.Dispose(); ParentPage?.Dispose(); ShimContext?.Dispose(); }
private static void EmitILForMethod(ILGenerator ilGenerator, OperandInstruction <MethodBase> instruction, MethodInfo methodInfo, ShimContext context, int contextParamIndex) { /*if (context.StubCache.TryGetValue(methodInfo, out DynamicMethod stub)) * { * ilGenerator.Emit(OpCodes.Ldtoken, methodInfo); * ilGenerator.Emit(OpCodes.Ldtoken, methodInfo.DeclaringType); * ilGenerator.Emit(OpCodes.Call, stub); * return; * }*/ var methodBody = methodInfo.GetMethodBody(); if (methodBody == null) { ilGenerator.Emit(instruction.OpCode, methodInfo); return; } MethodInfo stub; if (instruction.OpCode == OpCodes.Call) { stub = StubGenerator.GenerateStubForMethod(methodInfo); } else if (instruction.OpCode == OpCodes.Callvirt) { stub = StubGenerator.GenerateStubForVirtualMethod(methodInfo); } /*else if (instruction.OpCode == OpCodes.Ldftn) * { * stub = StubGenerator.GenerateStubForMethodPointer(methodInfo); * } * else if (instruction.OpCode == OpCodes.Ldvirtftn) * { * stub = StubGenerator.GenerateStubForMethodPointer(methodInfo); * }*/ else { ilGenerator.Emit(instruction.OpCode, methodInfo); return; } ilGenerator.Emit(OpCodes.Ldarg, contextParamIndex); ilGenerator.Emit(OpCodes.Call, stub); //PoseContext.StubCache.TryAdd(methodInfo, stub); }
public static MethodInfo Rewrite(MethodBase method, ShimContext context) { var parameterTypes = new List <Type>(); if (!method.IsStatic) { parameterTypes.Add(method.IsForValueType() ? method.DeclaringType.MakeByRefType() : method.DeclaringType); } parameterTypes.AddRange(method.GetParameters().Select(p => p.ParameterType)); parameterTypes.Add(typeof(ShimContext)); var returnType = method.IsConstructor ? typeof(void) : ((MethodInfo)method).ReturnType; var dynamicMethod = new DynamicMethod( string.Format("dynamic_{0}_{1}", method.DeclaringType, method.Name), returnType, parameterTypes.ToArray(), typeof(ILRewriter).Module, true); var ilGenerator = dynamicMethod.GetILGenerator(); var targetInstructions = new Dictionary <ILProcessorInstruction, Label>(); foreach (var local in method.GetMethodBody().LocalVariables) { ilGenerator.DeclareLocal(local.LocalType, local.IsPinned); } var ilReader = new ILReader.ILReader(method); var instructions = ilReader.ToList(); var processor = ILProcessor.FromILInstructions(instructions); var steps = new IILRewriterStep[] { new RemoveShortBranchsStep(), new RemoveConstrainedStep(), new OptimizeBranchesStep(), }; foreach (var step in steps) { step.Rewriter(processor); } foreach (var instruction in processor.Instructions) { switch (instruction) { case OperandInstruction <ILProcessorInstruction> branchInstruction: targetInstructions.TryAdd(branchInstruction.Operand, ilGenerator.DefineLabel); break; case OperandInstruction <IReadOnlyList <ILProcessorInstruction> > switchInstruction: foreach (var target in switchInstruction.Operand) { targetInstructions.TryAdd(target, ilGenerator.DefineLabel); } break; } } foreach (var instruction in processor.Instructions) { if (targetInstructions.TryGetValue(instruction, out var label)) { ilGenerator.MarkLabel(label); } var opCode = instruction.OpCode; switch (instruction) { case NoneInstruction _: ilGenerator.Emit(opCode); break; case OperandInstruction <byte> i: if (instruction.OpCode == OpCodes.Ldc_I4_S) { ilGenerator.Emit(opCode, (sbyte)i.Operand); } else { ilGenerator.Emit(opCode, i.Operand); } break; case OperandInstruction <short> i: ilGenerator.Emit(opCode, i.Operand); break; case OperandInstruction <ushort> i: //Some instructions like ldarg require a unsigned int16 operand but ilGenerator only supports signed int16 ilGenerator.Emit(opCode, (short)i.Operand); break; case OperandInstruction <int> i: ilGenerator.Emit(opCode, i.Operand); break; case OperandInstruction <long> i: ilGenerator.Emit(opCode, i.Operand); break; case OperandInstruction <float> i: ilGenerator.Emit(opCode, i.Operand); break; case OperandInstruction <double> i: ilGenerator.Emit(opCode, i.Operand); break; case OperandInstruction <string> i: ilGenerator.Emit(opCode, i.Operand); break; case OperandInstruction <FieldInfo> i: ilGenerator.Emit(opCode, i.Operand); break; case OperandInstruction <Type> i: ilGenerator.Emit(opCode, i.Operand); break; /*case OperandInstruction<MemberInfo> i: * ilGenerator.Emit(opCode, i.Operand); * break;*/ case OperandInstruction <ILProcessorInstruction> i: ilGenerator.Emit(i.OpCode, targetInstructions[i.Operand]); break; case OperandInstruction <IReadOnlyList <ILProcessorInstruction> > i: ilGenerator.Emit(i.OpCode, i.Operand.Select(t => targetInstructions[t]).ToArray()); break; case OperandInstruction <MethodBase> i: if (i.Operand is ConstructorInfo constructorInfo) { EmitILForConstructor(ilGenerator, i, constructorInfo, parameterTypes.Count - 1); } else { EmitILForMethod(ilGenerator, i, (MethodInfo)i.Operand, context, parameterTypes.Count - 1); } break; /*case InlineTokInstruction tok: * ilGenerator.Emit(instruction.OpCode, tok.Token); * break;*/ default: throw new NotSupportedException(); } } return(dynamicMethod); }