A deep understanding of how. NET is JIT-compiled

Source: Internet
Author: User
Tags stub
Compiling the CLR only executes native machine code. There are two ways to generate native machine code: Just-in-time compilation (JIT) and precompilation (resulting in native image). Next, I want to talk about JIT.
The CLR uses the type's method table to route by all method calls. A method table of type consists of multiple entry entries. Each entry entry points to a unique stub routine (stub routine). When initialized, each stub routine contains a call to the CLR's JIT compiler (which is exposed by an internal Prestubworker program). After the JIT compiler has born the cost machine code, it overrides the stub routine, inserting a jmp instruction to jump to the code of the JIT compiler just now. The JIT compiler compiles the CIL method body to the appropriate native machine code version only when a method is invoked. This allows you to optimize the working set of your program.
For the following 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 ();
}
}
JIT debugging with the debugger.

First, look at the compilation of each method:
The Assembly of Main () is displayed as:
Push EBP
MOV Ebp,esp
Call Bob.f () method
Call DWORD ptr ds:[00975394h]
Nop
Pop EBP
Ret

[Note]00975394h is Bob.f () the corresponding memory address in corinfo_class_struct the internal data structure, where the content is the starting address of the corresponding stub routine.

The Assembly of F () is shown as:
Push EBP
MOV Ebp,esp
Call BOB.C () method
Call DWORD ptr ds:[00975390h]
Call Bob.b () method
Call DWORD ptr ds:[0097538ch]
Call BOB.A () method
Call DWORD ptr ds:[00975388h]
Nop
Pop EBP
Ret
[note] 00975390, 0097538c, 00975388 are BOB.C (), bob.b (), BOB.A () in corinfo_class_struct the corresponding memory address in the internal data structure, The content in this address is the start address of the corresponding stub routine.

The compilation of C () is shown as:
Push EBP
MOV Ebp,esp
Add DWORD ptr ds:[0097539ch],4
Nop
Pop EBP
Ret
[Note]0097539c is the bob.x memory address.

The compilation of B () is shown as:
Push EBP
MOV Ebp,esp
Add DWORD ptr ds:[0097539ch],3
Nop
Pop EBP
Ret
[Note]0097539c is the bob.x memory address.

The compilation of A () is shown as:
Push EBP
MOV Ebp,esp
Add DWORD ptr ds:[0097539ch],2
Nop
Pop EBP
Ret
[Note]0097539c is the bob.x memory address.



Below, let's look at the contents of the address 00975394h, 00975390h, 0097538ch, 00975388h when debugging:
0X00975384 2b 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-00
Green is the BOB.F () in the corinfo_class_struct of the internal data structure of the corresponding memory address;
Purple is the BOB.C () in the corinfo_class_struct of the internal data structure of the corresponding memory address;
Gray is the bob.b () in the corinfo_class_struct of the internal data structure of the corresponding memory address;
Yellow is the BOB.A () in the corinfo_class_struct of the internal data structure of the corresponding memory address;
[note] The red content is the value of bob.x Oh! You don't believe me? If you look at the changes in the value of red at the bottom of the debugging process, you'll see:
Go to F () before:
0X00975384 2b 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-00
C () plus 4 becomes:
0X00975384 2b 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-00
Add 3 and then change to:
0X00975384 2b 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-00
Add 2 and then change to:
0X00975384 2b 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-00

Let's look at the contents of the stub routine before calling Bob.f ():
0x00975303 E8 d0 7d ff (FE) C0
0x00975313 E8 C0 7d ff (6c) C0 FC
0x00975323 E8 b0 7d ff (C0) FA
0x00975333 E8 A0 7d ff/A4 C0 F8
Green is the content of the stub routines of the Bob.f ();
The purple is the content of the stub routines of the BOB.C ();
The gray place is the contents of the stub routines of the bob.b ();
The yellow is the contents of the stub routine of the BOB.A ();

Let's look at the contents of the stub routine after entering the BOB.F () method body:
0x00975303 E8 d0 7d ff (FE) C0
0x00975313 E8 C0 7d ff (6c) C0 FC
0x00975323 E8 b0 7d ff (C0) FA
0x00975333 E9 ad for a D1 in the F8
It is easy to see that only the contents of the stub routines of Bob.f () have changed. This indicates that the JIT compiler was invoked. Also, the compiler converts the CIL method body of F () to the machine code version in the address space. Replaces the original contents of the stub routine. After the substitution, the first address of the machine code version of the F () method is 0x06d10078 (the content at the blue callout). Don't you believe it? Well, let's take a look at the memory content at the 0x06d10078:
0X06D10078 8b EC FF FF (8c) FF
0x06d10088 5d C3 00 00 00 00 00 00 00 00
You might as well look back at the Assembly of F (), Where:
Purple is not exactly the corresponding memory address of BOB.C () in corinfo_class_struct the internal data structure;
The Gray place is not exactly the corresponding memory address of the bob.b () in corinfo_class_struct the internal data structure;
Yellow is not exactly the corresponding memory address of BOB.A () in corinfo_class_struct the internal data structure;
does not exactly correspond to the F () assembly display:
Call BOB.C () method
Call DWORD ptr ds:[00975390h]
Call Bob.b () method
Call DWORD ptr ds:[0097538ch]
Call BOB.A () method
Call DWORD ptr ds:[00975388h]

Get It! Well, the following calls to C (), B (), A () are the same. The following memory display is available for subsequent debugging:
The contents of the following stub routines:
After entering C (), it becomes:
0x00975303 E8 d0 7d ff (FE) C0
0x00975313 E8 C0 7d ff (6c) C0 FC
0x00975323 E9 Ad-A0 D1 (FA)
0x00975333 E9 ad for a D1 in the F8
After entering B (), it becomes:
0x00975303 E8 d0 7d ff (FE) C0
0x00975313 E9 A8 ad-C0 D1 (MB)
0x00975323 E9 Ad-A0 D1 (FA)
0x00975333 E9 ad for a D1 in the F8
After entering a (), it becomes:
0x00975303 E9 D8 Ad-E0 D1 (FE)
0x00975313 E9 A8 ad-C0 D1 (MB)
0x00975323 E9 Ad-A0 D1 (FA)
0x00975333 E9 ad for a D1 in the F8


After entering C () the contents of the 0X06D100A0 (BOB.C () version of the machine code) are as follows:
0X06D100A0 8b EC 00 9c C3 5d 00 00
Enter B () after the address of the 0X06D100C0 content (bob.b () version of the machine code) is as follows:
0X06D100C0 8b EC 00 00 00 5d C3 (9c)
After entering a () the 0x06d100e0 content (BOB.A () 's machine code version) is as follows:
0X06D100E0 8b EC 00 00 00 (9c) 5d C3







Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.