字节码栈 vs 三地址码

8
设计字节码解释器时,现在是否有关于使用堆栈、三地址格式或其他方式的共识?以下是需要考虑的因素:
  1. 目标语言是一种类似于JavaScript的动态语言。

  2. 性能很重要,但开发速度和可移植性更为重要。

  3. 因此,实现目前将严格作为解释器;如果有足够资源,可能会稍后引入JIT编译器。

  4. 解释器将使用C语言编写。

5个回答

7

阅读Lua的演变Lua 5.0的实现,了解Lua从基于堆栈的虚拟机转变为基于寄存器的虚拟机,并因此获得性能提升的原因。


此外,Lua解释器是用C语言编写的。 - Dour High Arch

5

David Gregg和Roberto Ierusalimschy的实验表明,基于寄存器的字节码比基于堆栈的字节码效果更好,因为执行相同任务所需的字节码指令更少(因此解码开销更小)。因此,三地址格式是最佳选择。


1

我在这个领域没有太多(实际上几乎没有)经验,所以您可能需要自己验证以下内容(或者也许其他人可以在必要时纠正我?)。

我现在使用最多的两种语言是C#和Java,所以我自然倾向于它们的方法。正如大多数人所知道的那样,它们都被编译为字节码,并且两个平台(CLR和JVM)都利用了JIT(至少在主流实现中)。此外,我猜想每个平台的即时编译器都是用C/C++编写的,但我确实不确定。

总的来说,这些语言及其各自的平台与您的情况非常相似(除了动态部分,但我不确定这是否重要)。此外,由于它们是如此主流的语言,我相信它们的实现可以作为您设计的很好指南。


说到这一点,我确定CLR和JVM都是基于堆栈的架构。我记得基于堆栈架构相对于基于寄存器架构有以下一些优势:

  1. 生成的代码更小
  2. 解释器更简单
  3. 编译器更简单
  4. 等等。

此外,我认为基于堆栈的架构更直观、更易读,但这是一个主观的事情,就像我之前说过的,我还没有看到太多字节码。

而基于寄存器的架构的一些优点是:

  1. 需要执行的指令较少
  2. 解释器更快(来自于#1)
  3. 可以更容易地转换成机器码,因为大多数常见硬件都是基于寄存器的
  4. 等等。

当然,总是有方法可以弥补每种架构的劣势,但我认为这些描述了需要考虑的明显问题。


1
CLR看起来比它实际上少得多的是“基于堆栈”的。而且它从未被设计用于解释。如果您仔细查看其指令集,除了普通的pop和dup之外,您将找不到任何堆栈操作。没有像JVM中那样的交换等操作。所有现有的.NET JIT都将这个“堆栈”表示先转换为3地址形式,然后进行SSA变换。对于JVM来说,由于堆栈行为不太可预测,这一步骤要复杂得多-请参阅HotSpot源以获取详细信息。 - SK-logic

0

看一下OCaml字节码解释器 - 它是同类中最快的之一。它基本上是一个堆栈机器,在加载时转换为线程代码(使用GNU计算跳转扩展)。你也可以生成类似Forth的线程代码,应该相对容易实现。

但是,如果你考虑到未来的JIT编译,请确保你的堆栈机器不是真正的全功能堆栈机器,而是表达式树序列化形式(如.NET CLI) - 这样你就能将你的“堆栈”字节码转换成3地址形式,然后再转换成SSA。


-1

2
OP已经决定使用字节码 - 他正在询问解释器的一些实现细节。 - Ken Wayne VanderLinde
@Ken Wayne VanderLinde:啊,那个……答案取决于该语言将具有什么样的内存模型以及项目的整体复杂性/大小要求。基于堆栈的方法简单而紧凑。 TIScript是基于堆栈的,带有单值寄存器(也称为累加器)。我认为这是速度/大小的合理折衷。 实际上,累加器是一个包含256个插槽的数组,用于从函数中返回多个值。 - c-smile

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接