Difference between a bytecode parsed instruction and machine language?
"A bytecode program is normally executed by parsing the instructions one at a time. This kind of bytecode interpreter is very portable. Some systems, called dynamic translators, or"just-in-time" (JIT) compilers, translate bytecode into machine language as necessary at runtime: this makes the virtual machine unportable."
关于这一段的问题是:在处理字节码之后,
解析指令和机器语言(或机器代码)之间的区别是什么?
JIT与字节码解释器不同。
考虑以下C函数:
1 2 3 | int sum() { return 5 + 6; } |
这将直接编译机器代码。关于x86和ARM处理器的确切说明将有所不同。
如果我们编写了一个基本的字节码解释器,它可能看起来像这样:
1 2 3 4 5 6 7 8 9 10 11 12 13 | for(;;) { switch(*currentInstruction++) { case OP_PUSHINT: *stack++ = nextInt(currentInstruction); break; case OP_ADD: --stack; stack[-1].add(*stack); break; case OP_RETURN: return stack[-1]; } } |
然后,这可以解释以下一组说明:
1 2 3 4 | OP_PUSHINT (5) OP_PUSHINT (6) OP_ADD OP_RETURN |
如果您在x86或ARM上编译了字节码解释器,那么您将能够运行相同的字节代码而无需进一步重写解释器。
如果您编写了JIT编译器,则需要为每个支持的处理器发出特定于处理器的指令(机器代码),而字节代码解释器依赖于C ++编译器来发出处理器特定的指令。
在字节码解释器中,指令格式通常用于使用移位和掩码运算符进行非常快速的"解析"。解释器在"解析"(我更喜欢"解码")指令之后,立即更新虚拟机的状态,然后开始解码下一条指令。因此,在解释器中处理字节码后,没有剩余的残余。
在JIT编译器中,字节以大于单个指令的单位进行处理。最小单位是基本块,但现代JIT将更大的路径转换为机器代码。这是转换步骤,转换步骤的输出是机器代码。原始字节码可能保留在内存中,但它不用于实现—因此没有真正的区别。 (尽管JITted虚拟机的机器代码与本机代码编译器发出的机器代码完全不同,但通常也是如此。)
归根结底,它归结为机器指令。
正如您所知,使用#1,您拥有最少的开销,而使用#3,您的开销最大。因此,在初始编译开销之后,性能应该在#1上最快,在#2上同样快。
没有区别 - JIT编译器正是为此完成的 - 它产生了在硬件上执行的机器代码。