lua虚拟机是固定长度指令格式,按参数不同分为4类enum OpMode {iABC, iABx, iAsBx, iAx}:
iABC: B:9 C:9 A:8 OP:6
iABx: Bx:18 A:8 OP:6
iAsBx: sBx:18 A:8 OP:6
iAx: Ax:26 OP:6
所有指令都有一个占6位的opcode
A:8位
B:9位
C:9位
Ax:26位
Bx:18位
sBx:有符号的Bx
虚拟机指令数据主要来源为
1,寄存器,基址为:base = ci->u.l.base;
2,常量表,基址位:cl->p->k;
3,upvalue,来自闭包cl = clLvalue(ci->func); /* local reference to function’s closure */
当前指令地址为ci->u.l.savedpc,每执行一条指令,对此计数器地址+1
每条指令执行前,寄存器A设置为R(A) = base+GETARG_A(i)
指令介绍:
OP_MOVE,/* A B R(A) := R(B) */
行为:setobjs2s(L, ra, RB(i));
其中RB(i) = base+GETARG_B(i)
即设置寄存器A的值为寄存器B的值
OP_LOADK,/* A Bx R(A) := Kst(Bx) */、
行为:setobj2s(L, ra, rb);
其中TValue *rb = k + GETARG_Bx(i);
即设置寄存器A的值为常量表中rb的值
OP_LOADKX,/* A R(A) := Kst(extra arg) */
行为:setobj2s(L, ra, rb);
其中TValue *rb = k + GETARG_Ax(*ci->u.l.savedpc++);
即设置寄存器A的值为常量表中rb的值
OP_LOADBOOL,/* A B C R(A) := (Bool)B; if (C) pc++ */
行为:
setbvalue(ra, GETARG_B(i));
if (GETARG_C(i)) ci->u.l.savedpc++; /* skip next instruction (if C) */
先把B的值设置到寄存器A中,如果C不是0的话则跳过下一条语句
OP_LOADNIL,/* A B R(A), R(A+1), …, R(A+B) := nil */
行为:
int b = GETARG_B(i);
do {
setnilvalue(ra++);
} while (b–);
把以A起始的连续b个寄存器设置为nil
OP_GETUPVAL,/* A B R(A) := UpValue[B] */
行为:
int b = GETARG_B(i);
setobj2s(L, ra, cl->upvals[b]->v);
设置寄存器A的值为当前闭包的upval[b]的值
OP_GETTABUP,/* A B C R(A) := UpValue[B][RK(C)] */
行为:
TValue *upval = cl->upvals[GETARG_B(i)]->v;
TValue *rc = RKC(i);
gettableProtected(L, upval, rc, ra);
首先cl->upvals[GETARG_B(i)]是一个table,把这个table的RKC(i)的值赋给寄存器A
OP_GETTABLE,/* A B C R(A) := R(B)[RK(C)] */
行为:
StkId rb = RB(i);
TValue *rc = RKC(i);
gettableProtected(L, rb, rc, ra);
RB(i)是一个table,把这个table的RKC(i)的值赋给寄存器A
OP_SETTABUP,/* A B C UpValue[A][RK(B)] := RK(C) */
OP_SETUPVAL,/* A B UpValue[B] := R(A) */
OP_SETTABLE,/* A B C R(A)[RK(B)] := RK(C) */
行为:
与上三个GET类似,设置函数
OP_NEWTABLE,/* A B C R(A) := {} (size = B,C) */
行为:
int b = GETARG_B(i);
int c = GETARG_C(i);
Table *t = luaH_new(L);
sethvalue(L, ra, t);
if (b != 0 || c != 0)
luaH_resize(L, t, luaO_fb2int(b), luaO_fb2int(c));
checkGC(L, ra + 1);
创建一个table,并初始化其线性空间和哈希空间
OP_SELF,/* A B C R(A+1) := R(B); R(A) := R(B)[RK(C)] */
行为:
const TValue *aux;
StkId rb = RB(i);
TValue *rc = RKC(i);
TString key = tsvalue(rc); / key must be a string */
setobjs2s(L, ra + 1, rb);
if (luaV_fastget(L, rb, key, aux, luaH_getstr)) {
setobj2s(L, ra, aux);
}
else Protect(luaV_finishget(L, rb, rc, ra, aux));
为执行self调用做参数准备R(A+1) := R(B); R(A) := R(B)[RK(C)]
OP_ADD,/* A B C R(A) := RK(B) + RK(C) */
OP_SUB,/* A B C R(A) := RK(B) - RK(C) */
OP_MUL,/* A B C R(A) := RK(B) * RK(C) */
OP_MOD,/* A B C R(A) := RK(B) % RK(C) */
OP_POW,/* A B C R(A) := RK(B) ^ RK(C) */
OP_DIV,/* A B C R(A) := RK(B) / RK(C) */
OP_IDIV,/* A B C R(A) := RK(B) // RK(C) */
OP_BAND,/* A B C R(A) := RK(B) & RK(C) */
OP_BOR,/* A B C R(A) := RK(B) | RK(C) */
OP_BXOR,/* A B C R(A) := RK(B) ~ RK(C) */
OP_SHL,/* A B C R(A) := RK(B) << RK(C) */
OP_SHR,/* A B C R(A) := RK(B) >> RK(C) */
OP_UNM,/* A B R(A) := -R(B) */
OP_BNOT,/* A B R(A) := ~R(B) */
OP_NOT,/* A B R(A) := not R(B) */
OP_LEN,/* A B R(A) := length of R(B) */
行为:
逻辑运算,主要完成参数检查和转换,并完成运算,表示时会调用metatable中的函数
OP_CONCAT,/* A B C R(A) := R(B).. … ..R(C) */
行为:
将寄存器B到C直接的数,当做字符串做连接操作,然后赋给寄存器A
OP_JMP,/* A sBx pc+=sBx; if (A) close all upvalues >= R(A - 1) */
行为:
dojump(ci, i, 0);
跳转指令,直接修改程序计数器的值,并关闭闭包上的upvalues
OP_EQ,/* A B C if ((RK(B) == RK(C)) ~= A) then pc++ */
行为:
TValue *rb = RKB(i);
TValue *rc = RKC(i);
Protect(
if (luaV_equalobj(L, rb, rc) != GETARG_A(i))
ci->u.l.savedpc++;
else
donextjump(ci);
)
如果 ((RK(B) == RK(C)) ~= A) 则跳过跳转指令:pc++,否则执行跳转
OP_LT,/* A B C if ((RK(B) < RK(C)) ~= A) then pc++ */
行为:
Protect(
if (luaV_lessthan(L, RKB(i), RKC(i)) != GETARG_A(i))
ci->u.l.savedpc++;
else
donextjump(ci);
)
如果 ((RK(B) < RK(C)) ~= A) 则跳过跳转指令:pc++,否则执行跳转
OP_LE,/* A B C if ((RK(B) <= RK(C)) ~= A) then pc++ */
行为:
Protect(
if (luaV_lessequal(L, RKB(i), RKC(i)) != GETARG_A(i))
ci->u.l.savedpc++;
else
donextjump(ci);
)
如果 ((RK(B) <= RK(C)) ~= A) 则跳过跳转指令:pc++,否则执行跳转
OP_TEST,/* A C if not (R(A) <=> C) then pc++ */
行为:
if (GETARG_C(i) ? l_isfalse(ra) : !l_isfalse(ra))
ci->u.l.savedpc++;
else
donextjump(ci);
如果 not (R(A) <=> C) 则跳过跳转指令:pc++,否则执行跳转
OP_TESTSET,/* A B C if (R(B) <=> C) then R(A) := R(B) else pc++ */
行为:
TValue *rb = RB(i);
if (GETARG_C(i) ? l_isfalse(rb) : !l_isfalse(rb))
ci->u.l.savedpc++;
else {
setobjs2s(L, ra, rb);
donextjump(ci);
}
如果 not (R(B) <=> C) 则设置R(A)=R(B),然后执行跳转,否则跳过跳转指令
OP_CALL,/* A B C R(A), … ,R(A+C-2) := R(A)(R(A+1), … ,R(A+B-1)) */
行为:函数调用指令
OP_TAILCALL,/* A B C return R(A)(R(A+1), … ,R(A+B-1)) */
行为:尾调用指令
OP_RETURN,/* A B return R(A), … ,R(A+B-2) (see note) */
行为:函数返回指令
OP_FORLOOP,/* A sBx R(A)+=R(A+2);
if R(A)