diff options
| author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2004-05-14 16:25:09 -0300 |
|---|---|---|
| committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2004-05-14 16:25:09 -0300 |
| commit | 0bda88e6cd960d3b1ad1d46826bfdef179098d2a (patch) | |
| tree | d3b237faef502dba76747a5563be9ccc4c404754 | |
| parent | 7966a4acaea50230e30acc8fd6997bce22307f24 (diff) | |
| download | lua-0bda88e6cd960d3b1ad1d46826bfdef179098d2a.tar.gz lua-0bda88e6cd960d3b1ad1d46826bfdef179098d2a.tar.bz2 lua-0bda88e6cd960d3b1ad1d46826bfdef179098d2a.zip | |
small steps towards yields in iterators and tag methods
| -rw-r--r-- | lapi.c | 10 | ||||
| -rw-r--r-- | ldo.c | 30 | ||||
| -rw-r--r-- | ldo.h | 10 | ||||
| -rw-r--r-- | lstate.h | 5 | ||||
| -rw-r--r-- | lvm.c | 127 | ||||
| -rw-r--r-- | lvm.h | 8 |
6 files changed, 111 insertions, 79 deletions
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lapi.c,v 2.7 2004/04/30 20:13:38 roberto Exp roberto $ | 2 | ** $Id: lapi.c,v 2.8 2004/05/11 16:52:08 roberto Exp roberto $ |
| 3 | ** Lua API | 3 | ** Lua API |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -488,7 +488,7 @@ LUA_API void lua_gettable (lua_State *L, int idx) { | |||
| 488 | lua_lock(L); | 488 | lua_lock(L); |
| 489 | t = luaA_index(L, idx); | 489 | t = luaA_index(L, idx); |
| 490 | api_checkvalidindex(L, t); | 490 | api_checkvalidindex(L, t); |
| 491 | luaV_gettable(L, t, L->top - 1, L->top - 1); | 491 | luaV_gettable(L, t, L->top - 1, L->top - 1, NULL); |
| 492 | lua_unlock(L); | 492 | lua_unlock(L); |
| 493 | } | 493 | } |
| 494 | 494 | ||
| @@ -500,7 +500,7 @@ LUA_API void lua_getfield (lua_State *L, int idx, const char *k) { | |||
| 500 | t = luaA_index(L, idx); | 500 | t = luaA_index(L, idx); |
| 501 | api_checkvalidindex(L, t); | 501 | api_checkvalidindex(L, t); |
| 502 | setsvalue(L, &key, luaS_new(L, k)); | 502 | setsvalue(L, &key, luaS_new(L, k)); |
| 503 | luaV_gettable(L, t, &key, L->top); | 503 | luaV_gettable(L, t, &key, L->top, NULL); |
| 504 | api_incr_top(L); | 504 | api_incr_top(L); |
| 505 | lua_unlock(L); | 505 | lua_unlock(L); |
| 506 | } | 506 | } |
| @@ -584,7 +584,7 @@ LUA_API void lua_settable (lua_State *L, int idx) { | |||
| 584 | api_checknelems(L, 2); | 584 | api_checknelems(L, 2); |
| 585 | t = luaA_index(L, idx); | 585 | t = luaA_index(L, idx); |
| 586 | api_checkvalidindex(L, t); | 586 | api_checkvalidindex(L, t); |
| 587 | luaV_settable(L, t, L->top - 2, L->top - 1); | 587 | luaV_settable(L, t, L->top - 2, L->top - 1, NULL); |
| 588 | L->top -= 2; /* pop index and value */ | 588 | L->top -= 2; /* pop index and value */ |
| 589 | lua_unlock(L); | 589 | lua_unlock(L); |
| 590 | } | 590 | } |
| @@ -598,7 +598,7 @@ LUA_API void lua_setfield (lua_State *L, int idx, const char *k) { | |||
| 598 | t = luaA_index(L, idx); | 598 | t = luaA_index(L, idx); |
| 599 | api_checkvalidindex(L, t); | 599 | api_checkvalidindex(L, t); |
| 600 | setsvalue(L, &key, luaS_new(L, k)); | 600 | setsvalue(L, &key, luaS_new(L, k)); |
| 601 | luaV_settable(L, t, &key, L->top - 1); | 601 | luaV_settable(L, t, &key, L->top - 1, NULL); |
| 602 | L->top--; /* pop value */ | 602 | L->top--; /* pop value */ |
| 603 | lua_unlock(L); | 603 | lua_unlock(L); |
| 604 | } | 604 | } |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: ldo.c,v 2.3 2004/04/30 20:13:38 roberto Exp roberto $ | 2 | ** $Id: ldo.c,v 2.4 2004/05/10 17:50:51 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 | */ |
| @@ -219,7 +219,7 @@ static StkId tryfuncTM (lua_State *L, StkId func) { | |||
| 219 | } | 219 | } |
| 220 | 220 | ||
| 221 | 221 | ||
| 222 | StkId luaD_precall (lua_State *L, StkId func) { | 222 | int luaD_precall (lua_State *L, StkId func, int nresults) { |
| 223 | LClosure *cl; | 223 | LClosure *cl; |
| 224 | ptrdiff_t funcr = savestack(L, func); | 224 | ptrdiff_t funcr = savestack(L, func); |
| 225 | if (!ttisfunction(func)) /* `func' is not a function? */ | 225 | if (!ttisfunction(func)) /* `func' is not a function? */ |
| @@ -239,10 +239,11 @@ StkId luaD_precall (lua_State *L, StkId func) { | |||
| 239 | ci->top = L->base + p->maxstacksize; | 239 | ci->top = L->base + p->maxstacksize; |
| 240 | ci->u.l.savedpc = p->code; /* starting point */ | 240 | ci->u.l.savedpc = p->code; /* starting point */ |
| 241 | ci->u.l.tailcalls = 0; | 241 | ci->u.l.tailcalls = 0; |
| 242 | ci->nresults = nresults; | ||
| 242 | for (st = L->top; st < ci->top; st++) | 243 | for (st = L->top; st < ci->top; st++) |
| 243 | setnilvalue(st); | 244 | setnilvalue(st); |
| 244 | L->top = ci->top; | 245 | L->top = ci->top; |
| 245 | return NULL; | 246 | return PCRLUA; |
| 246 | } | 247 | } |
| 247 | else { /* if is a C function, call it */ | 248 | else { /* if is a C function, call it */ |
| 248 | CallInfo *ci; | 249 | CallInfo *ci; |
| @@ -256,7 +257,14 @@ StkId luaD_precall (lua_State *L, StkId func) { | |||
| 256 | lua_unlock(L); | 257 | lua_unlock(L); |
| 257 | n = (*curr_func(L)->c.f)(L); /* do the actual call */ | 258 | n = (*curr_func(L)->c.f)(L); /* do the actual call */ |
| 258 | lua_lock(L); | 259 | lua_lock(L); |
| 259 | return L->top - n; | 260 | if (n >= 0) { /* no yielding? */ |
| 261 | luaD_poscall(L, nresults, L->top - n); | ||
| 262 | return PCRC; | ||
| 263 | } | ||
| 264 | else { | ||
| 265 | ci->nresults = nresults; | ||
| 266 | return PCRYIELD; | ||
| 267 | } | ||
| 260 | } | 268 | } |
| 261 | } | 269 | } |
| 262 | 270 | ||
| @@ -297,17 +305,16 @@ void luaD_poscall (lua_State *L, int wanted, StkId firstResult) { | |||
| 297 | ** function position. | 305 | ** function position. |
| 298 | */ | 306 | */ |
| 299 | void luaD_call (lua_State *L, StkId func, int nResults) { | 307 | void luaD_call (lua_State *L, StkId func, int nResults) { |
| 300 | StkId firstResult; | ||
| 301 | if (++L->nCcalls >= LUA_MAXCCALLS) { | 308 | if (++L->nCcalls >= LUA_MAXCCALLS) { |
| 302 | if (L->nCcalls == LUA_MAXCCALLS) | 309 | if (L->nCcalls == LUA_MAXCCALLS) |
| 303 | luaG_runerror(L, "C stack overflow"); | 310 | luaG_runerror(L, "C stack overflow"); |
| 304 | else if (L->nCcalls >= (LUA_MAXCCALLS + (LUA_MAXCCALLS>>3))) | 311 | else if (L->nCcalls >= (LUA_MAXCCALLS + (LUA_MAXCCALLS>>3))) |
| 305 | luaD_throw(L, LUA_ERRERR); /* error while handing stack error */ | 312 | luaD_throw(L, LUA_ERRERR); /* error while handing stack error */ |
| 306 | } | 313 | } |
| 307 | firstResult = luaD_precall(L, func); | 314 | if (luaD_precall(L, func, nResults) == PCRLUA) { /* is a Lua function? */ |
| 308 | if (firstResult == NULL) /* is a Lua function? */ | 315 | StkId firstResult = luaV_execute(L, 1); /* call it */ |
| 309 | firstResult = luaV_execute(L, 1); /* call it */ | 316 | luaD_poscall(L, nResults, firstResult); |
| 310 | luaD_poscall(L, nResults, firstResult); | 317 | } |
| 311 | L->nCcalls--; | 318 | L->nCcalls--; |
| 312 | luaC_checkGC(L); | 319 | luaC_checkGC(L); |
| 313 | } | 320 | } |
| @@ -319,15 +326,14 @@ static void resume (lua_State *L, void *ud) { | |||
| 319 | CallInfo *ci = L->ci; | 326 | CallInfo *ci = L->ci; |
| 320 | if (!L->isSuspended) { | 327 | if (!L->isSuspended) { |
| 321 | lua_assert(ci == L->base_ci && nargs < L->top - L->base); | 328 | lua_assert(ci == L->base_ci && nargs < L->top - L->base); |
| 322 | luaD_precall(L, L->top - (nargs + 1)); /* start coroutine */ | 329 | luaD_precall(L, L->top - (nargs + 1), LUA_MULTRET); /* start coroutine */ |
| 323 | } | 330 | } |
| 324 | else { /* resuming from previous yield */ | 331 | else { /* resuming from previous yield */ |
| 325 | if (!f_isLua(ci)) { /* `common' yield? */ | 332 | if (!f_isLua(ci)) { /* `common' yield? */ |
| 326 | /* finish interrupted execution of `OP_CALL' */ | 333 | /* finish interrupted execution of `OP_CALL' */ |
| 327 | int nresults; | 334 | int nresults = ci->nresults; |
| 328 | lua_assert(GET_OPCODE(*((ci-1)->u.l.savedpc - 1)) == OP_CALL || | 335 | lua_assert(GET_OPCODE(*((ci-1)->u.l.savedpc - 1)) == OP_CALL || |
| 329 | GET_OPCODE(*((ci-1)->u.l.savedpc - 1)) == OP_TAILCALL); | 336 | GET_OPCODE(*((ci-1)->u.l.savedpc - 1)) == OP_TAILCALL); |
| 330 | nresults = GETARG_C(*((ci-1)->u.l.savedpc - 1)) - 1; | ||
| 331 | luaD_poscall(L, nresults, L->top - nargs); /* complete it */ | 337 | luaD_poscall(L, nresults, L->top - nargs); /* complete it */ |
| 332 | if (nresults >= 0) L->top = L->ci->top; | 338 | if (nresults >= 0) L->top = L->ci->top; |
| 333 | } /* else yielded inside a hook: just continue its execution */ | 339 | } /* else yielded inside a hook: just continue its execution */ |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: ldo.h,v 1.58 2003/08/27 21:01:44 roberto Exp roberto $ | 2 | ** $Id: ldo.h,v 2.1 2003/12/10 12:13:36 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 | */ |
| @@ -38,13 +38,19 @@ | |||
| 38 | #define restoreci(L,n) ((CallInfo *)((char *)L->base_ci + (n))) | 38 | #define restoreci(L,n) ((CallInfo *)((char *)L->base_ci + (n))) |
| 39 | 39 | ||
| 40 | 40 | ||
| 41 | /* results from luaD_precall */ | ||
| 42 | #define PCRLUA 0 /* initiated a call to a Lua function */ | ||
| 43 | #define PCRC 1 /* did a call to a C function */ | ||
| 44 | #define PCRYIELD 2 /* C funtion yielded */ | ||
| 45 | |||
| 46 | |||
| 41 | /* type of protected functions, to be ran by `runprotected' */ | 47 | /* type of protected functions, to be ran by `runprotected' */ |
| 42 | typedef void (*Pfunc) (lua_State *L, void *ud); | 48 | typedef void (*Pfunc) (lua_State *L, void *ud); |
| 43 | 49 | ||
| 44 | void luaD_resetprotection (lua_State *L); | 50 | void luaD_resetprotection (lua_State *L); |
| 45 | int luaD_protectedparser (lua_State *L, ZIO *z, const char *name); | 51 | int luaD_protectedparser (lua_State *L, ZIO *z, const char *name); |
| 46 | void luaD_callhook (lua_State *L, int event, int line); | 52 | void luaD_callhook (lua_State *L, int event, int line); |
| 47 | StkId luaD_precall (lua_State *L, StkId func); | 53 | int luaD_precall (lua_State *L, StkId func, int nresults); |
| 48 | void luaD_call (lua_State *L, StkId func, int nResults); | 54 | void luaD_call (lua_State *L, StkId func, int nResults); |
| 49 | int luaD_pcall (lua_State *L, Pfunc func, void *u, | 55 | int luaD_pcall (lua_State *L, Pfunc func, void *u, |
| 50 | ptrdiff_t oldtop, ptrdiff_t ef); | 56 | ptrdiff_t oldtop, ptrdiff_t ef); |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lstate.h,v 2.1 2003/12/10 12:13:36 roberto Exp roberto $ | 2 | ** $Id: lstate.h,v 2.2 2004/03/23 17:02:58 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 | */ |
| @@ -70,8 +70,9 @@ typedef struct stringtable { | |||
| 70 | ** informations about a call | 70 | ** informations about a call |
| 71 | */ | 71 | */ |
| 72 | typedef struct CallInfo { | 72 | typedef struct CallInfo { |
| 73 | StkId base; /* base for called function */ | 73 | StkId base; /* base for this function */ |
| 74 | StkId top; /* top for this function */ | 74 | StkId top; /* top for this function */ |
| 75 | int nresults; /* expected number of results from this function */ | ||
| 75 | union { | 76 | union { |
| 76 | struct { /* for Lua functions */ | 77 | struct { /* for Lua functions */ |
| 77 | const Instruction *savedpc; | 78 | const Instruction *savedpc; |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lvm.c,v 2.4 2004/04/30 20:13:38 roberto Exp roberto $ | 2 | ** $Id: lvm.c,v 2.5 2004/05/10 17:50:51 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 | */ |
| @@ -106,7 +106,8 @@ static void callTM (lua_State *L) { | |||
| 106 | } | 106 | } |
| 107 | 107 | ||
| 108 | 108 | ||
| 109 | void luaV_gettable (lua_State *L, const TValue *t, TValue *key, StkId val) { | 109 | StkId luaV_gettable (lua_State *L, const TValue *t, TValue *key, StkId val, |
| 110 | const Instruction *pc) { | ||
| 110 | int loop; | 111 | int loop; |
| 111 | for (loop = 0; loop < MAXTAGLOOP; loop++) { | 112 | for (loop = 0; loop < MAXTAGLOOP; loop++) { |
| 112 | const TValue *tm; | 113 | const TValue *tm; |
| @@ -116,24 +117,30 @@ void luaV_gettable (lua_State *L, const TValue *t, TValue *key, StkId val) { | |||
| 116 | if (!ttisnil(res) || /* result is no nil? */ | 117 | if (!ttisnil(res) || /* result is no nil? */ |
| 117 | (tm = fasttm(L, h->metatable, TM_INDEX)) == NULL) { /* or no TM? */ | 118 | (tm = fasttm(L, h->metatable, TM_INDEX)) == NULL) { /* or no TM? */ |
| 118 | setobj2s(L, val, res); | 119 | setobj2s(L, val, res); |
| 119 | return; | 120 | return L->base; |
| 120 | } | 121 | } |
| 121 | /* else will try the tag method */ | 122 | /* else will try the tag method */ |
| 122 | } | 123 | } |
| 123 | else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_INDEX))) | 124 | else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_INDEX))) { |
| 125 | if (pc) L->ci->u.l.savedpc = pc; | ||
| 124 | luaG_typeerror(L, t, "index"); | 126 | luaG_typeerror(L, t, "index"); |
| 127 | } | ||
| 125 | if (ttisfunction(tm)) { | 128 | if (ttisfunction(tm)) { |
| 129 | if (pc) L->ci->u.l.savedpc = pc; | ||
| 126 | prepTMcall(L, tm, t, key); | 130 | prepTMcall(L, tm, t, key); |
| 127 | callTMres(L, val); | 131 | callTMres(L, val); |
| 128 | return; | 132 | return L->base; |
| 129 | } | 133 | } |
| 130 | t = tm; /* else repeat with `tm' */ | 134 | t = tm; /* else repeat with `tm' */ |
| 131 | } | 135 | } |
| 136 | if (pc) L->ci->u.l.savedpc = pc; | ||
| 132 | luaG_runerror(L, "loop in gettable"); | 137 | luaG_runerror(L, "loop in gettable"); |
| 138 | return NULL; /* to avoid warnings */ | ||
| 133 | } | 139 | } |
| 134 | 140 | ||
| 135 | 141 | ||
| 136 | void luaV_settable (lua_State *L, const TValue *t, TValue *key, StkId val) { | 142 | StkId luaV_settable (lua_State *L, const TValue *t, TValue *key, StkId val, |
| 143 | const Instruction *pc) { | ||
| 137 | int loop; | 144 | int loop; |
| 138 | for (loop = 0; loop < MAXTAGLOOP; loop++) { | 145 | for (loop = 0; loop < MAXTAGLOOP; loop++) { |
| 139 | const TValue *tm; | 146 | const TValue *tm; |
| @@ -144,21 +151,26 @@ void luaV_settable (lua_State *L, const TValue *t, TValue *key, StkId val) { | |||
| 144 | (tm = fasttm(L, h->metatable, TM_NEWINDEX)) == NULL) { /* or no TM? */ | 151 | (tm = fasttm(L, h->metatable, TM_NEWINDEX)) == NULL) { /* or no TM? */ |
| 145 | setobj2t(L, oldval, val); | 152 | setobj2t(L, oldval, val); |
| 146 | luaC_barrier(L, h, val); | 153 | luaC_barrier(L, h, val); |
| 147 | return; | 154 | return L->base; |
| 148 | } | 155 | } |
| 149 | /* else will try the tag method */ | 156 | /* else will try the tag method */ |
| 150 | } | 157 | } |
| 151 | else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_NEWINDEX))) | 158 | else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_NEWINDEX))) { |
| 159 | if (pc) L->ci->u.l.savedpc = pc; | ||
| 152 | luaG_typeerror(L, t, "index"); | 160 | luaG_typeerror(L, t, "index"); |
| 161 | } | ||
| 153 | if (ttisfunction(tm)) { | 162 | if (ttisfunction(tm)) { |
| 163 | if (pc) L->ci->u.l.savedpc = pc; | ||
| 154 | prepTMcall(L, tm, t, key); | 164 | prepTMcall(L, tm, t, key); |
| 155 | setobj2s(L, L->top+3, val); /* 3th argument */ | 165 | setobj2s(L, L->top+3, val); /* 3th argument */ |
| 156 | callTM(L); | 166 | callTM(L); |
| 157 | return; | 167 | return L->base; |
| 158 | } | 168 | } |
| 159 | t = tm; /* else repeat with `tm' */ | 169 | t = tm; /* else repeat with `tm' */ |
| 160 | } | 170 | } |
| 171 | if (pc) L->ci->u.l.savedpc = pc; | ||
| 161 | luaG_runerror(L, "loop in settable"); | 172 | luaG_runerror(L, "loop in settable"); |
| 173 | return NULL; /* to avoid warnings */ | ||
| 162 | } | 174 | } |
| 163 | 175 | ||
| 164 | 176 | ||
| @@ -427,22 +439,16 @@ StkId luaV_execute (lua_State *L, int nexeccalls) { | |||
| 427 | case OP_GETGLOBAL: { | 439 | case OP_GETGLOBAL: { |
| 428 | TValue *rb = KBx(i); | 440 | TValue *rb = KBx(i); |
| 429 | lua_assert(ttisstring(rb) && ttistable(&cl->g)); | 441 | lua_assert(ttisstring(rb) && ttistable(&cl->g)); |
| 430 | L->ci->u.l.savedpc = pc; | 442 | base = luaV_gettable(L, &cl->g, rb, ra, pc); /***/ |
| 431 | luaV_gettable(L, &cl->g, rb, ra); /***/ | ||
| 432 | base = L->base; | ||
| 433 | break; | 443 | break; |
| 434 | } | 444 | } |
| 435 | case OP_GETTABLE: { | 445 | case OP_GETTABLE: { |
| 436 | L->ci->u.l.savedpc = pc; | 446 | base = luaV_gettable(L, RB(i), RKC(i), ra, pc); /***/ |
| 437 | luaV_gettable(L, RB(i), RKC(i), ra); /***/ | ||
| 438 | base = L->base; | ||
| 439 | break; | 447 | break; |
| 440 | } | 448 | } |
| 441 | case OP_SETGLOBAL: { | 449 | case OP_SETGLOBAL: { |
| 442 | lua_assert(ttisstring(KBx(i)) && ttistable(&cl->g)); | 450 | lua_assert(ttisstring(KBx(i)) && ttistable(&cl->g)); |
| 443 | L->ci->u.l.savedpc = pc; | 451 | base = luaV_settable(L, &cl->g, KBx(i), ra, pc); /***/ |
| 444 | luaV_settable(L, &cl->g, KBx(i), ra); /***/ | ||
| 445 | base = L->base; | ||
| 446 | break; | 452 | break; |
| 447 | } | 453 | } |
| 448 | case OP_SETUPVAL: { | 454 | case OP_SETUPVAL: { |
| @@ -452,9 +458,7 @@ StkId luaV_execute (lua_State *L, int nexeccalls) { | |||
| 452 | break; | 458 | break; |
| 453 | } | 459 | } |
| 454 | case OP_SETTABLE: { | 460 | case OP_SETTABLE: { |
| 455 | L->ci->u.l.savedpc = pc; | 461 | base = luaV_settable(L, ra, RKB(i), RKC(i), pc); /***/ |
| 456 | luaV_settable(L, ra, RKB(i), RKC(i)); /***/ | ||
| 457 | base = L->base; | ||
| 458 | break; | 462 | break; |
| 459 | } | 463 | } |
| 460 | case OP_NEWTABLE: { | 464 | case OP_NEWTABLE: { |
| @@ -469,9 +473,7 @@ StkId luaV_execute (lua_State *L, int nexeccalls) { | |||
| 469 | case OP_SELF: { | 473 | case OP_SELF: { |
| 470 | StkId rb = RB(i); | 474 | StkId rb = RB(i); |
| 471 | setobjs2s(L, ra+1, rb); | 475 | setobjs2s(L, ra+1, rb); |
| 472 | L->ci->u.l.savedpc = pc; | 476 | base = luaV_gettable(L, rb, RKC(i), ra, pc); /***/ |
| 473 | luaV_gettable(L, rb, RKC(i), ra); /***/ | ||
| 474 | base = L->base; | ||
| 475 | break; | 477 | break; |
| 476 | } | 478 | } |
| 477 | case OP_ADD: { | 479 | case OP_ADD: { |
| @@ -582,43 +584,59 @@ StkId luaV_execute (lua_State *L, int nexeccalls) { | |||
| 582 | } | 584 | } |
| 583 | break; | 585 | break; |
| 584 | } | 586 | } |
| 585 | case OP_CALL: | 587 | case OP_CALL: { /***/ |
| 586 | case OP_TAILCALL: { /***/ | 588 | int pcr; |
| 587 | StkId firstResult; | ||
| 588 | int b = GETARG_B(i); | 589 | int b = GETARG_B(i); |
| 590 | int nresults = GETARG_C(i) - 1; | ||
| 589 | if (b != 0) L->top = ra+b; /* else previous instruction set top */ | 591 | if (b != 0) L->top = ra+b; /* else previous instruction set top */ |
| 590 | L->ci->u.l.savedpc = pc; | 592 | L->ci->u.l.savedpc = pc; |
| 591 | firstResult = luaD_precall(L, ra); | 593 | pcr = luaD_precall(L, ra, nresults); |
| 592 | if (firstResult) { | 594 | if (pcr == PCRLUA) { |
| 593 | int nresults = GETARG_C(i) - 1; | 595 | nexeccalls++; |
| 594 | if (firstResult > L->top) { /* yield? */ | 596 | goto callentry; /* restart luaV_execute over new Lua function */ |
| 595 | (L->ci - 1)->u.l.savedpc = pc; | 597 | } |
| 596 | return NULL; | 598 | else if (pcr == PCRC) { |
| 597 | } | ||
| 598 | /* it was a C function (`precall' called it); adjust results */ | 599 | /* it was a C function (`precall' called it); adjust results */ |
| 599 | luaD_poscall(L, nresults, firstResult); | ||
| 600 | if (nresults >= 0) L->top = L->ci->top; | 600 | if (nresults >= 0) L->top = L->ci->top; |
| 601 | base = L->base; | ||
| 602 | break; | ||
| 601 | } | 603 | } |
| 602 | else { /* it is a Lua function */ | 604 | else { |
| 603 | if (GET_OPCODE(i) == OP_CALL) /* regular call? */ | 605 | lua_assert(pcr == PCRYIELD); |
| 604 | nexeccalls++; | 606 | return NULL; |
| 605 | else { /* tail call: put new frame in place of previous one */ | 607 | } |
| 606 | int aux; | 608 | } |
| 607 | base = (L->ci - 1)->base; /* `luaD_precall' may change the stack */ | 609 | case OP_TAILCALL: { /***/ |
| 608 | ra = RA(i); | 610 | int pcr; |
| 609 | if (L->openupval) luaF_close(L, base); | 611 | int b = GETARG_B(i); |
| 610 | for (aux = 0; ra+aux < L->top; aux++) /* move frame down */ | 612 | if (b != 0) L->top = ra+b; /* else previous instruction set top */ |
| 611 | setobjs2s(L, base+aux-1, ra+aux); | 613 | L->ci->u.l.savedpc = pc; |
| 612 | (L->ci - 1)->top = L->top = base+aux; /* correct top */ | 614 | lua_assert(GETARG_C(i) - 1 == LUA_MULTRET); |
| 613 | (L->ci - 1)->u.l.savedpc = L->ci->u.l.savedpc; | 615 | pcr = luaD_precall(L, ra, LUA_MULTRET); |
| 614 | (L->ci - 1)->u.l.tailcalls++; /* one more call lost */ | 616 | if (pcr == PCRLUA) { |
| 615 | L->ci--; /* remove new frame */ | 617 | /* tail call: put new frame in place of previous one */ |
| 616 | L->base = L->ci->base; | 618 | int aux; |
| 617 | } | 619 | base = (L->ci - 1)->base; /* `luaD_precall' may change the stack */ |
| 620 | ra = RA(i); | ||
| 621 | if (L->openupval) luaF_close(L, base); | ||
| 622 | for (aux = 0; ra+aux < L->top; aux++) /* move frame down */ | ||
| 623 | setobjs2s(L, base+aux-1, ra+aux); | ||
| 624 | (L->ci - 1)->top = L->top = base+aux; /* correct top */ | ||
| 625 | (L->ci - 1)->u.l.savedpc = L->ci->u.l.savedpc; | ||
| 626 | (L->ci - 1)->u.l.tailcalls++; /* one more call lost */ | ||
| 627 | L->ci--; /* remove new frame */ | ||
| 628 | L->base = L->ci->base; | ||
| 618 | goto callentry; | 629 | goto callentry; |
| 619 | } | 630 | } |
| 620 | base = L->base; | 631 | else if (pcr == PCRC) { |
| 621 | break; | 632 | /* it was a C function (`precall' called it) */ |
| 633 | base = L->base; | ||
| 634 | break; | ||
| 635 | } | ||
| 636 | else { | ||
| 637 | lua_assert(pcr == PCRYIELD); | ||
| 638 | return NULL; | ||
| 639 | } | ||
| 622 | } | 640 | } |
| 623 | case OP_RETURN: { | 641 | case OP_RETURN: { |
| 624 | CallInfo *ci = L->ci - 1; /* previous function frame */ | 642 | CallInfo *ci = L->ci - 1; /* previous function frame */ |
| @@ -629,10 +647,9 @@ StkId luaV_execute (lua_State *L, int nexeccalls) { | |||
| 629 | if (--nexeccalls == 0) /* was previous function running `here'? */ | 647 | if (--nexeccalls == 0) /* was previous function running `here'? */ |
| 630 | return ra; /* no: return */ | 648 | return ra; /* no: return */ |
| 631 | else { /* yes: continue its execution */ | 649 | else { /* yes: continue its execution */ |
| 632 | int nresults; | 650 | int nresults = (ci+1)->nresults; |
| 633 | lua_assert(isLua(ci)); | 651 | lua_assert(isLua(ci)); |
| 634 | lua_assert(GET_OPCODE(*(ci->u.l.savedpc - 1)) == OP_CALL); | 652 | lua_assert(GET_OPCODE(*(ci->u.l.savedpc - 1)) == OP_CALL); |
| 635 | nresults = GETARG_C(*(ci->u.l.savedpc - 1)) - 1; | ||
| 636 | luaD_poscall(L, nresults, ra); | 653 | luaD_poscall(L, nresults, ra); |
| 637 | if (nresults >= 0) L->top = L->ci->top; | 654 | if (nresults >= 0) L->top = L->ci->top; |
| 638 | goto retentry; | 655 | goto retentry; |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lvm.h,v 1.49 2003/07/16 20:49:02 roberto Exp roberto $ | 2 | ** $Id: lvm.h,v 2.1 2003/12/10 12:13:36 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 | */ |
| @@ -26,8 +26,10 @@ int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r); | |||
| 26 | int luaV_equalval (lua_State *L, const TValue *t1, const TValue *t2); | 26 | int luaV_equalval (lua_State *L, const TValue *t1, const TValue *t2); |
| 27 | const TValue *luaV_tonumber (const TValue *obj, TValue *n); | 27 | const TValue *luaV_tonumber (const TValue *obj, TValue *n); |
| 28 | int luaV_tostring (lua_State *L, StkId obj); | 28 | int luaV_tostring (lua_State *L, StkId obj); |
| 29 | void luaV_gettable (lua_State *L, const TValue *t, TValue *key, StkId val); | 29 | StkId luaV_gettable (lua_State *L, const TValue *t, TValue *key, StkId val, |
| 30 | void luaV_settable (lua_State *L, const TValue *t, TValue *key, StkId val); | 30 | const Instruction *pc); |
| 31 | StkId luaV_settable (lua_State *L, const TValue *t, TValue *key, StkId val, | ||
| 32 | const Instruction *pc); | ||
| 31 | StkId luaV_execute (lua_State *L, int nexeccalls); | 33 | StkId luaV_execute (lua_State *L, int nexeccalls); |
| 32 | void luaV_concat (lua_State *L, int total, int last); | 34 | void luaV_concat (lua_State *L, int total, int last); |
| 33 | 35 | ||
