不要JIT和非JIT启用的解释器最终生成机器代码

时间:2012-01-23 17:40:42

标签: jvm native interpreter jit

好的,我已经阅读了几个关于JIT和非JIT启用的解释器之间差异的讨论,以及为什么JIT通常会提升性能。

但是,我的问题是:

最终,非JIT启用的解释器是否必须将字节码(逐行)转换为要执行的机器/本机代码,就像JIT编译器一样?我已经看到过它的帖子和教科书,以及说它没有的帖子。后一个参数是解释器/ JVM直接执行此字节码而不与机器/本机代码交互。

如果非JIT解释器确实将每一行转换为机器代码,那么JIT的主要好处似乎是......

  1. 缓存字节码的所有(普通JIT)或经常遇到的(热点/自适应优化)部分的智能,以便每次都不需要机器代码编译步骤。

  2. 任何优化JIT编译器都可以将字节码转换为机器代码。

  3. 这是准确的吗?在通过非JIT和JIT启用的解释器将字节码转换为机器代码之间似乎没有什么区别(除了可能的优化,或者可能是逐行的JITting块)。

    提前致谢。

2 个答案:

答案 0 :(得分:9)

非JIT解释器不会将字节码转换为机器码。您可以想象非JIT字节码解释器的工作方式(我将使用类似Java的伪代码):

int[] bytecodes = { ... };
int   ip        = 0; // instruction pointer
while(true) {
  int code = bytecodes[ip];
  switch(code) {
    case 0;
      // do something
      ip += 1; break;
    case 1:
      // do something else
      ip += 1; break;
    // and so on...
  }
}

因此,对于每个执行的字节码,解释器必须检索代码,切换其值以决定要做什么,并在进入下一次迭代之前递增其“指令指针”。

使用JIT,所有开销都将减少到零。它只需要适当的开关分支的内容(表示“//做某事”的部分),在内存中将它们串在一起,然后执行跳转到第一个分支的开头。不需要软件“指令指针” - 只有CPU的硬件指令指针。不从内存中检索字节码并切换它们的值。

编写虚拟机并不困难(如果它不必具有极高的性能),并且可能是一项有趣的练习。我为嵌入式项目做过一次,程序代码必须非常紧凑。

答案 1 :(得分:0)

几十年前,似乎普遍认为编译器会将整个程序转换为机器代码,而解释器会将语句转换为机器代码,执行它,丢弃它,翻译下一个等等。这个概念是99%不正确,但有两个真实的核心。在某些微处理器上,某些指令需要使用代码中指定的地址。例如,在8080上,有一条指令用于读取或写入指定的I / O地址0x00-0xFF,但没有指令读取或写入寄存器中指定的I / O地址。对于语言解释器来说,如果用户代码执行类似“out 123,45”的操作,将指令“out 7Bh / ret”存储到内存的三个字节中,用2Dh加载累加器,并调用第一个那些指示。在那种情况下,解释器确实会产生一个机器代码指令来执行解释的指令。但是,这样的代码生成主要限于IN和OUT指令之类的内容。

6502(也许还有8080)的许多常见Microsoft BASIC解释器对存储在RAM中的代码进行了更广泛的使用,但存储在RAM中的代码并不显着依赖于正在执行的程序;大部分RAM例程在程序执行期间不会改变,但是下一条指令的地址作为例程的一部分保持在线,允许使用绝对模式“LDA”指令​​,这节省了至少一个周期每个字节提取。