解释型语言(比如Ruby)是如何运行的?

6

我打算学习Ruby。我知道它是一种解释性语言。我知道编译型语言最终会被翻译成机器码,但Ruby解释器做了什么呢?我读过解释器是用C编写的,但每一行Ruby代码是否都会转换成C,然后再编译成机器码?我也听说过JIT,但如果这会使回答变得更加复杂,您无需回答。我想知道的是我的Ruby代码会发生什么。

1个回答

8
它将Ruby代码转换为某种更简单的“中间”表示形式(在最近的版本中,它编译为字节码)。它还在计算机内存中构建了一个“虚拟机”,模拟执行该表示形式的物理机器。
这台机器镜像了物理机器,至少是合理和有用的。它通常具有用于存储中间值和返回地址的指令内存、程序计数器、堆栈等。一些更复杂的机器也有寄存器。它有一个固定而相对原始(与像Ruby这样的语言相比,而不是与实际CPU指令集相比)的指令集。像CPU一样,虚拟机无休止地循环:
读取当前指令(由程序计数器标识)。 (解码它,尽管这通常比真正的CPU要简单得多,至少比CISC更简单。) 执行它(在过程中可能操作堆栈和/或寄存器)。 更新程序计数器。
使用解释器,所有这些都通过间接层发生。您的实际物理CPU不知道自己在做什么。虚拟机本身就是软件,上述每个步骤都委托给CPU进行多个(在具有相当高级别的字节码指令的情况下,可能是几十个或几百个)物理CPU周期。每次读取指令时都会发生这种情况。
进入JIT编译。最简单的形式只是用执行解释器遇到它时将每个字节码指令替换为代码的(有些优化)副本。这已经带来了速度优势,例如可以省略程序计数器操作。但还有更聪明的变体。
例如,跟踪JIT开始作为常规解释器,并额外观察它们执行的程序。如果他们注意到程序在特定代码部分(几乎总是循环或从循环调用的函数)花费了大量时间,它开始记录它在此期间所做的内容 - 生成一个跟踪。当它达到开始记录的点(经过一次循环后)时,就可以停止并将跟踪编译为机器代码。但是由于它看到了程序在运行时实际的行为方式,因此它可以生成完全符合此行为的代码。例如,考虑一个添加整数的循环。机器代码不会包含解释器实际执行的任何类型检查和函数调用。至少,它不会包含大多数检查。为确保正确性,它将添加检查以确保记录跟踪的条件(例如涉及的变量为整数)仍然成立。当这样的检查失败时,它会退出并恢复解释器,直到记录另一个跟踪为止。但在发生这种情况之前,它可以以与手写C代码相媲美的速度执行一百次迭代。

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