Created
January 21, 2014 12:01
-
-
Save LukasBoersma/8538784 to your computer and use it in GitHub Desktop.
MethodRental
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Reflection; | |
using System.Reflection.Emit; | |
using System.Runtime.CompilerServices; | |
using System.Runtime.InteropServices; | |
public class Program | |
{ | |
static ModuleBuilder modb; | |
static Type type; | |
static void Main() | |
{ | |
var ab = AppDomain.CurrentDomain.DefineDynamicAssembly(new AssemblyName("Foo"), AssemblyBuilderAccess.Run); | |
modb = ab.DefineDynamicModule("Foo"); | |
var tb1 = modb.DefineType("Frob"); | |
var jitstub = new byte[15]; | |
jitstub[0] = (byte)OpCodes.Ldtoken.Value; | |
jitstub[5] = (byte)OpCodes.Call.Value; | |
WriteInt32(jitstub, 6, modb.GetMethodToken(typeof(Program).GetMethod("JIT")).Token); | |
jitstub[10] = (byte)OpCodes.Jmp.Value; | |
var mb1 = tb1.DefineMethod("M", MethodAttributes.Static | MethodAttributes.Public, null, new Type[] { typeof(int) }); | |
mb1.SetImplementationFlags(MethodImplAttributes.NoInlining); | |
int tok1 = modb.GetMethodToken(mb1).Token; | |
WriteInt32(jitstub, 1, tok1); | |
WriteInt32(jitstub, 11, tok1); | |
mb1.CreateMethodBody(jitstub, jitstub.Length); | |
var mb2 = tb1.DefineMethod(".ctor", MethodAttributes.Public | MethodAttributes.RTSpecialName | MethodAttributes.SpecialName, null, new Type[] { typeof(int) }); | |
mb2.SetImplementationFlags(MethodImplAttributes.NoInlining); | |
var tok2 = modb.GetMethodToken(mb2).Token; | |
WriteInt32(jitstub, 1, tok2); | |
WriteInt32(jitstub, 11, tok2); | |
mb2.CreateMethodBody(jitstub, jitstub.Length); | |
type = tb1.CreateType(); | |
var mi = type.GetMethod("M"); | |
mi.Invoke(null, new object[] { 42 }); | |
mi.Invoke(null, new object[] { 42 }); | |
} | |
[MethodImpl(MethodImplOptions.NoInlining)] | |
public static void JIT(RuntimeMethodHandle rmh) | |
{ | |
MethodBase method = MethodBase.GetMethodFromHandle(rmh); | |
Console.WriteLine("JIT compiling " + method.Name); | |
if (method.Name == "M") | |
{ | |
byte[] buf = new byte[18]; | |
buf[0] = 0x02 | (17 << 2); | |
buf[1] = (byte)OpCodes.Call.Value; | |
WriteInt32(buf, 2, modb.GetMethodToken(typeof(Console).GetMethod("WriteLine", Type.EmptyTypes)).Token); | |
buf[6] = (byte)OpCodes.Ldarg_0.Value; | |
buf[7] = (byte)OpCodes.Newobj.Value; | |
WriteInt32(buf, 8, modb.GetConstructorToken(type.GetConstructor(new Type[] { typeof(int) })).Token); | |
buf[12] = (byte)OpCodes.Call.Value; | |
WriteInt32(buf, 13, modb.GetMethodToken(typeof(Console).GetMethod("WriteLine", new Type[] { typeof(object) })).Token); | |
buf[17] = (byte)OpCodes.Ret.Value; | |
GCHandle h = GCHandle.Alloc(buf, GCHandleType.Pinned); | |
MethodRental.SwapMethodBody(method.DeclaringType, method.MetadataToken, h.AddrOfPinnedObject(), 18, MethodRental.JitImmediate); | |
h.Free(); | |
} | |
else | |
{ | |
byte[] buf = new byte[14]; | |
buf[0] = 0x02 | (13 << 2); | |
buf[1] = (byte)OpCodes.Ldarg_0.Value; | |
buf[2] = (byte)OpCodes.Call.Value; | |
WriteInt32(buf, 3, modb.GetConstructorToken(typeof(object).GetConstructor(Type.EmptyTypes)).Token); | |
buf[7] = (byte)OpCodes.Ldarg_1.Value; | |
buf[8] = (byte)OpCodes.Call.Value; | |
WriteInt32(buf, 9, modb.GetMethodToken(typeof(Console).GetMethod("WriteLine", new Type[] { typeof(int) })).Token); | |
buf[13] = (byte)OpCodes.Ret.Value; | |
GCHandle h = GCHandle.Alloc(buf, GCHandleType.Pinned); | |
MethodRental.SwapMethodBody(method.DeclaringType, method.MetadataToken, h.AddrOfPinnedObject(), 14, MethodRental.JitImmediate); | |
h.Free(); | |
} | |
} | |
private static void WriteInt32(byte[] buf, int offset, int value) | |
{ | |
buf[offset++] = (byte)(value >> 0); | |
buf[offset++] = (byte)(value >> 8); | |
buf[offset++] = (byte)(value >> 16); | |
buf[offset++] = (byte)(value >> 24); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Thank you. I really appreciate your work.