Skip to content

虚拟机架构 ​

虚拟机(VM)执行 Lua 代码,把源码转换成机器可以执行的操作,是 Lua 高效运行的核心部分。

1. 字节码 ​

字节码是 Lua 代码的中间表示,介于源代码和机器码之间,供虚拟机解释执行。源代码在执行时先被编译成字节码,编译经过词法分析、语法分析和代码生成三个阶段。字节码指令集由一组简洁的指令组成,每条指令对应一种操作,便于虚拟机快速解析和执行。

2. 虚拟机执行器 ​

执行器读取并执行字节码指令,是 Lua 运行时的核心。主循环在 lvm.c 的 luaV_execute 中:读取指令、解码、执行操作,并处理相关的数据。Lua 的虚拟机基于寄存器,指令直接以寄存器编号读写操作数,寄存器实际是从 Lua 栈中为当前函数划分出来的一组槽位。

3. 堆栈管理 ​

栈是执行函数调用、局部变量和表达式计算的关键数据结构。每次函数调用都在栈上分配一段连续的槽位作为自己的“寄存器”,字节码指令通过寄存器编号获取和存储操作数,而不是像 JVM 那样反复压栈、弹栈,因此指令数更少、分支预测更友好。每个函数调用还对应一个调用信息结构(CallInfo),记录函数的参数、局部变量所在的寄存器区间以及返回地址。

4. 内存管理 ​

虚拟机内置垃圾回收机制自动管理内存。Lua 默认使用增量式标记-清除算法(5.4 也可切换到分代模式),定期扫描内存,标记活跃对象并清除不再使用的对象。创建虚拟机时通过 lua_newstate 注册一个统一的分配函数(lua_Alloc),所有对象的分配与释放都经由它完成,默认实现基于 realloc,并不使用预分配的内存池。

5. 调用机制 ​

每次函数调用时,虚拟机创建一个新栈帧压入调用栈,函数返回时弹出栈帧、恢复到调用点,嵌套调用和递归调用都走这条路径。参数通过堆栈传递,调用和返回时由虚拟机处理参数传递和返回值。

6. 调试和扩展 ​

调试接口配合调试库和工具进行调试和分析。C API 允许用 C 语言编写扩展,修改虚拟机行为,或与 Lua 进行交互。

总结 ​

字节码作为中间表示、基于寄存器的栈管理、统一的分配函数、栈帧式的调用机制,这套设计以性能和简洁性为目标;调试接口和 C API 则把扩展能力留给了宿主程序。

Hello Lua