国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > .NET > 正文

深入理解.NET 的JIT編譯方式

2024-07-10 12:58:40
字體:
來源:轉載
供稿:網友
  • 本文來源于網頁設計愛好者web開發社區http://www.html.org.cn收集整理,歡迎訪問。
  • clr只執行本機的機器代碼。有兩種方式產生本機的機器代碼:實時編譯(jit)和預編譯方式(產生native image)。下面,我想談談jit。
    clr使用類型的方法表來路由所有的方法調用。類型的方法表由多個入口項組成。每個入口項指向一個唯一的存根例程(stub routine)。初始化時,每個存根例程包含一個對于clr的jit編譯器的調用(它由內部的prestubworker程序公開)。在jit編譯器生成本機代碼后,它會重寫存根例程,插入一個jmp指令跳轉到剛才jit編譯器的代碼。只有當要調用某個方法時,jit編譯器才會將cil的方法體編譯為相應的本機機器碼版本。這樣可以優化程序的工作集。
    對于如下的例子:
    //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調試。

    首先,看一下每個方法的匯編顯示:
    main()的匯編顯示為:
    push ebp
    mov ebp,esp
    //調用bob.f()方法
    call dword ptr ds:[00975394h]
    nop
    pop ebp
    ret

    [注]00975394h是bob.f()在corinfo_class_struct該內部數據結構中對應的內存地址,該地址中的內容是對應的存根例程的開始地址。

    f()的匯編顯示為:
    push ebp
    mov ebp,esp
    //調用bob.c()方法
    call dword ptr ds:[00975390h]
    //調用bob.b()方法
    call dword ptr ds:[0097538ch]
    //調用bob.a()方法
    call dword ptr ds:[00975388h]
    nop
    pop ebp
    ret
    [注]00975390、0097538c、00975388分別為bob.c()、bob.b()、bob.a()在corinfo_class_struct該內部數據結構中對應的內存地址,該地址中的內容是對應的存根例程的開始地址。

    c()的匯編顯示為:
    push ebp
    mov ebp,esp
    add dword ptr ds:[0097539ch],4
    nop
    pop ebp
    ret
    [注]0097539c是bob.x的內存地址。

    b()的匯編顯示為:
    push ebp
    mov ebp,esp
    add dword ptr ds:[0097539ch],3
    nop
    pop ebp
    ret
    [注]0097539c是bob.x的內存地址。

    a()的匯編顯示為:
    push ebp
    mov ebp,esp
    add dword ptr ds:[0097539ch],2
    nop
    pop ebp
    ret
    [注]0097539c是bob.x的內存地址。



    下面,讓我們看看調試時,地址為00975394h、00975390h、0097538ch、00975388h中的內容:
    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 00
    綠色的是bob.f()在corinfo_class_struct該內部數據結構中對應的內存地址;
    紫色的是bob.c()在corinfo_class_struct該內部數據結構中對應的內存地址;
    灰色的是bob.b()在corinfo_class_struct該內部數據結構中對應的內存地址;
    黃色的是bob.a()在corinfo_class_struct該內部數據結構中對應的內存地址;
    [注]紅色的內容則是bob.x的值哦!不信嗎?那你看看下面的調試過程中紅色處的值的變化,就明白了:
    進入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 00
    c()加4后變為:
    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 00
    加3后變為:
    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 00
    加2后變為:
    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 00

    下面讓我們看看在調用bob.f()之前存根例程處的內容:
    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
    綠色處是bob.f()的存根例程的內容;
    紫色處是bob.c()的存根例程的內容;
    灰色處是bob.b()的存根例程的內容;
    黃色處是bob.a()的存根例程的內容;

    下面讓我們看看在進入bob.f()方法體之后存根例程處的內容:
    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
    易見,只有bob.f()的存根例程的內容起了變化。這說明,jit編譯器被調用了。同時,編譯器將f()的cil方法體轉換為地址空間中的機器碼版本。再替換了存根例程的原內容。替換后,f()方法的機器碼版本的首地址是0x06d10078(藍色標注處的內容)。你不信嗎?那好,我們看一下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
    你不妨再回頭看看f()的匯編顯示,這里:
    紫色處不正是對bob.c()在corinfo_class_struct該內部數據結構中對應的內存地址;
    灰色處不正是對bob.b()在corinfo_class_struct該內部數據結構中對應的內存地址;
    黃色處不正是對bob.a()在corinfo_class_struct該內部數據結構中對應的內存地址;
    不正好對應了f()匯編顯示中:
    //調用bob.c()方法
    call dword ptr ds:[00975390h]
    //調用bob.b()方法
    call dword ptr ds:[0097538ch]
    //調用bob.a()方法
    call dword ptr ds:[00975388h]

    明白了吧!好了,下面對于c() 、b()、a()的調用也是一樣的道理。對于接下來的調試會有如下的內存顯示:
    接下來的存根例程的內容:
    進入c()后變為:
    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
    進入b()后變為:
    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
    進入a()后變為:
    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


    進入c()后地址為0x06d100a0的內容(bob.c()的機器碼版本)如下:
    0x06d100a0 55 8b ec 83 05 9c 53 97 00 04 90 5d c3 00 00 00
    進入b()后地址為0x06d100c0的內容(bob.b()的機器碼版本)如下:
    0x06d100c0 55 8b ec 83 05 9c 53 97 00 03 90 5d c3 00 00 00
    進入a()后地址為0x06d100e0的內容(bob.a()的機器碼版本)如下:
    0x06d100e0 55 8b ec 83 05 9c 53 97 00 02 90 5d c3 00 00 00





    發表評論 共有條評論
    用戶名: 密碼:
    驗證碼: 匿名發表
    主站蜘蛛池模板: 大竹县| 临沧市| 星座| 长寿区| 上林县| 高唐县| 孙吴县| 丽江市| 枞阳县| 哈尔滨市| 海淀区| 九龙县| 紫云| 兴隆县| 内丘县| 阿克陶县| 西华县| 十堰市| 华池县| 卫辉市| 若羌县| 桐柏县| 武安市| 福鼎市| 哈密市| 常熟市| 京山县| 昌乐县| 治县。| 马鞍山市| 乌审旗| 阿城市| 河津市| 马龙县| 崇仁县| 囊谦县| 广德县| 娱乐| 财经| 赣榆县| 抚宁县|