Lua解释器构建:从虚拟机到编译器
上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人

1.1.2 Lua解释器的运行机制

上一节介绍了Lua解释器的整体架构,并且在比较抽象的层面上,介绍了它的运作机制。本节会详细论述Lua解释器的整体运行机制。读者已经知道:Lua解释器由编译器和虚拟机两个部分组成;脚本代码,在经过编译器编译之后,会得到一系列的字节码,它们会被存放到一个Proto结构中。

这里需要对字节码进行解释,字节码是一种能够被虚拟机识别的中间代码。一些解释型语言,能够通过它们的编译器将源代码编译成字节码,再交给虚拟机去执行。和机器码不同,它不能直接被CPU识别和执行,而需要借助虚拟机。只要虚拟机程序能够在不同架构的CPU上运行,那么同一份字节码,就能在这些不同架构的CPU上运行。字节码的名称来自其指令的组织形式。一般来说,一个字节码指令是由1字节的操作码(opcode)和若干个可选操作参数组成(如图1-9所示)。一般来说,字节码指令就是虚拟机中定义的指令。

·图1-9

如图1-10所示,Lua解释器的内置编译器会将脚本编译成类似这种形式的指令,也就是虚拟机指令(后文统称为指令)。前文所述的Proto结构,有一个指令列表(code列表),这个列表会用来存放编译好的指令。指令列表的最后一个指令通常是RETURN指令,代表程序结束。

·图1-10

在Lua-5.3.5中,编译脚本源码,并将指令存入Proto结构是通过luaL_loadfile函数来进行的。这步操作完之后,脚本代码并不会立即被执行,而需要调用lua_pcall函数来执行Proto里的指令。lua_pcall函数会调用Lua虚拟机的入口函数,进入到这个函数之后,Lua虚拟机会将Proto指令列表中的指令,逐个取出来并执行。虚拟机内执行的伪代码,如下所示。

Proto结构的code列表,最后一般都是RETURN指令,这是编译器自动加上去的,它要确保程序最终能够被终止。当然,虚拟机的指令执行函数不会这么简单,这里只是为了给读者建立一个整体的概念,理解它大体的运行流程。