Aug 072015
 

Microsoft recently open sourced the CLR and the framework libraries and published them on Github. Though a non production version has been open sourced for a long time under the name Rotor or SSCLI, this time there were no half measures. It gives the community the opportunity to raise issues and also fix them by creating pull requests.

The journey from source to executable code has two phases – first the compiler compiles the source code into the Intermediate Language (MSIL) and then the execution engine (CLR) converts the IL to machine specific assembly instructions. This allows .NET code to be executable across platforms and also be language agnostic as the runtime only understands MSIL.

When the program is executed, the CLR reads the type information from the assembly and creates in-memory structures to represent them. The main structures that represent a type at runtime are the MethodTable and the EEClass. The MethodTable contains “hot” data which is frequently accessed by the runtime to resolve method calls and for garbage collection. The EEClass on the other hand is a cold structure which has detailed structural information about the type including its fields and methods. This is used in Reflection. The main reason for splitting these structures is to optimize performance and keep the frequently accessed fields in as small a data structure  as possible. Every non-generic type has its own copy of the MethodTable and the EEClass, and the pointer to the MethodTable is stored in the first memory address location of each object. We can observe this by loading the SOS managed debugging extension in WinDbg

methodtablelayout

 

The DumpHeap command gives us the information of our type along with the the addresses of all the objects for the type. Using the WinDbg command dq to read the address at the memory address we see that the first memory address points to its MethodTable. There is another structure called the SyncBlock which exists at a negative offset to the MethodTable in the memory. This structure handles the thread synchronization information for the object.

This diagram from the SSCLI Essentials Book explains the relationship between various data structures very clearly.

objectlayout

As you can see the object header points to the MethodTable which in turns point to the EEClassSince the EEClass is not frequently used during runtime, this extra level of indirection doesn’t hurt performance. The MethodTable itself is followed by a call table – a table which contains the addresses of the virtual and non virtual methods to be executed for the type. Since the dispatch table is laid out at a fixed offset from the MethodTablethere is no pointer indirection to access the right method to call. One more thing to be noted about the CLR is that everything is loaded only when it’s needed to be executed. This holds true for both types and methods. When the CLR executes a method which creates another type, it creates the memory structures for the new type. However, even then the methods themselves are not compiled till the absolute last moment when they are needed to be executed.

In the above diagram, you can see the MethodTable vtable pointing to a thunk, which is called a prestub in .NET. When the method is first called, the prestub calls the JIT compiler. The JIT compiler is responsible for reading the MSIL opcode and generating the processor specific assembly code. Once the JIT Compilation is done, the address at which the compiled code resides is backpatched on to the call table. Subsequent calls to the method are directly executed without having to go through the compilation phase

Loading the MethodTable for our calculator type using the command DumpMT with the MD switch which also loads the MethodDescriptors.

methodtable

At this stage in the application execution, the object for Calculator class has been created but the AddTwoNumbers method hasn’t been executed yet. So the MethodDesc table shows that only the constructor method has been jitted but not the AddTwoNumbers method.  Seeing the MethodDescriptors for both the methods using the command !DumpMD

MethodDescriptors

 

The Constructor method now contains a code address, but the AddTwoNumbers doesn’t have code yet. Let’s step forward and see what happens after the method is jitted. Now the code address is replaced by an actual memory address which contains our machine specific assembly code. The next time this method is called, this assembly code will be directly executed.

afterjitting

To view the assembly, use the !u command followed by the code address.  Like in most languages, there are two registers ebp and esp to keep track of each stackframe. During a method call a new stackframe is created and the ebp maintains a pointer to the base of the stack. As code executes the esp register keeps track of how the stack grows and once execution completes, the stack is cleared and the epb value is popped.

assemblyccode

 

Now lets look at this from a code level. Detailed building and debugging instructions are given at the coreclr repo. The MethodTableBuilder class contains the method which loads the types. You could put a breakpoint here but it will keep breaking when system types are loading. To avoid this , put a breakpoint in the RunMain method in assembly.cpp class, and once it breaks then put the breakpoint in the CreateTypeHandle method. This will start breaking on your custom type creation.

createtypehandle

Below is the simple Calculator class code that we are calling. I just used the name of the executable as a Command Argument to run CoreRun.exe in the coreclr solution (Detailed instructions given in Github repo)

DebugCode

 

Now for the fun part – we start debugging the solution. The first step (after loading allocators) is to make sure all parent types are loaded. Since our type doesn’t inherit any class, its parent is System.Object. Once the Parent type is found (can’t be an interface, only a concrete type), it’s method table is returned to the MethodTableBuilder

loadparenttype

 

Then there are some additional checks to handle cases like enums, Generic method, excplicit layouts etc. I’ll skip over them for brevity. At this time we have started to build the MethodTable but not the EEClass. That is done in the next step.

