diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2002-08-07 16:22:39 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2002-08-07 16:22:39 -0300 |
commit | 5016f43aa439662ca35a5d78e820c617c517f60a (patch) | |
tree | 167aabeccb5a2307c3de7d20542ecf7d99769d3c | |
parent | c1c100a0c04bc77623b32269f37df49e7a2457d2 (diff) | |
download | lua-5016f43aa439662ca35a5d78e820c617c517f60a.tar.gz lua-5016f43aa439662ca35a5d78e820c617c517f60a.tar.bz2 lua-5016f43aa439662ca35a5d78e820c617c517f60a.zip |
(much) cleaner way to control function states
-rw-r--r-- | ldebug.c | 14 | ||||
-rw-r--r-- | ldo.c | 16 | ||||
-rw-r--r-- | lstate.c | 4 | ||||
-rw-r--r-- | lstate.h | 16 | ||||
-rw-r--r-- | lvm.c | 37 | ||||
-rw-r--r-- | lvm.h | 9 |
6 files changed, 54 insertions, 42 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: ldebug.c,v 1.128 2002/08/06 18:01:50 roberto Exp roberto $ | 2 | ** $Id: ldebug.c,v 1.129 2002/08/07 14:35:55 roberto Exp roberto $ |
3 | ** Debug Interface | 3 | ** Debug Interface |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -28,14 +28,16 @@ | |||
28 | static const char *getfuncname (CallInfo *ci, const char **name); | 28 | static const char *getfuncname (CallInfo *ci, const char **name); |
29 | 29 | ||
30 | 30 | ||
31 | static int isLua (CallInfo *ci) { | 31 | #define isLua(ci) (!((ci)->state & CI_C)) |
32 | return isLfunction (ci->base - 1); | 32 | |
33 | } | ||
34 | 33 | ||
35 | static int currentpc (CallInfo *ci) { | 34 | static int currentpc (CallInfo *ci) { |
36 | if (!isLua(ci)) return -1; /* function is not a Lua function? */ | 35 | if (!isLua(ci)) return -1; /* function is not a Lua function? */ |
37 | if (ci->pc != &luaV_callingmark) /* is not calling another Lua function? */ | 36 | if (!(ci->state & CI_SAVEDPC)) { /* savedpc outdated? */ |
38 | ci->u.l.savedpc = *ci->pc; /* `pc' may not be saved; save it */ | 37 | lua_assert(ci->state & CI_HASFRAME); |
38 | ci->u.l.savedpc = *ci->u.l.pc; | ||
39 | ci->state |= CI_SAVEDPC; | ||
40 | } | ||
39 | /* function's pc is saved */ | 41 | /* function's pc is saved */ |
40 | return pcRel(ci->u.l.savedpc, ci_func(ci)->l.p); | 42 | return pcRel(ci->u.l.savedpc, ci_func(ci)->l.p); |
41 | } | 43 | } |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: ldo.c,v 1.189 2002/08/05 17:36:24 roberto Exp roberto $ | 2 | ** $Id: ldo.c,v 1.190 2002/08/06 15:32:22 roberto Exp roberto $ |
3 | ** Stack and Call structure of Lua | 3 | ** Stack and Call structure of Lua |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -108,7 +108,7 @@ static void correctstack (lua_State *L, TObject *oldstack) { | |||
108 | for (ci = L->base_ci; ci <= L->ci; ci++) { | 108 | for (ci = L->base_ci; ci <= L->ci; ci++) { |
109 | ci->base = (ci->base - oldstack) + L->stack; | 109 | ci->base = (ci->base - oldstack) + L->stack; |
110 | ci->top = (ci->top - oldstack) + L->stack; | 110 | ci->top = (ci->top - oldstack) + L->stack; |
111 | if (ci->pc && ci->pc != &luaV_callingmark) /* function has a frame? */ | 111 | if (ci->state & CI_HASFRAME) /* Lua function with active frame? */ |
112 | *ci->u.l.pb = (*ci->u.l.pb - oldstack) + L->stack; /* correct frame */ | 112 | *ci->u.l.pb = (*ci->u.l.pb - oldstack) + L->stack; /* correct frame */ |
113 | } | 113 | } |
114 | } | 114 | } |
@@ -229,6 +229,7 @@ StkId luaD_precall (lua_State *L, StkId func) { | |||
229 | ci->base = restorestack(L, funcr) + 1; | 229 | ci->base = restorestack(L, funcr) + 1; |
230 | ci->top = ci->base + p->maxstacksize; | 230 | ci->top = ci->base + p->maxstacksize; |
231 | ci->u.l.savedpc = p->code; /* starting point */ | 231 | ci->u.l.savedpc = p->code; /* starting point */ |
232 | ci->state = CI_SAVEDPC; | ||
232 | while (L->top < ci->top) | 233 | while (L->top < ci->top) |
233 | setnilvalue(L->top++); | 234 | setnilvalue(L->top++); |
234 | L->top = ci->top; | 235 | L->top = ci->top; |
@@ -241,7 +242,7 @@ StkId luaD_precall (lua_State *L, StkId func) { | |||
241 | ci = ++L->ci; /* now `enter' new function */ | 242 | ci = ++L->ci; /* now `enter' new function */ |
242 | ci->base = restorestack(L, funcr) + 1; | 243 | ci->base = restorestack(L, funcr) + 1; |
243 | ci->top = L->top + LUA_MINSTACK; | 244 | ci->top = L->top + LUA_MINSTACK; |
244 | ci->pc = NULL; /* not a Lua function */ | 245 | ci->state = CI_C; /* a C function */ |
245 | if (L->hookmask & LUA_MASKCALL) { | 246 | if (L->hookmask & LUA_MASKCALL) { |
246 | luaD_callhook(L, LUA_HOOKCALL, -1); | 247 | luaD_callhook(L, LUA_HOOKCALL, -1); |
247 | ci = L->ci; /* previous call may realocate `ci' */ | 248 | ci = L->ci; /* previous call may realocate `ci' */ |
@@ -300,7 +301,6 @@ void luaD_call (lua_State *L, StkId func, int nResults) { | |||
300 | LUA_API void lua_cobegin (lua_State *L, int nargs) { | 301 | LUA_API void lua_cobegin (lua_State *L, int nargs) { |
301 | lua_lock(L); | 302 | lua_lock(L); |
302 | luaD_precall(L, L->top - (nargs+1)); | 303 | luaD_precall(L, L->top - (nargs+1)); |
303 | L->ci->pc = &luaV_callingmark; /* function is not active (yet) */ | ||
304 | lua_unlock(L); | 304 | lua_unlock(L); |
305 | } | 305 | } |
306 | 306 | ||
@@ -317,10 +317,10 @@ static void move_results (lua_State *L, TObject *from, TObject *to) { | |||
317 | static void resume (lua_State *L, void *ud) { | 317 | static void resume (lua_State *L, void *ud) { |
318 | StkId firstResult; | 318 | StkId firstResult; |
319 | CallInfo *ci = L->ci; | 319 | CallInfo *ci = L->ci; |
320 | if (ci->pc == NULL) { /* not first time? */ | 320 | if (ci->state & CI_C) { /* not first time (i.e. inside a yield)? */ |
321 | /* finish interrupted execution of `OP_CALL' */ | 321 | /* finish interrupted execution of `OP_CALL' */ |
322 | int nresults; | 322 | int nresults; |
323 | lua_assert((ci - 1)->pc == &luaV_callingmark); | 323 | lua_assert((ci-1)->state & CI_SAVEDPC); |
324 | lua_assert(GET_OPCODE(*((ci-1)->u.l.savedpc - 1)) == OP_CALL || | 324 | lua_assert(GET_OPCODE(*((ci-1)->u.l.savedpc - 1)) == OP_CALL || |
325 | GET_OPCODE(*((ci-1)->u.l.savedpc - 1)) == OP_TAILCALL); | 325 | GET_OPCODE(*((ci-1)->u.l.savedpc - 1)) == OP_TAILCALL); |
326 | nresults = GETARG_C(*((ci-1)->u.l.savedpc - 1)) - 1; | 326 | nresults = GETARG_C(*((ci-1)->u.l.savedpc - 1)) - 1; |
@@ -363,9 +363,9 @@ LUA_API int lua_yield (lua_State *L, int nresults) { | |||
363 | CallInfo *ci; | 363 | CallInfo *ci; |
364 | lua_lock(L); | 364 | lua_lock(L); |
365 | ci = L->ci; | 365 | ci = L->ci; |
366 | if ((ci-1)->pc == NULL) | 366 | if ((ci-1)->state & CI_C) |
367 | luaG_runerror(L, "cannot yield a C function"); | 367 | luaG_runerror(L, "cannot yield a C function"); |
368 | lua_assert(ci->pc == NULL); /* current function is not Lua */ | 368 | lua_assert(ci->state & CI_C); /* current function is not Lua */ |
369 | ci->u.c.yield_results = nresults; | 369 | ci->u.c.yield_results = nresults; |
370 | lua_unlock(L); | 370 | lua_unlock(L); |
371 | return -1; | 371 | return -1; |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lstate.c,v 1.101 2002/08/05 18:45:45 roberto Exp roberto $ | 2 | ** $Id: lstate.c,v 1.102 2002/08/06 15:32:22 roberto Exp roberto $ |
3 | ** Global State | 3 | ** Global State |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -41,7 +41,7 @@ static void stack_init (lua_State *L, lua_State *OL) { | |||
41 | L->stack_last = L->stack+(L->stacksize - EXTRA_STACK)-1; | 41 | L->stack_last = L->stack+(L->stacksize - EXTRA_STACK)-1; |
42 | L->base_ci = luaM_newvector(OL, BASIC_CI_SIZE, CallInfo); | 42 | L->base_ci = luaM_newvector(OL, BASIC_CI_SIZE, CallInfo); |
43 | L->ci = L->base_ci; | 43 | L->ci = L->base_ci; |
44 | L->ci->pc = NULL; /* not a Lua function */ | 44 | L->ci->state = CI_C; /* not a Lua function */ |
45 | setnilvalue(L->top++); /* `function' entry for this `ci' */ | 45 | setnilvalue(L->top++); /* `function' entry for this `ci' */ |
46 | L->ci->base = L->top; | 46 | L->ci->base = L->top; |
47 | L->ci->top = L->top + LUA_MINSTACK; | 47 | L->ci->top = L->top + LUA_MINSTACK; |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lstate.h,v 1.91 2002/08/06 15:32:22 roberto Exp roberto $ | 2 | ** $Id: lstate.h,v 1.92 2002/08/06 18:01:50 roberto Exp roberto $ |
3 | ** Global State | 3 | ** Global State |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -87,10 +87,11 @@ typedef struct stringtable { | |||
87 | typedef struct CallInfo { | 87 | typedef struct CallInfo { |
88 | StkId base; /* base for called function */ | 88 | StkId base; /* base for called function */ |
89 | StkId top; /* top for this function */ | 89 | StkId top; /* top for this function */ |
90 | const Instruction **pc; /* points to `pc' variable in `luaV_execute' */ | 90 | int state; /* bit fields; see below */ |
91 | union { | 91 | union { |
92 | struct { /* for Lua functions */ | 92 | struct { /* for Lua functions */ |
93 | const Instruction *savedpc; | 93 | const Instruction *savedpc; |
94 | const Instruction **pc; /* points to `pc' variable in `luaV_execute' */ | ||
94 | StkId *pb; /* points to `base' variable in `luaV_execute' */ | 95 | StkId *pb; /* points to `base' variable in `luaV_execute' */ |
95 | } l; | 96 | } l; |
96 | struct { /* for C functions */ | 97 | struct { /* for C functions */ |
@@ -100,6 +101,17 @@ typedef struct CallInfo { | |||
100 | } CallInfo; | 101 | } CallInfo; |
101 | 102 | ||
102 | 103 | ||
104 | /* | ||
105 | ** bit fields for `CallInfo.state' | ||
106 | */ | ||
107 | #define CI_C 1 /* 1 if function is a C function */ | ||
108 | /* 1 if (Lua) function has an active `luaV_execute' running it */ | ||
109 | #define CI_HASFRAME 2 | ||
110 | /* 1 if Lua function is calling another Lua function (and therefore its | ||
111 | `pc' is being used by the other, and therefore CI_SAVEDPC is 1 too) */ | ||
112 | #define CI_CALLING 4 | ||
113 | #define CI_SAVEDPC 8 /* 1 if `savedpc' is updated */ | ||
114 | |||
103 | 115 | ||
104 | #define ci_func(ci) (clvalue((ci)->base - 1)) | 116 | #define ci_func(ci) (clvalue((ci)->base - 1)) |
105 | 117 | ||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lvm.c,v 1.249 2002/08/05 17:36:24 roberto Exp roberto $ | 2 | ** $Id: lvm.c,v 1.250 2002/08/07 14:24:24 roberto Exp roberto $ |
3 | ** Lua virtual machine | 3 | ** Lua virtual machine |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -24,8 +24,6 @@ | |||
24 | #include "lvm.h" | 24 | #include "lvm.h" |
25 | 25 | ||
26 | 26 | ||
27 | Instruction const *luaV_callingmark = NULL; | ||
28 | |||
29 | 27 | ||
30 | /* function to convert a lua_Number to a string */ | 28 | /* function to convert a lua_Number to a string */ |
31 | #ifndef lua_number2str | 29 | #ifndef lua_number2str |
@@ -83,16 +81,18 @@ static void traceexec (lua_State *L) { | |||
83 | if (mask & LUA_MASKLINE) { | 81 | if (mask & LUA_MASKLINE) { |
84 | CallInfo *ci = L->ci; | 82 | CallInfo *ci = L->ci; |
85 | Proto *p = ci_func(ci)->l.p; | 83 | Proto *p = ci_func(ci)->l.p; |
86 | int newline = getline(p, pcRel(*ci->pc, p)); | 84 | int newline = getline(p, pcRel(*ci->u.l.pc, p)); |
87 | if (pcRel(*ci->pc, p) == 0) /* tracing may be starting now? */ | 85 | lua_assert(ci->state & CI_HASFRAME); |
88 | ci->u.l.savedpc = *ci->pc; /* initialize `savedpc' */ | 86 | if (pcRel(*ci->u.l.pc, p) == 0) /* tracing may be starting now? */ |
87 | ci->u.l.savedpc = *ci->u.l.pc; /* initialize `savedpc' */ | ||
89 | /* calls linehook when enters a new line or jumps back (loop) */ | 88 | /* calls linehook when enters a new line or jumps back (loop) */ |
90 | if (*ci->pc <= ci->u.l.savedpc || | 89 | if (*ci->u.l.pc <= ci->u.l.savedpc || |
91 | newline != getline(p, pcRel(ci->u.l.savedpc, p))) { | 90 | newline != getline(p, pcRel(ci->u.l.savedpc, p))) { |
92 | luaD_callhook(L, LUA_HOOKLINE, newline); | 91 | luaD_callhook(L, LUA_HOOKLINE, newline); |
93 | ci = L->ci; /* previous call may reallocate `ci' */ | 92 | ci = L->ci; /* previous call may reallocate `ci' */ |
94 | } | 93 | } |
95 | ci->u.l.savedpc = *ci->pc; | 94 | ci->u.l.savedpc = *ci->u.l.pc; |
95 | ci->state |= CI_SAVEDPC; /* `savedpc' is updated */ | ||
96 | } | 96 | } |
97 | } | 97 | } |
98 | 98 | ||
@@ -374,11 +374,13 @@ StkId luaV_execute (lua_State *L) { | |||
374 | const Instruction *pc; | 374 | const Instruction *pc; |
375 | callentry: /* entry point when calling new functions */ | 375 | callentry: /* entry point when calling new functions */ |
376 | L->ci->u.l.pb = &base; | 376 | L->ci->u.l.pb = &base; |
377 | L->ci->pc = &pc; | 377 | L->ci->u.l.pc = &pc; |
378 | pc = L->ci->u.l.savedpc; | ||
379 | if (L->hookmask & LUA_MASKCALL) | 378 | if (L->hookmask & LUA_MASKCALL) |
380 | luaD_callhook(L, LUA_HOOKCALL, -1); | 379 | luaD_callhook(L, LUA_HOOKCALL, -1); |
381 | retentry: /* entry point when returning to old functions */ | 380 | retentry: /* entry point when returning to old functions */ |
381 | lua_assert(L->ci->state & CI_SAVEDPC); | ||
382 | L->ci->state = CI_HASFRAME; /* activate frame */ | ||
383 | pc = L->ci->u.l.savedpc; | ||
382 | base = L->ci->base; | 384 | base = L->ci->base; |
383 | cl = &clvalue(base - 1)->l; | 385 | cl = &clvalue(base - 1)->l; |
384 | k = cl->p->k; | 386 | k = cl->p->k; |
@@ -599,7 +601,7 @@ StkId luaV_execute (lua_State *L) { | |||
599 | if (firstResult) { | 601 | if (firstResult) { |
600 | if (firstResult > L->top) { /* yield? */ | 602 | if (firstResult > L->top) { /* yield? */ |
601 | (L->ci - 1)->u.l.savedpc = pc; | 603 | (L->ci - 1)->u.l.savedpc = pc; |
602 | (L->ci - 1)->pc = &luaV_callingmark; | 604 | (L->ci - 1)->state = CI_SAVEDPC; |
603 | return NULL; | 605 | return NULL; |
604 | } | 606 | } |
605 | /* it was a C function (`precall' called it); adjust results */ | 607 | /* it was a C function (`precall' called it); adjust results */ |
@@ -609,7 +611,7 @@ StkId luaV_execute (lua_State *L) { | |||
609 | else { /* it is a Lua function */ | 611 | else { /* it is a Lua function */ |
610 | if (GET_OPCODE(i) == OP_CALL) { /* regular call? */ | 612 | if (GET_OPCODE(i) == OP_CALL) { /* regular call? */ |
611 | (L->ci-1)->u.l.savedpc = pc; /* save `pc' to return later */ | 613 | (L->ci-1)->u.l.savedpc = pc; /* save `pc' to return later */ |
612 | (L->ci-1)->pc = &luaV_callingmark; /* function is calling */ | 614 | (L->ci-1)->state = (CI_SAVEDPC | CI_CALLING); |
613 | } | 615 | } |
614 | else { /* tail call: put new frame in place of previous one */ | 616 | else { /* tail call: put new frame in place of previous one */ |
615 | int aux; | 617 | int aux; |
@@ -618,7 +620,9 @@ StkId luaV_execute (lua_State *L) { | |||
618 | for (aux = 0; ra1+aux < L->top; aux++) /* move frame down */ | 620 | for (aux = 0; ra1+aux < L->top; aux++) /* move frame down */ |
619 | setobj(base+aux-1, ra1+aux); | 621 | setobj(base+aux-1, ra1+aux); |
620 | (L->ci - 1)->top = L->top = base+aux; /* correct top */ | 622 | (L->ci - 1)->top = L->top = base+aux; /* correct top */ |
623 | lua_assert(L->ci->state & CI_SAVEDPC); | ||
621 | (L->ci - 1)->u.l.savedpc = L->ci->u.l.savedpc; | 624 | (L->ci - 1)->u.l.savedpc = L->ci->u.l.savedpc; |
625 | (L->ci - 1)->state = CI_SAVEDPC; | ||
622 | L->ci--; /* remove previous frame */ | 626 | L->ci--; /* remove previous frame */ |
623 | } | 627 | } |
624 | goto callentry; | 628 | goto callentry; |
@@ -629,20 +633,21 @@ StkId luaV_execute (lua_State *L) { | |||
629 | CallInfo *ci = L->ci - 1; | 633 | CallInfo *ci = L->ci - 1; |
630 | int b = GETARG_B(i); | 634 | int b = GETARG_B(i); |
631 | if (b != 0) L->top = ra+b-1; | 635 | if (b != 0) L->top = ra+b-1; |
632 | lua_assert(L->ci->pc == &pc); | 636 | lua_assert(L->ci->state & CI_HASFRAME); |
633 | if (L->openupval) luaF_close(L, base); | 637 | if (L->openupval) luaF_close(L, base); |
638 | L->ci->state = CI_SAVEDPC; /* deactivate current function */ | ||
639 | L->ci->u.l.savedpc = pc; | ||
634 | /* previous function was running `here'? */ | 640 | /* previous function was running `here'? */ |
635 | if (ci->pc != &luaV_callingmark) | 641 | if (!(ci->state & CI_CALLING)) |
636 | return ra; /* no: return */ | 642 | return ra; /* no: return */ |
637 | else { /* yes: continue its execution (go through) */ | 643 | else { /* yes: continue its execution (go through) */ |
638 | int nresults; | 644 | int nresults; |
639 | lua_assert(ttisfunction(ci->base - 1)); | 645 | lua_assert(ttisfunction(ci->base - 1)); |
646 | lua_assert(ci->state & CI_SAVEDPC); | ||
640 | lua_assert(GET_OPCODE(*(ci->u.l.savedpc - 1)) == OP_CALL); | 647 | lua_assert(GET_OPCODE(*(ci->u.l.savedpc - 1)) == OP_CALL); |
641 | nresults = GETARG_C(*(ci->u.l.savedpc - 1)) - 1; | 648 | nresults = GETARG_C(*(ci->u.l.savedpc - 1)) - 1; |
642 | luaD_poscall(L, nresults, ra); | 649 | luaD_poscall(L, nresults, ra); |
643 | if (nresults >= 0) L->top = L->ci->top; | 650 | if (nresults >= 0) L->top = L->ci->top; |
644 | L->ci->pc = &pc; /* function is active again */ | ||
645 | pc = L->ci->u.l.savedpc; | ||
646 | goto retentry; | 651 | goto retentry; |
647 | } | 652 | } |
648 | } | 653 | } |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lvm.h,v 1.44 2002/07/05 18:27:39 roberto Exp $ | 2 | ** $Id: lvm.h,v 1.45 2002/08/05 17:36:24 roberto Exp roberto $ |
3 | ** Lua virtual machine | 3 | ** Lua virtual machine |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -22,13 +22,6 @@ | |||
22 | (ttype(o1) == ttype(o2) && luaV_equalval(L, o1, o2)) | 22 | (ttype(o1) == ttype(o2) && luaV_equalval(L, o1, o2)) |
23 | 23 | ||
24 | 24 | ||
25 | /* | ||
26 | ** dummy addrees, to mark Lua functions calling other Lua functions (and | ||
27 | ** therefore without a valid `pc' | ||
28 | */ | ||
29 | extern Instruction const *luaV_callingmark; | ||
30 | |||
31 | |||
32 | int luaV_lessthan (lua_State *L, const TObject *l, const TObject *r); | 25 | int luaV_lessthan (lua_State *L, const TObject *l, const TObject *r); |
33 | int luaV_equalval (lua_State *L, const TObject *t1, const TObject *t2); | 26 | int luaV_equalval (lua_State *L, const TObject *t1, const TObject *t2); |
34 | const TObject *luaV_tonumber (const TObject *obj, TObject *n); | 27 | const TObject *luaV_tonumber (const TObject *obj, TObject *n); |