How to see the Assembly code generated by the JIT using Visual Studio

by Brian Sullivan


In Visual Studio you can set a breakpoint at any line in your source code. When you run your program Visual Studio will break and stop execution when it reaches your breakpoint. At this point you can right click on your source code and select Go To Disassembly . You will see the assembly language instructions that were created by the JIT compiler for this method.

The JIT compiler generates either Debug code or Optimized code

If this is your first time looking at the JIT assembly code you undoubtedly are looking at the Debug code generated by the JIT compiler.

This Debug code is not the high quality optimized code that the JIT compiler can generate.

Instead it is basic assembly code that does not have any optimizations applied to it. All local variables references are references into the local stack frame storage because in Debug code the JIT does not enregister any local variables. Another property of Debug code is that nop instructions are inserted before some source code statements.

You probably don’t want to spend much time looking at the Debug JIT code. Instead you probably want to look at Optimized JIT code. By looking at Optimized JIT code you can confirm that the assembly code for your important methods are well optimized. And if they are not optimized as well as you want, you can experiment to see if making some source code changes can improve the Optimized JIT code.

There are several settings that you will need to change in order for you to see the Optimized code generated by the JIT compiler.

1. The default configuration is Debug and you want to select the Release configuration.

· Select the Release configuration

2. Make sure that PDB files get created for Release builds.

· Set Generate debug info topdb-only.

More information on why this is necessary:

Ideally you would have wanted it to be the case that simply changing the configuration in the Solution Configuration window to ‘Release’ would be sufficient. However by default the ‘Release’ builds do NOT build a program data base (PDB) file for your program. The (PDB) file is essential when using a debugger as it holds the mapping of the source code lines and local variables for your program.

To fix this go to the properties for the project (right click on the project in the Solution Explorer), select the ‘Build’ tab and click the ‘Advanced’ button all the way at the bottom (you may need to scroll to see it). In the dialog box that comes up there will be a line ‘Debug Info’. It should be set to ‘pdb-only’. This tells the compiler to still compile with optimizations, but to also create the pdb file.

3. Configure the Debugging Options in Visual Studio to allow the JIT to generate optimized code and to allow you to debug the optimized code.

Go to Tools => Options => Debugging => General

· Make sure that box labeled ‘Suppress JIT optimization on module load’ is Unchecked.

· Make sure that the box labeled ‘Enable Just My Code’ is Unchecked.

More information on why this is necessary:

The Visual Studio IDE makes debugging optimized code harder than you would like.

Whenever you launch a managed program under Visual Studio using (Start-Debugging or F5), it will by default, force the JIT to create Debug code. This is true even when you have selected the 'Release' configuration. The reason for this is to improve the debugging experience, but it also makes it impossible to see the Optimized code that you will get whenever your program is not running under the Visual Studio debugger. Your alternative of launching the program using (Start Without Debugging or Ctrl+F5) does allow the JIT to create optimized code but Visual Studio won’t set any of your break points in your code. Thus you normally won't be able to stop and examine the assembly code for a method. We actually want do some debugging with the Optimized JIT code.

Another problem is that Visual Studio 2005 has a new feature called ‘Just My Code’ in which the debugger will not step into any code that it does not believe is being developed. Instead it will step over the code. This is also to improve the debugging experience, as most typical users do not want to step into Microsoft code such as the Collections classes, etc… However any optimized code is also not considered as 'Just My Code’ so it too will be step over and is skipped. Again this makes it impossible to actually stop and see the optimized code.

Note that these are global settings as they affect all solutions; however I have found I don’t miss any of these ‘features’. That is because any code that is compiled for the ‘Debug’ configuration is still not optimized by the JIT so you will still get good debugging there.[*]

In my next blog entry I will demonstrate some of the optimizations that we perform in the JIT compiler.


[*] Note that much of this article was adapted from an earlier article by Vance Morrison (What does foreach actually do?)