语言不可知论——寄存器与堆栈



与使用基于堆栈的虚拟机相比,使用基于寄存器的虚拟机究竟有哪些优势和劣势?

对我来说,基于寄存器的机器似乎更直接地进行编程,也更高效。那么,为什么JVM、CLR和PythonVM都是基于堆栈的呢?

在硬件中实现,基于寄存器的机器将更高效,因为对较慢RAM的访问更少。然而,在软件中,即使是基于寄存器的体系结构也很可能在RAM中有"寄存器"。在这种情况下,基于堆栈的机器将同样高效。

此外,基于堆栈的虚拟机将使编写编译器变得更加容易。您不必处理寄存器分配策略。基本上,您可以使用数量不受限制的寄存器。

更新:我写这个答案是假设一个解释的VM。对于JIT编译的VM来说,这可能不成立。我偶然看到这篇论文,它似乎表明JIT编译的VM使用寄存器体系结构可能更高效。

这已经在Parrot VM的常见问题解答和相关文档中得到了一定程度的回答:鹦鹉概述该文档的相关文本如下:

Parrot VM将具有寄存器架构而不是堆栈架构。它还将具有极低级别的操作,与Perl和Python等的中级操作相比,它更类似于Java。

这个决定的理由主要是,通过在某种程度上类似底层硬件,可以将Parrot字节码编译成高效的本地机器语言。

此外,高级语言中的许多程序都由嵌套的函数和方法调用组成,有时使用词汇变量来保存中间结果。在非JIT设置下,基于堆栈的VM将弹出并多次推送相同的操作数,而基于寄存器的VM将简单地分配适当数量的寄存器并对其进行操作,这可以显著减少操作量和CPU时间。

您可能还想阅读以下内容:解释器设计的寄存器与堆栈引用一下:

毫无疑问,为堆栈机器生成代码更容易。大多数大一的编译生都能做到这一点。为寄存器机生成代码有点困难,除非您将其视为带有累加器的堆栈机。(这是可行的,尽管从性能的角度来看有点不理想)简单的目标定位并不是什么大不了的,至少对我来说不是,部分原因是很少有人会直接针对它——我的意思是,拜托,你知道有多少人真的试图为任何人都关心的东西编写编译器?数字很小。另一个问题是,许多有编译器知识的人已经习惯于以寄存器机为目标,因为所有常用的硬件CPU都是这样。

传统上,由于"虚拟机实现的简单性"易于编写编译器后端,虚拟机实现者更喜欢基于堆栈的体系结构,而不是基于寄存器的体系结构——大多数虚拟机最初设计为托管单一语言和代码密度,堆栈体系结构的可执行程序总是比寄存器体系结构的执行程序小。简单性和代码密度是性能的代价。

研究表明,与基于堆栈的体系结构相比,基于注册的体系结构所需执行的虚拟机指令平均减少47%,寄存器代码比相应的堆栈代码大25%,但由于代码大小较大,获取更多虚拟机指令的成本增加,每个虚拟机指令只涉及1.07%的额外实际机器负载,这是可以忽略的。基于寄存器的虚拟机的总体性能是,执行标准基准测试的时间平均减少32.3%。

构建基于堆栈的虚拟机的一个原因是实际的虚拟机操作码可以更小更简单(无需编码/解码操作数)。这使得生成的代码更小,也使得VM代码更简单。

您需要多少个寄存器?

我可能至少还需要一个。

基于堆栈的VM更简单,代码也更紧凑。作为一个现实世界的例子,一位朋友(大约30年前)在Cosmac上用自制的Forth VM构建了一个数据记录系统。Forth VM是一台具有2k ROM和256字节RAM的机器上的30字节代码。

对我来说,"基于寄存器的"虚拟机"更直接地编程"或"更高效"并不明显。也许您认为虚拟寄存器会在JIT编译阶段提供一条捷径?事实肯定不是这样,因为实际处理器可能比VM有更多或更少的寄存器,并且这些寄存器可以以不同的方式使用。(例如:在x86处理器上,要递减的值最好放在ECX寄存器中。)如果实际机器的寄存器比VM多,那么使用"基于寄存器"的编程就会浪费资源,减少资源,而且一无所获。

基于堆栈的虚拟机更容易生成代码。

基于寄存器的虚拟机更容易为创建快速实现,也更容易为生成高度优化的代码。

对于您的第一次尝试,我建议您从基于堆栈的VM开始。

最新更新