Microsoft Intermediate Language (MSIL)
All compilers which create code for .NET platform doesn’t create code for x86 CPUs nor other concrete CPU, but generates a code written in the intermediate language known as Microsoft Intermediate Language (MSIL). The CLR gives to the apps the sensation of being executed over a virtual machine, and MSIL is the language of this virtual machine. It means that MSIL is the unique code which can be interpreted by the CLR, and therefore saying that a compiler generates code for .NET platform is the same than saying that it’s generating MSIL.
MSIL was created by Microsoft after asking many specialists in writing compilers and languages, both in academia and business. This is a language with an abstraction level so higher than in the most machine codes of existing CPUs, and includes instructions which allow to work directly with objects (create, destroy, initialize, call virtual methods, etc.), tables and exceptions (throw and catch).
It was said the C# compiler compiles directly the soure code to MSIL, that Microsoft has developed new versions for their languages Visual Basic (Visual Basic.NET) and C++ (C++ with managed extensions) whose compilers generates MSIL, and that they have developed an interpreter for JScript which generates MSIL too. Well, there are also many third parties which has announced to be working in new versions for .NET platform for languages like APL, CAML, Cobol, Eiffel, Fortran, Haskell, Java, Mercury, ML, Mondrian, Oberon, Oz, Pascal, Perl, Python, RPG, Scheme and Smalltalk.
The main advantage of MSIL is that it makes easier the multiplatform execution, and the integration between languages, because of the independence of the CPU, and giving a common format for machine code generated by all compilers which generates for .NET. However, due to the CPUs cannot execute directly MSIL, before executing must be converted to the native code of the CPU. This is done by a component of the CLR, known as JIT compiler (Just In Time) or jitter, which converts dynamically the MSIL code to be executed into the native code needed. This jitter is distributed in three different versions:
● common jitter: This is used by default, and only compiles the MSIL code to native code while it’s necessary, thus saving time and memory avoiding to compile code that never will be executed.To do this, the class charger of the CLR initially replaces calls to new classes to be loaded by calling auxiliary functions (stubs), aimed to compile the real code in the method. Once compiled, the call to the stub is replaced by a direct call to the compiled code, so that subsequent calls will not need the same compilation.
● economic jitter: It works in a similar way to the common jitter, but doesn’t realize any code optimization at compile, it translates each MSIL instruction to the equivalent in machine code on which it runs. This is specially thought to be used in embedded devices with low CPU power and limited memory, because although most inefficient code generated, it’s less time and memory required to compile. Even more, to save memory this jitter can download compiled code that takes some time without running and replace it by the appropiate stub.
For these reasons, this jitter is used by default in windows CE, OS normally included in embebed devices.
Another utility of the economic jitter is that it makes easier to adapt the .NET platform to new systems, because it’s easier to be implemented than the common jitter. In this way, thanks to this it’s possible to develop fastly a version of the CLR that can execute managed apps, although it’s an inefficient way, and once developed it’s possible to focus on developing the common jitter to optimize its execution.
● prejitter: It’s distributed as an command line app caled ngen.exe, by which it’s possible to fully compile any exec or library (any assembly in general, although this concept will be discussed later) containing managed code, and convert it to native code, so that subsecuent executions of the same will be using this compiled version and will not waste time doing dynamic compilation.
The performance of a jitter during the execution of a managed app can give the feeling of making it run slower because time has to be invested in dynamic compilation. This is true, but keep in mind this is a much more efficient solution than which is used in other plataforms, as Java, because in .NET each code isn’t interpreted each time it’s executed but it’s only compiled the first time the method that belongs is called. Even more, the fact that the compilation is done dynamicaly allows to the jitter to have acces to much more info about the machine where the app will be executed than could have any other traditional compiler, so that it can optimize to the machine the code generated (for example using special instructions for Pentium III if the machine allows it, using extra regs, including inline code, etc.).
In addition, as the garbage collector in .NET maintains allways compacted the dynamic memory, memory reservations will be made faster, particulary in apps that don’t cover the memory and, therefore, don’t need garbage collection. For this reasons, engineers at Microsoft think that future versions of their jitters may even get the managed code to be executed faster than unmanaged.
Latest posts by IAvilaE (see all)
- Programación Android, Cómo usar SwipeRefreshLayout - 26 April 2015
- Programación Android, Gson – Librería para parsear documentos JSON - 13 February 2015
- Programación Android, Cómo usar múltiples Fragments II - 24 January 2015