国产探花免费观看_亚洲丰满少妇自慰呻吟_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





    發表評論 共有條評論
    用戶名: 密碼:
    驗證碼: 匿名發表
    主站蜘蛛池模板: 永寿县| 子长县| 蒙阴县| 谷城县| 汉阴县| 定日县| 平山县| 泗水县| 包头市| 武定县| 专栏| 榆中县| 大埔县| 茂名市| 中牟县| 上饶市| 璧山县| 泌阳县| 邢台县| 吴川市| 武宣县| 仁寿县| 镇康县| 娱乐| 苍山县| 清水县| 合江县| 沧源| 石景山区| 托克托县| 德惠市| 阳新县| 娄底市| 常熟市| 进贤县| 林芝县| 宁德市| 台中市| 大田县| 麻江县| 嘉定区|