5

I want to see the x86 assembly being generated by .Net's just-in-time compiler. I know how to do this for "normal" code, compiled ahead of time, but don't know how to do it for code generated dynamically at runtime (which I'm doing with expression trees).

I'm not even really sure what to try. For example, the delegate created by compiling the expression tree points at an address, but I don't know what to use to view what's at that address.

Community
  • 1
  • 1
Craig Gidney
  • 17,763
  • 5
  • 68
  • 136

2 Answers2

2

Use LambdaExpression.CompileToMethod(MethodBuilder).

You can then save the AssemblyBuilder to a file which you can examine in your favorite ,NET disassembler.

svick
  • 236,525
  • 50
  • 385
  • 514
leppie
  • 115,091
  • 17
  • 196
  • 297
  • Will the jitter treat CIL generated at runtime in exactly the same way as CIL loaded from an assembly? What if there's, for example, heuristics that do more optimization in one of the cases? – Craig Gidney Feb 16 '13 at 12:11
  • Do you want to view the JIT assembly or the IL? My answer is not applicable to the former. IL loaded from anywhere should be treated the same. – leppie Feb 16 '13 at 12:12
  • 1
    I guess you can just use the debugger in that case. Not quite sure how to do that ;p – leppie Feb 16 '13 at 12:14
2

I ended up using leppie's basic suggestion, outputting the expression to an external assembly. Then, I used reflector to extract the method and paste it into my own code. Then I ran the pasted method, and checked what had been jitted. This might not be 100% accurate, but it at least gives an indication.

Here's some code for writing out the method (the resulting assembly ends up in same directory as the executable):

/// <summary>
/// Writes an assembly, containing the given method, to the working directory.
/// The assembly, type, and method are named based on the given hash name.
/// </summary>
public static void WriteMethodToAssembly<T>(Expression<T> method, string hashName) {
    var assemblyName = new AssemblyName(hashName);
    var assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.RunAndSave);
    var moduleBuilder = assemblyBuilder.DefineDynamicModule(assemblyName.Name, assemblyName.Name + ".dll");
    var typeBuilder = moduleBuilder.DefineType(hashName, TypeAttributes.Public);
    var methodBuilder = typeBuilder.DefineMethod("Run" + hashName, MethodAttributes.Public | MethodAttributes.Static);
    method.CompileToMethod(methodBuilder);

    typeBuilder.CreateType();
    assemblyBuilder.Save(hashName + ".dll");
}

Once you have the assembly, you can use a tool like reflector to extract the method.

Craig Gidney
  • 17,763
  • 5
  • 68
  • 136