eeclass

 

At this  stage, the CLR checks if the type implements any interfaces. Since interface calls are a bit more complex, there needs to be a relationship from the interface vtable to the implementing type, the calls are mapped using a slot map maintained on the implementing type’s MethodTable which maps it to the vtable slot on the interface. Since our Calculator Class doesn’t inherit interfaces, it will totally skip this block.

interfaces

Now we go into the final and most crucial method which will finally return the TypeHandle. If this method succeeds, then our type has been successfully loaded into memory.

bmtfinalmethod

The first thing the BuildMethodTableThrowing class does is to walk up the inheritance hierarchy and load the parent type. This holds for all methods except interfaces. An interface’s vtable will not contain the System.Object’s method calls. So the method builder will simply set the parent Type to null if the type being loaded is an interface.

interfaceInBuilder

After this, the method makes sure the type in question is not a value type, enum, remoting type, or being called via COM Interop. All this would be loaded differently then simple reference types deriving directly from System.Object. Then the MethodImpl attributes are checked since they impact how a type a loaded. Our Calculator class just skips over these checks. The next method is EnumerateClassMethods which iterates through all the methods and adds them to the MethodTable.

Now that the implemented methods are added to the MethodTable, we need to also add the parent type’s method calls to the current vtable. this is done by the methods ImportParentMethods, AllocateWorkingSlotTables and CopyParentVtable in the MethodBuilder class. Here virtual methods have to be handled differently since they can be overridden by the current type. For non virtual methods, a direct entry to the methods implemented by the Parent type should suffice.

First the maximum possible vtable size is computed. Next a temporary table is allocated for the maximum possible size of the table

maxVTableSize

Then the parent vTable methods are loaded to the Calculator type.

CopyParentVtable

After the Parent methods are added, the current type’s methods are added. We just have two methods – the Constructor and the AddTwoNumbers method. Here first the Virtual Methods are added and then the Non-Virtual ones. Since we didn’t define a custom constructor, it will just inherit the Default constructor and add it in the vtable. Once all virtual methods are added, the remaining methods will get the non vtable slots.

constructorCurrentType

Now that the type’s methods have been completely been loaded, the MethodDescriptors are  created. However the code for the methods is not called even once so it will simply be pointing to a stub waiting to be JIT compiled on execution. After this stage the remaining fields are placed in the MethodTable and some additional integrity checks are done. Finally the Type is loaded and is ready to be published

finalMethodTable

 

May 082010
 

When I looked at the first post in this series, I realized had jumped the gun a bit by going straight to generics and didn’t do enough justice to the fundamentals. So in this post, I have made an effort to go back to the basics.

The CLR (Common Language Runtime) is the heart of .NET. It’s the virtual execution system responsible for converting the platform neutral CIL (Common Intermediate Language) into platform specific and optimized code. The CLR provides services like memory management, garbage collection, exception handling and type verification. Thus it allows language designers to concentrate solely on outputting good CIL and provides a uniform API to allow language interoperability.

The only truth in .NET is the assembly code which is the final product. All the rest are virtual constraints enforced by the execution system in a very robust manner. For e.g. A memory address declared as int cannot take a string value, not because the memory is not able to take the value, but rather the CLR makes sure the values conform to the types declared – a feature called type verification. Usually this happens at the compilation level, but still rechecked at runtime.

Microsoft released the code of the CLI (Common Language Infrastructure) under the name SSCLI (Shared Source CLI). It can be downloaded here. Joel Pobar and others wrote a great book about it. Unfortunately the 2.0 version is still a draft.

Type safety is the most important aspect of .NET programming and a lot of thought went into it. A type can be thought of as a contract which the objects need to conform to. For e.g. in the following code, the Person class is a type – which is supposed to have five public variables and one method. Any object that claims itself to be a person type must necessarily fulfill this contract – or the CLR will reject it during runtime. While working with the more mature compilers like C# and VC++, these checks are already done while converting the code to CIL.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
class Person
{
    public string _name;
    public int _ssn;
    public char _middleName;
    public decimal _phoneNumber;
    public char _bloodGroup;
 
    public Person(string name, int ssn, char middleName, decimal phoneNumber, char bloodGroup)
    {
        this._name = name;
        this._ssn = ssn;
        this._middleName = middleName;
        this._phoneNumber = phoneNumber;
        this._bloodGroup = bloodGroup;
    }
 
    public string GetSomeDetails()
    {
        return String.Empty;
    }
}
 
static void Main(string[] args)
{
    Person _p = new Person("John Doe", 4454353, 'B', 324242432, 'O');
    _p.GetSomeDetails();
}

