Monday, January 30, 2012

nop - No Operation

If you ever looked at your code compiled in DebugMode Versus ReleaseMode you most certainly saw a few differences. One of those differences is the higher presence of the nop IL instruction in the DebugMode. What does this instruction do? Well, nothing "meaningful"...
Take a look at the following simple example:

(click to enlarge)

As you can see, I have a breakpoint set on the bracket. If we compile this in DebugMode you can see that the compiler inserted a nop instruction right after the anonymous methods "signature":

(click to enlarge)

And in release mode, it didn't:

(click to enlarge)

The compiler inserts nop instructions as placeholders for the non-executing lines of code (since non-executing lines of code are not translated into IL instructions). This is the reason why we can set breakpoints on brackets. The nop instruction does not perform any "meaningful" work yet it can consume a processing cycle.

Thursday, November 24, 2011

callvirt

The first release of the .NET Framework was about 10 years ago (13 February 2002). How well do you know the framework? Take a look at the following class:

(click to enlarge)

Simple. A static field, a static method and an instance method. Both methods return the static field. Now, imagine that we have the following in main:

(click to enlarge)

As you probably noticed, there's an instance call using a null reference. So, the first idea that pops up in your head when someasks "Will this code throw an exception?" is "Yes, it will! A NullReference exception to be exact". Well, if we compile it and run it using Visual Studio, it will actually throw an exception:

(click to enlarge)

So, what's the catch? Well, the right answer to the question above is "It depends". If we look at the generated IL, we can see that the compiler emmited the "callvirt" instruction for the instance method:

(click to enlarge)

That's the normal behaviour. The C# compiler emmits a callvirt instruction on every instance method. It does so in order to check for an object reference at runtime (TypeSafety). But, if we write the exact same code in IL and replace the callvirt by a call instruction and compile it using ILASM:

(click to enlarge)

It works:

(click to enlarge)

This is because the instance method is only using a static field and, at that point of the code, the type constructor already did it's work and the method works fine. If you look at both the assemblies ("C# Compiled" and "ILASM compiled") in .NET Reflector, both generate the following C# code (Main):

(click to enlarge)

If you ever get the change to read this, thanks MC.

Thursday, September 8, 2011

Everything is volatile (.NET Micro)

If you ever builted multithreaded applications, you most certainly came across the volatile keyword. As stated on MSDN, "The volatile keyword indicates that a field might be modified by multiple threads that are executing at the same time. Fields that are declared volatile are not subject to compiler optimizations that assume access by a single thread. This ensures that the most up-to-date value is present in the field at all times". Just recently, I needed this "volatile behaviour" in a .NET MicroFramework project. But when using the keyword "volatile" the compiler actually yielded an error:

(click to enlarge)

What? IsVolatile is not defined? After googling a little I ended up on a blogpost from de .NET Micro development team. Turns out that everything is treated as volatile in the .NET MicroFramework. Well, it makes sense...