How is the CLR managed when calling a static method?
I have a static class with static methods as shown below:
public static StaticTest
{
public static void DoSomeWork()
{
/// Do Some work
}
}
When a function is called DoSomeWork()
, how does the CLR manage the function references, since it is obvious that a static class cannot be instantiated?
What is the mechanism behind the scenes for calling the function in this case?
source to share
When the CLR loads an assembly that contains static members, those members are placed in an allocated space in memory called High Frequency Heap. Objects on the high-frequency heap are never garbage collected to ensure that static variables are available throughout the life of the application.
source to share
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);
This translates to hidden class parameter (first). In C ++ for Intel, this is called the thiscall convention. For static functions this parameter is simply not available.
If you open the Disassembly function in this code, you will 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, Foo.Fiz
is straight forward call 00007FFBD46ECA40
, and temp.bar()
first does a check for null
(I think mov
+ cmp
), then puts the rcx
link and doescall
source to share
The function body exists in the assembly as a set of IL instructions. When you call this function, the IL result is something like:
call void[assembly]StaticTest:DoSomeWork()
therefore the runtime looks at the "build" for the IL DoSomeWork body, JIT, and executes it. From another point of view, a static function is a normal function, but without the "this" reference to work with.
source to share
When a method runs, the CLR identifies the types used in that method and loads the said assemblies.
It then creates an "Object Type" for each reference type in the method (if they don't exist).
Each type object contains an object type pointer, a sync lock index, static fields, and a method table (which contains one entry for each method of the type).
public void DoSomething()
{
InstanceClass objectInstance = new InstanceClass();
objectInstance.MethodName();
StaticClass.MethodName();
// i.e.here clr creates Type Objects for Instance class and StaticClass in the heap
}
When a statement is new
used to create an object of a class, the CLR automatically creates a pointer of type Object in an instance of that class and initializes it to refer to the corresponding object of the type.
When the INSTANCE method is called (not virtual), i.e. objectInstance.MethodName()
The CLR identifies the Type object based on the type of the variable used and finds that method in the method table of the type object, followed by the JIT method.
When a static method is called, i.e. StaticTest.DoSomeWork()
The CLR (JIT Compiler) identifies the "type object" of the static class based on the class name, and the JIT compiler looks for the method in the method table of the corresponding Object type, and then the JIT method.
source to share