Lua执行字节码的过程介绍(2)

1 void luaV_execute (lua_State *L, int nexeccalls) { 2 LClosure *cl; 3 StkId base; 4 TValue *k; 5 const Instruction *pc; 6 reentry: /* entry point */ 7 lua_assert(isLua(L->ci)); 8 pc = L->savedpc; 9 cl = &clvalue(L->ci->func)->l; 10 base = L->base; 11 k = cl->p->k; 12 //... ...

L->savedpc为字节码数组的指针,因此pc保存了当前要执行字节码的下标,clvalue萃取出当前要执行的lua function对应的closure,k指向了当前function的常量数组。

下面先来看看vm解释loadk01字节码的过程。

1 /* main loop of interpreter */ 2 for (;;) { 3 const Instruction i = *pc++; 4 StkId ra; 5 //... ... 6 ra = RA(i); 7 //... ... 8 switch (GET_OPCODE(i)) { 9 //... ... 10 case OP_LOADK: { 11 setobj2s(L, ra, KBx(i)); 12 continue; 13 } 14 //... ...

第3行i保存了当前要执行的字节码,同时pc指向下一条字节码,第6行ra保存了通过宏RA萃取出的字节码中的a部分并与function stack的base相加得出的stack中的值;第8行Get_OPCODE宏萃取出字节码i的类型,结果是OP_LOADK,因此调用了setobj2s函数,其中KBx宏萃取出字节码i的bx部分并与function的常量数组地址相加得出的常量值,这里ra指向了function stack中相应的位置,KBx(i)部分指向了当前function中常量数组中存放的常量“bar”。

1 /* from stack to (same) stack */ 2 #define setobjs2s setobj 3 /* to stack (not from same stack) */ 4 #define setobj2s setobj 5 6 #define setobj(L,obj1,obj2) \ 7 { const TValue *o2=(obj2); TValue *o1=(obj1); \ 8 o1->value = o2->value; o1->tt=o2->tt; \ 9 checkliveness(G(L),o1); }

obj1为ra,obj2为KBx结果。可以看到第7行将这两个值转换为了TValue,并将o2的value设为o1的value,o2的值的类型设为o1的类型,效果上完成了将“bar”的值存放在了function stack上。接着又返回到上面的主循环处读取下一个字节码并执行,下一个要执行的字节码为setglobal00.

1 switch (GET_OPCODE(i)) { 2 //... ... 3 case OP_SETGLOBAL: { 4 TValue g; 5 sethvalue(L, &g, cl->env); 6 lua_assert(ttisstring(KBx(i))); 7 Protect(luaV_settable(L, &g, KBx(i), ra)); 8 continue; 9 } 10 //... ...

首先第5行中,cl->env为当前function的环境,函数sethvalue将其传给了g,KBx(i)指向了function常量数组中的值,ra为stack中的值,这里为前一条字节码loadk保存在stack中的“bar”。

1 void luaV_settable (lua_State *L, const TValue *t, TValue *key, StkId val) { 2 int loop; 3 TValue temp; 4 for (loop = 0; loop < MAXTAGLOOP; loop++) { 5 const TValue *tm; 6 if (ttistable(t)) { /* `t' is a table? */ 7 Table *h = hvalue(t); 8 TValue *oldval = luaH_set(L, h, key); /* do a primitive set */ 9 if (!ttisnil(oldval) || /* result is no nil? */ 10 (tm = fasttm(L, h->metatable, TM_NEWINDEX)) == NULL) { /* or no TM? */ 11 setobj2t(L, oldval, val); 12 h->flags = 0; 13 luaC_barriert(L, h, val); 14 return; 15 } 16 //... ... 17 }

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/d702bc209ba3b84e32a8a5e32c509e70.html