我一直很好奇JVM和CLR为什么有基于堆栈的架构? 他们为什么不使用基于寄存器的方法? 它对基于注册的方法有什么好处?
答案 0 :(得分:6)
我曾经考虑过寄存器和堆栈机器之间的差异,并比较指令序列,并运行基准......
然后我花了几年时间在Parrot VM上实现这两种类型的机器,这是一台注册机器。我们天真地开始使用固定寄存器集,结合数据和寄存器堆栈,但最终得出结论认为这是一个人为限制,所以我们改为无限寄存器集和分配器。在某些时候,Parrot快速核心(GCC计算goto)优于Mono和JVM解释器核心(非JIT),但差异归结为JIT。 Parrot的JIT从未与其他人的质量相匹配。 JITter的质量是最终的机器,而这通常是人们所关心的。如果所有VM都使用相同的规则(即,他们有一个约束条件在没有JIT的解释模式下运行),那么我的证据表明注册机器在等效的堆栈机器上具有性能优势。更大的指令,但更少的指令==更高的吞吐量(IPC),以及更好的缓存局部性参考。 Dalvik JVM实际上支持我的发现,Dalvik几年没有JIT,并且与其解释器核心竞争。
很少有主流虚拟机专门在解释模式下运行(AFAIK),他们JIT编译,这就是我们的基准测试。解释器核心的要点是在平台上建立存在,进行字节码验证,并在没有JIT的情况下提供故障安全执行核心。当然,这不是一个规则;有数十亿设备运行没有JIT的ARM加速JVM,但是在没有内存或CPU限制的情况下,这适用。
我工作并致力于调整核心,测试和调优,但最终发现我们真的想要一个快速的JIT。我得出的结论是,如果你最终要进行JIT,那么无论你是实现堆栈还是注册机器来启动,做你喜欢的事情都没有关系;但你会得到市场"使用堆栈机器更快。为虚拟机内核的字节码解释做很多伪寄存器机器虚拟优化部分是一种浪费,因为它不是真正的原生优化。软核不像真实处理器那样进行分支预测,寄存器重命名,指令重新排序,并行执行或预取。我的感觉是,一旦我们拥有高质量的JIT到原生二进制文件,我们就会到达同一个目的地。
由于这些原因,我在技术上倾向于使用基于堆栈的机器:
但在视觉上和情感上我更喜欢注册机:
注意我并没有说编译器可以更容易"#34;生成代码。这似乎是那些主要使用堆栈机器的人喜欢争辩的人。我不相信,也没有发现这是真的。我看到很多爱好编译器在短时间内写在Parrot和CLR上,虽然我承认CLR上的那些具有更高的质量,但这主要是生态系统和可用工具的质量之一。我自己在两个平台上编写了编译器,发现存在权衡,但还不足以让你失眠。
这是一个有根据的猜测,因为我的实际经验不包括编写一个完整的JITter所以我没有第一手经验比较JITting各种形式的操作码的优缺点,但我的意见是,如果您计划包含JIT,那么创建极其复杂的虚拟机操作码核心就等于过早优化。你的时间最好花在其他地方。
答案 1 :(得分:3)
通常不适合链接到文章,但这次我会例外:这个article by Eric Lippert只回答这个问题。