lua解释执行脚本流程

 1 #include "lua.hpp"
 2 
 3 #include <iostream>
 4 using namespace std;
 5 
 6 #pragma comment(lib, "lua5.1.lib")
 7 
 8 struct lua_guard{
 9     lua_State *pL;
10     lua_guard(lua_State *s) :pL(s){}
11     ~lua_guard(){ lua_close(pL); }
12 };
13 
14 int main(){
15     lua_guard g(lua_open());
16     luaL_openlibs(g.pL);
17     int err;
18     if ((err = luaL_dofile(g.pL, "mylua.lua") != 0)){
19         throw runtime_error("open lua file error");
20     }
21     system("pause");
22     return 0;
23 }

首先利用lua提供的函数luaL_dofile来执行一个lua脚本。

可以看到有两个过程,首先luaL_loadfile函数将lua文件加载进来然后进行词法语法语义分析,得到一个closure函数放入栈中,接着调用lua_pcall函数来执行栈顶的closure。

我们先来看看第一个过程:

首先在luaL_loadfile中真正加载lua文件的是lua_load函数

在lua_load中调用了luaD_protectedparser来进行parse过程

在luaD_protectedparser中又调用了f_parser

在f_parser中根据一些选择来分别处理不同的情况,我们示例中会跑到luaY_parser函数中去,在luaY_parser中会调用luaX_next进行分析,这个函数会首先读取源文件中的第一个token

最后在luaX_next中调用了llex,llex是真正切出token的例程

在读取了第一个token后luaX_next返回,相关的词法信息保存在了lexstate中,接着luaY_parser调用chunk函数来递归的生成一个chunk块

在chunk中循环读取下一个token并根据token的类型一层一层的递归的生成chunk,将chunks根据层次组合成tree,位于root的是最外层chunk

在分析完lua脚本后会返回到f_parser,在f_parser中接着调用luaF_newLclosure来将分析结果包裹成一个closure然后push到lua栈中

接下来分析第二个过程:

当第一个过程完成后lua栈顶存放着一个closure,luaL_dofile中调用lua_pcall让其来调用这个closure:

在lua_pcall中调用了f_call

f_call中又接着调用了luaD_call,传入了被调用的closure和参数个数

最后在luaD_call中调用了luaV_execute来执行closure中的opcode