The code for object class can be found at sscli20\clr\src\vm\object.h in the SSCLI code and the Type class at \sscli\clr\src\vm\typehandle.h. The Type class which is extensively used in Reflection for reading the type metadata is a wrapper for this TypeHandle class. Lets look at the underlying code for some familiar methods of the TypeHandle, some of which you see in Type Class. So every object that declares itself of this type, indirectly points to the data structure to define itself.

1
2
3
4
5
6
7
8
    BOOL IsEnum() const;
    BOOL IsFnPtrType() const;
    inline MethodTable* AsMethodTable() const;
    inline TypeDesc* AsTypeDesc() const;
    BOOL IsValueType() const;
    BOOL IsInterface() const;
    BOOL IsAbstract() const;
    WORD GetNumVirtuals() const;

The MethodTable that you see is the datastructure which contains the frequently used fields needed to call the methods. Along with another structure called EEClass, it defines the type identity of an object in .NET. The difference is that the MethodTable contains data that is frequently accessed by the runtime while the EEClass is a larger store of type metadata. This metadata helps querying type information and dynamically invoking methods using the Reflection API. Using the SOS dll’s DumpHeap command, the address of all the types can be gotten and used to see the EEClass and MethodTables. Lets examine the Person type in the above example.

.load SOS
extension C:\Windows\Microsoft.NET\Framework\v2.0.50727\SOS.dll loaded
 
!DumpHeap -type Person
PDB symbol for mscorwks.dll not loaded
 Address       MT     Size
020a34d4 001530f0       36
total 1 objects
Statistics:
      MT    Count    TotalSize Class Name
001530f0        1           36 DebugApp.Person
Total 1 objects
 
//Getting the address and using the DumpObj command
 
!DumpObj 020a34d4
Name: DebugApp.Person
MethodTable: 001530f0
EEClass: 001513d0
Size: 36(0x24) bytes
 (D:\Ganesh Ranganathan\Documents\Visual Studio 2005\Projects\DebugApp\DebugApp\bin\Debug\DebugApp.exe)
Fields:
      MT    Field   Offset                 Type VT     Attr    Value Name
70d00b68  4000001        4        System.String  0 instance 020a34b0 _name
70d02db4  4000002        8         System.Int32  1 instance  4454353 _ssn
70d01848  4000003        c          System.Char  1 instance       42 _middleName
70cd7f00  4000004       10       System.Decimal  1 instance 020a34e4 _phoneNumber
70d01848  4000005        e          System.Char  1 instance       4f _bloodGroup

Lets dissect this output. First the DumpObj command lists both the MethodTable and the EEClass address and the proceeds to list the fields . See how the value column lists the direct value for the int and char fields while the address is listed for the reference type string. However the bigger decimal type, which actually is a struct and hence a value type, displays the reference. Though SOS displays the reference, we can observe that the address is actually an offset from the object header, which means that it is still stored by value and not the reference. Looking at the memory window for the string and decimal fields’s address gives their original values.


Viewing the object in the memory window shows a pattern of how the runtime stores the values in memory. The object starts with a reference to the MethodTable, then the fields are lined up. It can be observed that there is a difference in how the runtime stores the values of the fields and how we defined them. For e.g. The two character fields are pushed together in spite of not being declared sequentially. This is done to save memory and the runtime is able to manage this situation because all it stores is the memory offset of the fields from the header. To avoid this behavior, types can be decorated with the [StructLayout(LayoutKind.Sequential)] attribute, often used while marshalling data out of managed code, because unmanaged code cant deal with such vagaries. You should also pin your objects, especially references while passing them to unmanaged code, because the runtime keeps moving the memory blocks around.

Now lets look at the MethodTable through SOS. As you can see, every type also inherits the methods from its parent, in this case System.Object. The MethodTable also contains a pointer to the EEClass. When it is laid out during type creation, the method points to a temporary piece of code called a thunk. The thunk in turn calls the JIT compiler and asks it to compile the method. This lazy compilation works wonders for performance and the memory footprint. Once the method is compiled the JIT updates the method to point to the compiled code instead of the thunk.

!DumpMT -MD 001230f0
EEClass: 001213d0
Module: 00122c5c
Name: DebugApp.Person
mdToken: 02000005  (D:\Ganesh Ranganathan\Documents\Visual Studio 2005\Projects\DebugApp\DebugApp\bin\Debug\DebugApp.exe)
BaseSize: 0x24
ComponentSize: 0x0
Number of IFaces in IFaceMap: 0
Slots in VTable: 6
--------------------------------------
MethodDesc Table
   Entry MethodDesc      JIT Name
