CLR only executes local machinesCode. There are two ways to generate local machine code: Real-Time compilation (JIT) and pre-compilation (native image ).
CLR uses a method table of the type to route all method calls. A method table of the type consists of multiple entry items. Each entry points to a unique stub routine (stub routine ).
During initialization, each stub routine contains a call to the clr jit Compiler (it is called by the internal prestubworkerProgramPublic ). After the JIT compiler generates the local code, it will rewrite the stub routine and insert a JMP command to jump to the code of the JIT compiler just now. Only when a method is called can the JIT compiler compile the method body of the Server Load balancer into a local machine code version. In this way, the working set of the program can be optimized.
For example:
// Using system;
Public class Bob {
Static int X;
Static void a () {x + = 2 ;}
Static void B () {x + = 3 ;}
Static void C () {x + = 4 ;}
Public static void F ()
{
C ();
B ();
A ();
}
}
Public class myclass
{
Public static void main ()
{
Bob. F ();
}
}
Use the debugger for JIT debugging.
First, let's take a look at the compilation of each method:
The Assembly of main () is displayed as follows:
Push EBP
MoV EBP, ESP
// Call the bob. F () method
Call dword ptr ds: [00975394 H]
NOP
Pop EBP
RET
[Note] 00975394h is the memory address of Bob. F () in the internal data structure of corinfo_class_struct. The content in this address is the start address of the corresponding stub routine.
F () assembly is shown:
Push EBP
MoV EBP, ESP
// Call the bob. C () method
Call dword ptr ds: [00975390 H]
// Call the bob. B () method
Call dword ptr ds: [0097538ch]
// Call the bob. A () method
Call dword ptr ds: [00975388 H]
NOP
Pop EBP
RET
[Note] 00975390, 0097538c, and 00975388 are Bob. C (), Bob. B (), Bob. A () memory address corresponding to the internal data structure in corinfo_class_struct. The content in this address is the start address of the corresponding stub routine.
C () Assembly display:
Push EBP
MoV EBP, ESP
Add dword ptr ds: [0097539ch], 4
NOP
Pop EBP
RET
[Note] 0097539c is the memory address of Bob. X.
The Assembly of B () is shown:
Push EBP
MoV EBP, ESP
Add dword ptr ds: [0097539ch], 3
NOP
Pop EBP
RET
[Note] 0097539c is the memory address of Bob. X.
The assembly of a () is shown:
Push EBP
MoV EBP, ESP
Add dword ptr ds: [0097539ch], 2
NOP
Pop EBP
RET
[Note] 0097539c is the memory address of Bob. X.
Next, let's take a look at the content in the address 00975394 H, 00975390 H, 0097538ch, and 00975388h during debugging:
0x00975384 2B 85 BF 79 03 53 97 00 13 53 97 00 23 53 97 00
0x00975394 33 53 97 00 43 53 97 00 00 00 00 00 00 00 00
In green, Bob. F () corresponds to the memory address in the internal data structure of corinfo_class_struct;
In purple, Bob. C () corresponds to the memory address in the internal data structure of corinfo_class_struct;
The gray part is the memory address corresponding to bob. B () in the internal data structure of corinfo_class_struct;
The yellow color is the memory address corresponding to bob. A () in the internal data structure of corinfo_class_struct;
[Note] the red content is the value of Bob. X! Believe it? Let's take a look at the changes in the red value in the following debugging process and you will understand:
Before entering F:
0x00975384 2B 85 BF 79 03 53 97 00 13 53 97 00 23 53 97 00
0x00975394 33 53 97 00 43 53 97 00 00 00 00 00 00 00 00
C () and 4 are changed:
0x00975384 2B 85 BF 79 03 53 97 00 13 53 97 00 23 53 97 00
0x00975394 33 53 97 00 43 53 97 00 04 00 00 00 00 00 00
After adding 3, it becomes:
0x00975384 2B 85 BF 79 03 53 97 00 13 53 97 00 23 53 97 00
0x00975394 33 53 97 00 43 53 97 00 07 00 00 00 00 00 00
After adding 2, it becomes:
0x00975384 2B 85 BF 79 03 53 97 00 13 53 97 00 23 53 97 00
0x00975394 33 53 97 00 43 53 97 00 09 00 00 00 00 00 00
Let's take a look at the content of the stub routine before Bob. F () is called:
0x00975303 E8 D0 52 7d FF 04 00 10 00 50 20 00 C0 02 00 fe
0x00975313 E8 C0 52 7d FF 05 00 10 00 6C 20 00 C0 03 00 FC
0x00975323 E8 B0 52 7d FF 06 00 10 00 88 20 00 C0 04 00 fa
0x00975333 E8 A0 52 7d FF 07 00 10 00 A4 20 00 C0 05 00 F8
In green, it is the content of Bob. F ()'s Stub routine;
The purple part is the content of Bob. C ()'s Stub routine;
The gray part is the content of Bob. B ()'s Stub routine;
The yellow part is the content of Bob. A ()'s Stub routine;
Let's take a look at the content of the stub routine after entering the bob. F () method body:
0x00975303 E8 D0 52 7d FF 04 00 10 00 50 20 00 C0 02 00 fe
0x00975313 E8 C0 52 7d FF 05 00 10 00 6C 20 00 C0 03 00 FC
0x00975323 E8 B0 52 7d FF 06 00 10 00 88 20 00 C0 04 00 fa
0x00975333 E9 40 ad 39 06 07 00 10 00 78 00 D1 06 05 00 F8
It is easy to see that only the content of the bob. F () Stub routine has changed. This indicates that the JIT compiler is called. At the same time, the compiler converts the F () method body to the machine code version in the address space. The original content of the stub routine is replaced. After replacement, the first address of the machine code version of the F () method is 0x06d10078 (content marked in blue ). Don't you believe it? Well, let's take a look at the memory content at 0x06d10078:
0x06d10078 55 8B ec ff 15 90 53 97 00 FF 15 8C 53 97 00 FF
0x06d10088 15 88 53 97 00 90 5d C3 00 00 00 00 00 00 00 00
You may look back at the F () Assembly display. Here:
Purple is not the memory address corresponding to bob. C () in the internal data structure of corinfo_class_struct;
The gray part is not the memory address corresponding to bob. B () in the internal data structure of corinfo_class_struct;
The yellow color is not the memory address corresponding to bob. A () in the internal data structure of corinfo_class_struct;
Not exactly corresponds to F () Assembly display:
// Call the bob. C () method
Call dword ptr ds: [00975390 H]
// Call the bob. B () method
Call dword ptr ds: [0097538ch]
// Call the bob. A () method
Call dword ptr ds: [00975388 H]
See it! Well, the same is true for calls to C (), B (), and. The following memory is displayed for subsequent debugging:
The following content of the stub routine:
After entering C (), it becomes:
0x00975303 E8 D0 52 7d FF 04 00 10 00 50 20 00 C0 02 00 fe
0x00975313 E8 C0 52 7d FF 05 00 10 00 6C 20 00 C0 03 00 FC
0x00975323 E9 78 ad 39 06 06 00 10 00 A0 00 D1 06 04 00 fa
0x00975333 E9 40 ad 39 06 07 00 10 00 78 00 D1 06 05 00 F8
After entering B (), it becomes:
0x00975303 E8 D0 52 7d FF 04 00 10 00 50 20 00 C0 02 00 fe
0x00975313 E9 A8 ad 39 06 05 00 10 00 C0 00 D1 06 03 00 FC
0x00975323 E9 78 ad 39 06 06 00 10 00 A0 00 D1 06 04 00 fa
0x00975333 E9 40 ad 39 06 07 00 10 00 78 00 D1 06 05 00 F8
After entering a (), it becomes:
0x00975303 E9 D8 ad 39 06 04 00 10 00 E0 00 D1 06 02 00 fe
0x00975313 E9 A8 ad 39 06 05 00 10 00 C0 00 D1 06 03 00 FC
0x00975323 E9 78 ad 39 06 06 00 10 00 A0 00 D1 06 04 00 fa
0x00975333 E9 40 ad 39 06 07 00 10 00 78 00 D1 06 05 00 F8
After entering C (), the content with the address 0x06d100a0 (the machine code version of Bob. C () is as follows:
0x06d100a0 55 8B EC 83 05 9C 53 97 00 04 90 5d C3 00 00 00
Enter the content with the address 0x06d100c0 after B () (the machine code version of Bob. B () as follows:
0x06d100c0 55 8B EC 83 05 9C 53 97 00 03 90 5d C3 00 00 00
Enter the content with the address 0x06d100e0 after a () (the machine code version of Bob. A () is as follows:
0x06d100e0 55 8B EC 83 05 9C 53 97 00 02 90 5d C3 00 00 00