104

我很好奇,为什么 Sun 决定让 JVM 堆栈为基础,而 Google 决定让 DalvikVM 以寄存器为基础?

我想JVM不能真正假设目标平台上有一定数量的寄存器可用,因为它应该是平台独立的。因此,它只是将寄存器分配等推迟到 JIT 编译器。(如我错了请纠正我。)

所以安卓的人想,“嘿,那太低效了,让我们马上去一个基于寄存器的虚拟机......”?但是等等,有多个不同的 android 设备,Dalvik 的目标寄存器是多少?Dalvik 操作码是否针对一定数量的寄存器进行了硬编码?

市场上所有当前的 Android 设备是否具有大致相同数量的寄存器?或者,在 dex 加载期间是否执行了寄存器重新分配?这一切如何结合在一起?

4

3 回答 3

70

基于堆栈的 VM 有一些属性非常适合 Java 的设计目标:

  1. 基于堆栈的设计对目标硬件(寄存器、CPU 功能)的假设很少,因此很容易在各种硬件上实现 VM。

  2. 由于指令的操作数在很大程度上是隐式的,因此目标代码往往会更小。如果您要通过慢速网络链接下载代码,这一点很重要。

使用基于寄存器的方案可能意味着 Dalvik 的代码生成器不必费力地工作来生成高性能代码。在寄存器极其丰富或寄存器极少的架构上运行可能会妨碍 Dalvik,但这不是通常的目标——ARM 是一个非常中间的架构。


我也忘记了 Dalvik 的初始版本根本不包含 JIT。如果您要直接解释指令,那么基于寄存器的方案可能是解释性能的赢家。

于 2010-04-27T07:49:48.687 回答
34

我找不到参考资料,但我认为 Sun 决定采用基于堆栈的字节码方法,因为它可以很容易地在寄存器很少的架构上运行 JVM(例如 IA32)。

在Google I/O 2008 的Dalvik VM Internals中,Dalvik 的创建者Dan Bornstein在演示幻灯片的第 35 张幻灯片中给出了以下关于选择基于寄存器的 VM 的论点:

注册机

为什么?

  • 避免指令调度
  • 避免不必要的内存访问
  • 有效地使用指令流(每条指令的语义密度更高)

在幻灯片 36 上:

注册机

统计数据

  • 指令减少 30%
  • 代码单元减少 35%
  • 指令流中的字节数增加 35%
    • 但我们可以一次吃两个

根据 Bornstein 的说法,这是“将一组类文件转换为 dex 文件时可以找到的一般期望”。

演示视频的相关部分从 25:00 开始

Shi 等人还有一篇题为“Virtual Machine Showdown: Stack Versus Registers”的有见地的论文。(2005)探讨了基于堆栈和基于寄存器的虚拟机之间的差异。

于 2014-03-04T17:13:03.380 回答
13

我不知道为什么 Sun 决定基于 JVM 堆栈。Erlangs 虚拟机,BEAM 出于性能原因是基于寄存器的。由于性能原因,Dalvik 似乎也是基于寄存器的。

Pro Android 2开始:

Dalvik 使用寄存器作为主要的数据存储单元,而不是堆栈。谷歌希望因此能减少 30% 的指令。

关于代码大小:

Dalvik VM 获取生成的 Java 类文件并将它们组合成一个或多个 Dalvik 可执行文件 (.dex) 文件。它重用了来自多个类文件的重复信息,有效地将空间需求(未压缩)比传统的 .jar 文件减少了一半。例如,Android 中 Web 浏览器应用的 .dex 文件约为 200k,而等效的未压缩 .jar 版本约为 500k。闹钟的 .dex 文件大小约为 50k,大约是 .jar 版本的两倍。

我记得计算机体系结构:定量方法也得出结论,寄存器机器比基于堆栈的机器性能更好。

于 2010-11-09T13:37:47.837 回答