0x1. 虚拟机原理
lua的虚拟机执行基于函数栈,所有的临时访问存储都基于栈,函数间的参数传递也是。在lua的官方说明里叫做寄存器。前面也提到过虚拟机的指令里面保存的是寄存器索引。
为了方便阐述栈虚拟机原理,这里以下面这段代码为例子来进行阐述,下面这段代码本身没有什么作用,只是为了方便阐述。这里有两个函数,分别为parent,clild。parent会调用chilld,并把返回值放到psum。这里之所以要有psum = psum + 1是为了防止被lua优化成尾调用。
function clild(num1, num2)local csum = num1 + num2return csumendfunction parent()local p1 = 1local p2 = 1local psum = clild(p1, p2)psum = psum + 1end--编译结果:函数clildfunction <test.lua:1,4> (3 instructions, 12 bytes at 0x55ece9ff5a50)2 params, 3 slots, 0 upvalues, 3 locals, 0 constants, 0 functions1 [2] ADD 2 0 12 [3] RETURN 2 23 [4] RETURN 0 1constants (0) for 0x55ece9ff5a50:locals (3) for 0x55ece9ff5a50:0 num1 1 31 num2 1 32 csum 2 3upvalues (0) for 0x55ece9ff5a50:函数parentfunction <test.lua:6,11> (8 instructions, 32 bytes at 0x55ece9ff5f10)0 params, 5 slots, 0 upvalues, 3 locals, 2 constants, 0 functions1 [7] LOADK 0 -1 ; 12 [8] LOADK 1 -1 ; 13 [9] GETGLOBAL 2 -2 ; clild4 [9] MOVE 3 05 [9] MOVE 4 16 [9] CALL 2 3 27 [10] ADD 2 2 -1 ; - 18 [11] RETURN 0 1constants (2) for 0x55ece9ff5f10:1 12 "clild"locals (3) for 0x55ece9ff5f10:0 p1 2 81 p2 3 82 psum 7 8upvalues (0) for 0x55ece9ff5f10:--
函数栈
lua栈或者称为lua的寄存器,是由TValue组成的数组。TValue是lua用于保存数据的数据结构。
下面这个过程是parent调用clild时栈的变化情况。
- 调用方将
Closure,函数参数放到栈中 - 调用
Call指令执行被调用函数 - 被调用函数执行完成后将返回值放到以
Closure为起始地址的地方。如果有多个参数,则按顺序存放。

数据结构
lua中栈的回溯没有完全放到栈帧中,而是由专门的结构CallInfo来保存。这个结构保存了栈帧恢复所需要的所有信息。而lua_state中的base/top始终指向当前正在执行的栈帧。