70c56aa0   70ad4a34   PreJIT System.Object.ToString()
70c56ac0   70ad4a3c   PreJIT System.Object.Equals(System.Object)
70c56b30   70ad4a6c   PreJIT System.Object.GetHashCode()
70cc7550   70ad4a90   PreJIT System.Object.Finalize()
0012c030   001230c4      JIT DebugApp.Person..ctor(System.String, Int32, Char, System.Decimal, Char)
0012c038   001230d4     NONE DebugApp.Person.GetSomeDetails()

You can see the JIT column says none for the GetSomeDetails method and thats because it hasnt been called yet. After its called for the first time, the method is JIT compiled and the MethodDesc shows the code address where the compiled code can be found. Note however, that the MethodDesc is not the usual route for the runtime to execute methods, it is rather done directly. Only when the method is invoked by its name, is the MethodDesc required.

!DumpMT -MD 001230f0
EEClass: 001213d0
Module: 00122c5c
Name: DebugApp.Person
mdToken: 02000005  (D:\Ganesh Ranganathan\Documents\Visual Studio 2005\Projects\DebugApp\DebugApp\bin\Debug\DebugApp.exe)
BaseSize: 0x24
ComponentSize: 0x0
Number of IFaces in IFaceMap: 0
Slots in VTable: 6
--------------------------------------
MethodDesc Table
   Entry MethodDesc      JIT Name
70c56aa0   70ad4a34   PreJIT System.Object.ToString()
70c56ac0   70ad4a3c   PreJIT System.Object.Equals(System.Object)
70c56b30   70ad4a6c   PreJIT System.Object.GetHashCode()
70cc7550   70ad4a90   PreJIT System.Object.Finalize()
0012c030   001230c4      JIT DebugApp.Person..ctor(System.String, Int32, Char, System.Decimal, Char)
0012c038   001230d4      JIT DebugApp.Person.GetSomeDetails()
 
!DumpMD 001230d4
Method Name: DebugApp.Person.GetSomeDetails()
Class: 001213d0
MethodTable: 001230f0
mdToken: 06000007
Module: 00122c5c
IsJitted: yes
CodeAddr: 009f01c8

In this post we saw basic functioning of the CLR and how it creates and stores internal data structures to facilitate code execution at the same time abstracting away all the gory details from the developer and allowing him to solely concentrate on his applications. Below the hood everything is simply memory addresses pointing to each other and a bunch of assembly code. To give it such a high degree of structure and definition is by no means an easy task. Hats off to the developers in the .NET and Java teams!! Hope I am able to reach their skill levels one day. 🙂

Nov 032009
 
Ever wondered how .NET actually works? What goes on behind the scenes with the CLR and JIT compilation. Now Microsoft gives you a chance to actually view all that by release SSCLI – Shared Source Common Language Interface or popularly called Rotor. This is the open source implementation of the CLI which runs .NET.
For Microsoft, which usually is the scourge of open source crowd and doesn’t believing in giving code away, Rotor is a huge step forward. For one, It shows its sincerity in getting more and more developers to code and extend its products. After all, with its huge financial muscle, MSFT has got the best developer talent to develop the framework and the IDE, but making it open source goes one step forward, revealing the internal workings encourages developers to improve the core product rather than just remain end users.
Setting up Rotor is fairly simple

Ever wondered how .NET actually works? What goes on behind the scenes with the CLR and JIT compilation. Now Microsoft gives you a chance to actually view all that by release SSCLI – Shared Source Common Language Interface or popularly called Rotor. This is the open source implementation of the CLI which runs .NET.

For Microsoft, which usually is the scourge of open source crowd and doesn’t believing in giving code away, Rotor is a huge step forward. For one, It shows its sincerity in getting more and more developers to code and extend its products. After all, with its huge financial muscle, MSFT has got the best developer talent to develop the framework and the IDE, but making it open source goes one step forward, revealing the internal workings encourages developers to improve the core product rather than just remain end users.

Setting up Rotor is fairly simple. Here are the steps:-

  • Download Rotor Here. It is a 21.6 MB and the tar.gz file will get downloaded.
  • Decompress the tar.gz file to a local disk.
  • Now Rotor requires Perl to be installed as well. So download ActivePerl from here.
  • The Perl environment variables need to be set. In Vista, this required a reboot
  • In the directory where Rotor was extracted, run env.bat. This batch file will set the various environment variables.
  • Once done, run buildall.cmd from the same location. It takes forever to complete and when its done, you end up with 1.2 GB of code you can go through.

After it completes, go the Samples\Hello directory and execute csc Hello.cs from the command prompt. The file should compile. After this do clix Hello.exe. If your program says “Hello World”, you are all set!!

Once done, this is a good time to start looking at the source code. A good place would be sscli20\clr\src\bcl to get the source code for the BCL without Reflector. More on Rotor later.