JIT的执行过程和原理(二)

        为了执行一个方法,首先必须把它的IL转换成本地CPU指令。这是CLR的JIT(just-in-time或者"即时")编译器的职责。       

        就在Main方法执行之前,CLR会检测出Main的代码引用的所有类型。这导致CLR分配一个内部数据结构,它用于管理对所引用的类型的访问。在图1-4中,Main方法引用了一个Console类型,这导致CLR分配一个内部结构。在这个内部数据结构中,Console类型定义的每个方法都有一个对应的记录项 。每个记录项都容纳了一个地址,根据此地址即可找到方法的实现。对这个结构进行初始化时,CLR将每个记录项都设置成(指向)包含在CLR内部的一个未文档化的函数。我将这个函数称为JITCompiler。


        Main方法首次调用WriteLine时,JITCompiler函数会被调用。JITCompiler函数负责将一个方法的IL代码编译成本地CPU指令。由于IL是"即时"(just in time)编译的,所以通常将CLR的这个组件称为JITter或者JIT编译器。
        注意  如果应用程序在Windows的x86版本或WoW64中运行,JIT编译器将生成x86指令。如果应用程序以一个64位应用程序的形式在Windows的x64或Itanium版本上运行,那么JIT编译器将分别生成x64或IA64指令。
       JITCompiler函数被调用时,它知道要调用的是哪个方法,以及具体是什么类型定义了该方法。然后,JITCompiler会在定义(该类型的)程序集的元数据中查找被调用的方法的IL。接着,JITCompiler验证IL代码,并将IL代码编译成本地CPU指令。本地CPU指令被保存到一个动态分配的内存块中。然后,JITCompiler返回CLR为类型创建的内部数据结构,找到与被调用的方法对应的那一条记录,修改最初对JITCompiler的引用,让它现在指向内存块(其中包含了刚才编译好的本地CPU指令)的地址。最后,JITCompiler函数跳转到内存块中的代码。这些代码正是WriteLine方法(获取单个String参数的那个版本)的具体实现。这些代码执行完毕并返回时,会返回到Main中的代码,并像往常一样继续执行。
        现在,Main要第二次调用WriteLine。这一次,由于已对WriteLine的代码进行了验证和编译,所以会直接执行内存块中的代码,完全跳过JITCompiler函数。WriteLine方法执行完毕之后,会再次返回Main。图1-5展示了第二次调用WriteLine时发生的事情。
        一个方法只有在首次调用时才会造成一些性能损失。以后对该方法的所有调用都以本地代码的形式全速运行,无需重新验证IL并把它编译成本地代码。
       JIT编译器将本地CPU指令存储到动态内存中。一旦应用程序终止,编译好的代码也会被丢弃。所以,如果将来再次运行应用程序,或者同时启动应用程序的两个实例(使用两个不同的操作系统进程),JIT编译器必须再次将IL编译成本地指令。
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值