Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does CLR manage when a static method is called?

Tags:

c#

I have static class having static methods as shown below:

public static StaticTest
{
   public static void DoSomeWork()
   {
    /// Do Some work
   }
}

When DoSomeWork() function is called, how does CLR manage the function references as it is obvious that an instance of static class cannot be created?

What is the mechanism behind the scene to call the function in this case?

like image 877
Tanzeel ur Rehman Avatar asked Dec 02 '22 14:12

Tanzeel ur Rehman


2 Answers

When the CLR loads an assembly containing static members, those members are placed in a dedicated space in memory called High Frequency Heap. Objects in the High-Frequency Heap are never Garbage collected to make sure that the static variables are available throughout the lifetime of the application.

like image 132
Darin Dimitrov Avatar answered Dec 09 '22 19:12

Darin Dimitrov


Let's say you have:

class Foo
{
    public void Bar()
    {
        // instance
    }

    public static void Fiz()
    {
        // instance
    }
}

And you do:

var temp = new Foo();
Foo.Fiz();
temp.Bar();

Your code is translated to something like:

var temp = new Foo();
Foo.Fiz();
Foo.Bar(temp);

The this is translated as an hidden parameter of the class (the first one). In C++ for Intel this is called the thiscall calling convention. For static functions, simply there isn't this parameter.

If you open the Disassembly function on that code you'll see that it is something like:

            var temp = new Foo();
00007FFBD48042EC  lea         rcx,[7FFBD48563D8h]  
00007FFBD48042F3  call        00007FFC33E42400  
00007FFBD48042F8  mov         qword ptr [rsp+2B0h],rax  
00007FFBD4804300  mov         rax,qword ptr [rsp+2B0h]  
00007FFBD4804308  mov         qword ptr [rsp+2B8h],rax  
00007FFBD4804310  mov         rcx,qword ptr [rsp+2B8h]  
00007FFBD4804318  call        00007FFBD46ECA48  
00007FFBD480431D  mov         r11,qword ptr [rsp+2B8h]  
00007FFBD4804325  mov         qword ptr [rsp+30h],r11  
            Foo.Fiz();
00007FFBD480432A  call        00007FFBD46ECA40  
            temp.Bar();
00007FFBD480432F  mov         r11,qword ptr [rsp+30h]  
00007FFBD4804334  cmp         byte ptr [r11],0  
00007FFBD4804338  mov         rcx,qword ptr [rsp+30h]  
00007FFBD480433D  call        00007FFBD46ECA38  

As you can see the Foo.Fiz is a direct call 00007FFBD46ECA40, while the temp.bar() first does a check for the null (I think, the mov + cmp), then puts in rcx the reference and does the call

like image 37
xanatos Avatar answered Dec 09 '22 19:12

xanatos