探索Lua5.2内部实现:虚拟机指令(8) LOOP
原文
Lua5.2种除了for循环之外,其他的各种循环都使用关系和逻辑指令,配合JMP指令来完成。
name args desc OP_FORLOOPA sBxR(A)+=R(A+2);
if R(A) <?= R(A+1) then { pc+=sBx; R(A+3)=R(A) }OP_FORPREPA sBxR(A)-=R(A+2); pc+=sBxname args desc OP_TFORCALLA CR(A+3), ... ,R(A+2+C) := R(A)(R(A+1), R(A+2));OP_TFORLOOPA sBxif R(A+1) ~= nil then { R(A)=R(A+1); pc += sBx }main <test.lua:0,0> (8 instructions at 0x80048eb0)0+ params, 6 slots, 1 upvalue, 5 locals, 4 constants, 0 functions 1 [1] LOADK 0 -1 ; 1 2 [1] LOADK 1 -2 ; 2 3 [1] LOADK 2 -3 ; 3 4 [1] JMP 0 1 ; to 6 5 [2] SETTABUP 0 -4 -1 ; _ENV "a" 1 6 [1] TFORCALL 0 2 7 [1] TFORLOOP 2 -3 ; to 5 8 [3] RETURN 0 1constants (4) for 0x80048eb0: 1 1 2 2 3 3 4 "a"locals (5) for 0x80048eb0: 0 (for generator) 4 8 1 (for state) 4 8 2 (for control) 4 8 3 i 5 6 4 v 5 6upvalues (1) for 0x80048eb0: 0 _ENV 1 0Generic for loop内部也使用了3个局部变量来控制循环,分别是"for generator”,“for state”和“for control”。for generator用来存放迭代使用的closure,每次迭代都会调用这个closure。for state和for control用于存放传给for generator的两个参数。Generic for loop还使用自定义的局部变量i,v,用来存储for generator的返回值。
上例中1~3行使用in后面的表达式列表(1,2,3)初始化3个内部使用的局部变量。第四行JMP调转到第六行。TFORCALL教用寄存器0(for generator)中的closure,传入for state和for control,并将结果返回给自定义局部变量列表i和v。第七行调用TFORLOOP进行循环条件判断,判断i是否为空。如果不为空,将i的值赋给for control,然后跳转到第五行,进行循环。