luaV_execute既是lua虚拟机执行opcode的函数,其中可以看到一个无限循环,利用switch (GET_OPCODE(i))来根据不同的opcode进行不同的过程

  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   /* main loop of interpreter */
 13   for (;;) {
 14     const Instruction i = *pc++;
 15     StkId ra;
 16     if ((L->hookmask & (LUA_MASKLINE | LUA_MASKCOUNT)) &&
 17         (--L->hookcount == 0 || L->hookmask & LUA_MASKLINE)) {
 18       traceexec(L, pc);
 19       if (L->status == LUA_YIELD) {  /* did hook yield? */
 20         L->savedpc = pc - 1;
 21         return;
 22       }
 23       base = L->base;
 24     }
 25     /* warning!! several calls may realloc the stack and invalidate `ra' */
 26     ra = RA(i);
 27     lua_assert(base == L->base && L->base == L->ci->base);
 28     lua_assert(base <= L->top && L->top <= L->stack + L->stacksize);
 29     lua_assert(L->top == L->ci->top || luaG_checkopenop(i));
 30     switch (GET_OPCODE(i)) {
 31       case OP_MOVE: {
 32         setobjs2s(L, ra, RB(i));
 33         continue;
 34       }
 35       case OP_LOADK: {
 36         setobj2s(L, ra, KBx(i));
 37         continue;
 38       }
 39       case OP_LOADBOOL: {
 40         setbvalue(ra, GETARG_B(i));
 41         if (GETARG_C(i)) pc++;  /* skip next instruction (if C) */
 42         continue;
 43       }
 44       case OP_LOADNIL: {
 45         TValue *rb = RB(i);
 46         do {
 47           setnilvalue(rb--);
 48         } while (rb >= ra);
 49         continue;
 50       }
 51       case OP_GETUPVAL: {
 52         int b = GETARG_B(i);
 53         setobj2s(L, ra, cl->upvals[b]->v);
 54         continue;
 55       }
 56       case OP_GETGLOBAL: {
 57         TValue g;
 58         TValue *rb = KBx(i);
 59         sethvalue(L, &g, cl->env);
 60         lua_assert(ttisstring(rb));
 61         Protect(luaV_gettable(L, &g, rb, ra));
 62         continue;
 63       }
 64       case OP_GETTABLE: {
 65         Protect(luaV_gettable(L, RB(i), RKC(i), ra));
 66         continue;
 67       }
 68       case OP_SETGLOBAL: {
 69         TValue g;
 70         sethvalue(L, &g, cl->env);
 71         lua_assert(ttisstring(KBx(i)));
 72         Protect(luaV_settable(L, &g, KBx(i), ra));
 73         continue;
 74       }
 75       case OP_SETUPVAL: {
 76         UpVal *uv = cl->upvals[GETARG_B(i)];
 77         setobj(L, uv->v, ra);
 78         luaC_barrier(L, uv, ra);
 79         continue;
 80       }
 81       case OP_SETTABLE: {
 82         Protect(luaV_settable(L, ra, RKB(i), RKC(i)));
 83         continue;
 84       }
 85       case OP_NEWTABLE: {
 86         int b = GETARG_B(i);
 87         int c = GETARG_C(i);
 88         sethvalue(L, ra, luaH_new(L, luaO_fb2int(b), luaO_fb2int(c)));
 89         Protect(luaC_checkGC(L));
 90         continue;
 91       }
 92       case OP_SELF: {
 93         StkId rb = RB(i);
 94         setobjs2s(L, ra+1, rb);
 95         Protect(luaV_gettable(L, rb, RKC(i), ra));
 96         continue;
 97       }
 98       case OP_ADD: {
 99         arith_op(luai_numadd, TM_ADD);
100         continue;
101       }
102       case OP_SUB: {
103         arith_op(luai_numsub, TM_SUB);
104         continue;
105       }
106       case OP_MUL: {
107         arith_op(luai_nummul, TM_MUL);
108         continue;
109       }
110       case OP_DIV: {
111         arith_op(luai_numdiv, TM_DIV);
112         continue;
113       }
114       case OP_MOD: {
115         arith_op(luai_nummod, TM_MOD);
116         continue;
117       }
118       case OP_POW: {
119         arith_op(luai_numpow, TM_POW);
120         continue;
121       }
122       case OP_UNM: {
123         TValue *rb = RB(i);
124         if (ttisnumber(rb)) {
125           lua_Number nb = nvalue(rb);
126           setnvalue(ra, luai_numunm(nb));
127         }
128         else {
129           Protect(Arith(L, ra, rb, rb, TM_UNM));
130         }
131         continue;
132       }
133       case OP_NOT: {
134         int res = l_isfalse(RB(i));  /* next assignment may change this value */
135         setbvalue(ra, res);
136         continue;
137       }
138       case OP_LEN: {
139         const TValue *rb = RB(i);
140         switch (ttype(rb)) {
141           case LUA_TTABLE: {
142             setnvalue(ra, cast_num(luaH_getn(hvalue(rb))));
143             break;
144           }
145           case LUA_TSTRING: {
146             setnvalue(ra, cast_num(tsvalue(rb)->len));
147             break;
148           }
149           default: {  /* try metamethod */
150             Protect(
151               if (!call_binTM(L, rb, luaO_nilobject, ra, TM_LEN))
152                 luaG_typeerror(L, rb, "get length of");
153             )
154           }
155         }
156         continue;
157       }
158       case OP_CONCAT: {
159         int b = GETARG_B(i);
160         int c = GETARG_C(i);
161         Protect(luaV_concat(L, c-b+1, c); luaC_checkGC(L));
162         setobjs2s(L, RA(i), base+b);
163         continue;
164       }
165       case OP_JMP: {
166         dojump(L, pc, GETARG_sBx(i));
167         continue;
168       }
169       case OP_EQ: {
170         TValue *rb = RKB(i);
171         TValue *rc = RKC(i);
172         Protect(
173           if (equalobj(L, rb, rc) == GETARG_A(i))
174             dojump(L, pc, GETARG_sBx(*pc));
175         )
176         pc++;
177         continue;
178       }
179       case OP_LT: {
180         Protect(
181           if (luaV_lessthan(L, RKB(i), RKC(i)) == GETARG_A(i))
182             dojump(L, pc, GETARG_sBx(*pc));
183         )
184         pc++;
185         continue;
186       }
187       case OP_LE: {
188         Protect(
189           if (lessequal(L, RKB(i), RKC(i)) == GETARG_A(i))
190             dojump(L, pc, GETARG_sBx(*pc));
191         )
192         pc++;
193         continue;
194       }
195       case OP_TEST: {
196         if (l_isfalse(ra) != GETARG_C(i))
197           dojump(L, pc, GETARG_sBx(*pc));
198         pc++;
199         continue;
200       }
201       case OP_TESTSET: {
202         TValue *rb = RB(i);
203         if (l_isfalse(rb) != GETARG_C(i)) {
204           setobjs2s(L, ra, rb);
205           dojump(L, pc, GETARG_sBx(*pc));
206         }
207         pc++;
208         continue;
209       }
210       case OP_CALL: {
211         int b = GETARG_B(i);
212         int nresults = GETARG_C(i) - 1;
213         if (b != 0) L->top = ra+b;  /* else previous instruction set top */
214         L->savedpc = pc;
215         switch (luaD_precall(L, ra, nresults)) {
216           case PCRLUA: {
217             nexeccalls++;
218             goto reentry;  /* restart luaV_execute over new Lua function */
219           }
220           case PCRC: {
221             /* it was a C function (`precall' called it); adjust results */
222             if (nresults >= 0) L->top = L->ci->top;
223             base = L->base;
224             continue;
225           }
226           default: {
227             return;  /* yield */
228           }
229         }
230       }
231       case OP_TAILCALL: {
232         int b = GETARG_B(i);
233         if (b != 0) L->top = ra+b;  /* else previous instruction set top */
234         L->savedpc = pc;
235         lua_assert(GETARG_C(i) - 1 == LUA_MULTRET);
236         switch (luaD_precall(L, ra, LUA_MULTRET)) {
237           case PCRLUA: {
238             /* tail call: put new frame in place of previous one */
239             CallInfo *ci = L->ci - 1;  /* previous frame */
240             int aux;
241             StkId func = ci->func;
242             StkId pfunc = (ci+1)->func;  /* previous function index */
243             if (L->openupval) luaF_close(L, ci->base);
244             L->base = ci->base = ci->func + ((ci+1)->base - pfunc);
245             for (aux = 0; pfunc+aux < L->top; aux++)  /* move frame down */
246               setobjs2s(L, func+aux, pfunc+aux);
247             ci->top = L->top = func+aux;  /* correct top */
248             lua_assert(L->top == L->base + clvalue(func)->l.p->maxstacksize);
249             ci->savedpc = L->savedpc;
250             ci->tailcalls++;  /* one more call lost */
251             L->ci--;  /* remove new frame */
252             goto reentry;
253           }
254           case PCRC: {  /* it was a C function (`precall' called it) */
255             base = L->base;
256             continue;
257           }
258           default: {
259             return;  /* yield */
260           }
261         }
262       }
263       case OP_RETURN: {
264         int b = GETARG_B(i);
265         if (b != 0) L->top = ra+b-1;
266         if (L->openupval) luaF_close(L, base);
267         L->savedpc = pc;
268         b = luaD_poscall(L, ra);
269         if (--nexeccalls == 0)  /* was previous function running `here'? */
270           return;  /* no: return */
271         else {  /* yes: continue its execution */
272           if (b) L->top = L->ci->top;
273           lua_assert(isLua(L->ci));
274           lua_assert(GET_OPCODE(*((L->ci)->savedpc - 1)) == OP_CALL);
275           goto reentry;
276         }
277       }
278       case OP_FORLOOP: {
279         lua_Number step = nvalue(ra+2);
280         lua_Number idx = luai_numadd(nvalue(ra), step); /* increment index */
281         lua_Number limit = nvalue(ra+1);
282         if (luai_numlt(0, step) ? luai_numle(idx, limit)
283                                 : luai_numle(limit, idx)) {
284           dojump(L, pc, GETARG_sBx(i));  /* jump back */
285           setnvalue(ra, idx);  /* update internal index... */
286           setnvalue(ra+3, idx);  /* ...and external index */
287         }
288         continue;
289       }
290       case OP_FORPREP: {
291         const TValue *init = ra;
292         const TValue *plimit = ra+1;
293         const TValue *pstep = ra+2;
294         L->savedpc = pc;  /* next steps may throw errors */
295         if (!tonumber(init, ra))
296           luaG_runerror(L, LUA_QL("for") " initial value must be a number");
297         else if (!tonumber(plimit, ra+1))
298           luaG_runerror(L, LUA_QL("for") " limit must be a number");
299         else if (!tonumber(pstep, ra+2))
300           luaG_runerror(L, LUA_QL("for") " step must be a number");
301         setnvalue(ra, luai_numsub(nvalue(ra), nvalue(pstep)));
302         dojump(L, pc, GETARG_sBx(i));
303         continue;
304       }
305       case OP_TFORLOOP: {
306         StkId cb = ra + 3;  /* call base */
307         setobjs2s(L, cb+2, ra+2);
308         setobjs2s(L, cb+1, ra+1);
309         setobjs2s(L, cb, ra);
310         L->top = cb+3;  /* func. + 2 args (state and index) */
311         Protect(luaD_call(L, cb, GETARG_C(i)));
312         L->top = L->ci->top;
313         cb = RA(i) + 3;  /* previous call may change the stack */
314         if (!ttisnil(cb)) {  /* continue loop? */
315           setobjs2s(L, cb-1, cb);  /* save control variable */
316           dojump(L, pc, GETARG_sBx(*pc));  /* jump back */
317         }
318         pc++;
319         continue;
320       }
321       case OP_SETLIST: {
322         int n = GETARG_B(i);
323         int c = GETARG_C(i);
324         int last;
325         Table *h;
326         if (n == 0) {
327           n = cast_int(L->top - ra) - 1;
328           L->top = L->ci->top;
329         }
330         if (c == 0) c = cast_int(*pc++);
331         runtime_check(L, ttistable(ra));
332         h = hvalue(ra);
333         last = ((c-1)*LFIELDS_PER_FLUSH) + n;
334         if (last > h->sizearray)  /* needs more space? */
335           luaH_resizearray(L, h, last);  /* pre-alloc it at once */
336         for (; n > 0; n--) {
337           TValue *val = ra+n;
338           setobj2t(L, luaH_setnum(L, h, last--), val);
339           luaC_barriert(L, h, val);
340         }
341         continue;
342       }
343       case OP_CLOSE: {
344         luaF_close(L, ra);
345         continue;
346       }
347       case OP_CLOSURE: {
348         Proto *p;
349         Closure *ncl;
350         int nup, j;
351         p = cl->p->p[GETARG_Bx(i)];
352         nup = p->nups;
353         ncl = luaF_newLclosure(L, nup, cl->env);
354         ncl->l.p = p;
355         for (j=0; j<nup; j++, pc++) {
356           if (GET_OPCODE(*pc) == OP_GETUPVAL)
357             ncl->l.upvals[j] = cl->upvals[GETARG_B(*pc)];
358           else {
359             lua_assert(GET_OPCODE(*pc) == OP_MOVE);
360             ncl->l.upvals[j] = luaF_findupval(L, base + GETARG_B(*pc));
361           }
362         }
363         setclvalue(L, ra, ncl);
364         Protect(luaC_checkGC(L));
365         continue;
366       }
367       case OP_VARARG: {
368         int b = GETARG_B(i) - 1;
369         int j;
370         CallInfo *ci = L->ci;
371         int n = cast_int(ci->base - ci->func) - cl->p->numparams - 1;
372         if (b == LUA_MULTRET) {
373           Protect(luaD_checkstack(L, n));
374           ra = RA(i);  /* previous call may change the stack */
375           b = n;
376           L->top = ra + n;
377         }
378         for (j = 0; j < b; j++) {
379           if (j < n) {
380             setobjs2s(L, ra + j, ci->base - n + j);
381           }
382           else {
383             setnilvalue(ra + j);
384           }
385         }
386         continue;
387       }
388     }
389   }
390 }

 

posted @ 2015-04-26 21:50  老司机  阅读(15092)  评论(0编辑  收藏  举报