Compilation 字节码堆栈与三地址

Compilation 字节码堆栈与三地址,compilation,interpreter,bytecode,language-implementation,Compilation,Interpreter,Bytecode,Language Implementation,在设计字节码解释器时,现在是否有共识认为堆栈或三地址格式(或其他格式)更好?我正在考虑这些因素: 目标语言是一种与Javascript非常相似的动态语言 性能很重要,但目前开发速度和可移植性更为重要 因此,目前执行将严格由译员执行;如果资源允许,JIT编译器可能会稍后出现 翻译程序将用C语言编写 如果你脑子里有JIT,那么字节码是唯一的选择 以防万一,您可以查看我的TIScript: 资料来源:阅读并了解Lua是如何从基于堆栈的虚拟机转变为基于寄存器的虚拟机的,以及为什么它通过这样做获得了性能

在设计字节码解释器时,现在是否有共识认为堆栈或三地址格式(或其他格式)更好?我正在考虑这些因素:

  • 目标语言是一种与Javascript非常相似的动态语言

  • 性能很重要,但目前开发速度和可移植性更为重要

  • 因此,目前执行将严格由译员执行;如果资源允许,JIT编译器可能会稍后出现

  • 翻译程序将用C语言编写


  • 如果你脑子里有JIT,那么字节码是唯一的选择

    以防万一,您可以查看我的TIScript: 资料来源:

    阅读并了解Lua是如何从基于堆栈的虚拟机转变为基于寄存器的虚拟机的,以及为什么它通过这样做获得了性能

    我在这方面没有太多(实际上没有)经验,因此您可能希望自己验证以下几点(或者其他人可以在必要时纠正我?)

    我现在使用最多的两种语言是C#和Java,因此我自然倾向于使用它们的方法。正如大多数人所知,两者都编译成字节码,并且两种平台(CLR和JVM)都使用JIT(至少在主流实现中是这样)。另外,我猜每个平台的抖动都是用C/C++编写的,但我真的不确定

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


    有了这些,我确信CLR和JVM都是基于堆栈的体系结构。我记得基于堆栈与基于寄存器的一些优点是

  • 较小的生成代码
  • 简单口译员
  • 更简单的编译器
  • 等等
  • 此外,我发现基于堆栈的代码更直观易读,但这是一个主观的问题,正如我之前所说,我还没有看到太多的字节码

    基于寄存器的体系结构的一些优点如下

  • 必须执行更少的指令
  • 更快的口译员(来自#1)
  • 可以更容易地翻译成机器代码,因为大多数常见的硬件都是基于寄存器的
  • 等等

  • 当然,总有办法来弥补每个缺点,但我认为这些描述了显而易见的事情。

    看看OcAML字节码解释器——它是同类中最快的一种。它几乎是一个堆栈机器,在加载时转换为线程代码(使用GNU计算的goto扩展)。您也可以生成类似Forth的线程化代码,这应该相对容易


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

    David Gregg和Roberto Ierusalimschy所做的实验表明,基于寄存器的字节码比基于堆栈的字节码工作得更好,因为执行相同任务所需的字节码指令更少(因此解码开销更小)。因此,三地址格式显然是赢家。

    OP已经决定使用字节码-他正在询问一些实现细节interpreter@Ken韦恩·范德林德:啊,那。。。答案取决于该语言将具有何种内存模型,以及对项目总体复杂性/规模的要求。基于堆栈的方法简单而紧凑。TIScript是基于堆栈的单值寄存器(也称为累加器)。我认为这是合理的速度/尺寸折衷。实际上,有一个256个插槽的数组,用于从函数返回多个值。CLR不像看上去那样“基于堆栈”。而且它从来不是为解释而设计的。如果仔细查看它的指令集,除了简单的pop和dup之外,您不会发现任何堆栈操作。没有交换,就像在JVM中一样。所有现有的.NET JIT都在首先将此“堆栈”表示转换为3地址形式,然后进行SSA转换。对于JVM来说,这一步要复杂得多,因为堆栈行为不太可预测——有关详细信息,请参阅热点源代码。