为什么基于JVM堆栈和Dalvik VM注册?

aio*_*obe 95 jvm computer-architecture dalvik cpu-registers vm-implementation

我很好奇,为什么Sun决定以JVM堆栈为基础,Google决定以DalvikVM注册为基础?

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

所以Android人员认为,"嘿,那效率很低,让我们马上去找一个基于寄存器的vm ......"?但等等,有多个不同的Android设备,Dalvik的目标是多少个寄存器?Dalvik操作码是否针对一定数量的寄存器进行了硬编码?

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

Mar*_*sey 65

基于堆栈的VM有一些属性可以很好地适应Java的设计目标:

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

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

使用基于寄存器的方案可能意味着Dalvik的代码生成器不一定难以生成高性能代码.运行在一个极其富有寄存器或注册不足的架构上可能会让Dalvik陷入困境,但这不是通常的目标 - ARM是一个非常中等的架构.


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

  • 好的,我刚刚了解到dex字节码是用无限寄存器机来定义的,并且在效率方面,它似乎主要与内存占用有关。 (2认同)

Flo*_*low 27

我找不到引用,但我认为Sun决定采用基于堆栈的字节码方法,因为它可以很容易地在几乎没有寄存器的架构上运行JVM(例如IA32).

在来自Google I/O 2008的Dalvik VM Internals中,Dalvik创建者Dan Bornstein演示幻灯片的幻灯片35上选择了基于寄存器的VM,提供了以下参数:

注册机器

为什么?

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

在幻灯片36上:

注册机器

统计数据

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

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

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

Shi等人还发表了一篇题为"虚拟机摊牌:堆栈与登记册"的富有洞察力的论文.(2005),它探讨了基于堆栈和基于寄存器的虚拟机之间的差异.


Jon*_*nas 12

我不知道为什么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版本大小的两倍.

正如我记得计算机体系结构:定量方法也得出结论,注册机器比基于堆栈的机器表现更好.

  • 如果我不得不猜测,我会说Sun决定使用JVM堆栈,因为它比注册机更容易实现.(但是如此处所述,这是一项非常重要的性能成本.) (2认同)
  • 对于硬件ISA,是的,注册机已经赢了。基本上每个 CPU / 微控制器都是一个寄存器机器,因为相比之下,其他一切都很糟糕。有些有很少的寄存器,比如只有一个累加器,可能还有一两个指针或索引寄存器,但这更像是计算理论意义上的寄存器机。但是我们谈论的是*解释*的VM,因此“注册文件”(如果有的话)实际上会在内存中。除非您 JIT 编译为本地机器代码。reg 比 stack 快的原因非常不同。 (2认同)