diff options
| author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2002-11-18 13:24:11 -0200 |
|---|---|---|
| committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2002-11-18 13:24:11 -0200 |
| commit | 9bab2cf55d9b151d730c1461e3882a5fbc7d790d (patch) | |
| tree | c264480215e163b96fe1d44d874648ee39cc3cfa | |
| parent | c4ae00a3d107a27d80bd157a135ef115104f98f0 (diff) | |
| download | lua-9bab2cf55d9b151d730c1461e3882a5fbc7d790d.tar.gz lua-9bab2cf55d9b151d730c1461e3882a5fbc7d790d.tar.bz2 lua-9bab2cf55d9b151d730c1461e3882a5fbc7d790d.zip | |
support for yield inside hooks
| -rw-r--r-- | ldo.c | 44 | ||||
| -rw-r--r-- | lvm.c | 13 |
2 files changed, 35 insertions, 22 deletions
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: ldo.c,v 1.201 2002/11/14 16:15:53 roberto Exp roberto $ | 2 | ** $Id: ldo.c,v 1.202 2002/11/18 11:01:55 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 | */ |
| @@ -308,15 +308,20 @@ static void resume (lua_State *L, void *ud) { | |||
| 308 | luaG_runerror(L, "cannot resume dead coroutine"); | 308 | luaG_runerror(L, "cannot resume dead coroutine"); |
| 309 | luaD_precall(L, L->top - (nargs + 1)); /* start coroutine */ | 309 | luaD_precall(L, L->top - (nargs + 1)); /* start coroutine */ |
| 310 | } | 310 | } |
| 311 | else if (ci->state && CI_YIELD) { /* inside a yield? */ | 311 | else if (ci->state & CI_YIELD) { /* inside a yield? */ |
| 312 | /* finish interrupted execution of `OP_CALL' */ | 312 | if (ci->state & CI_C) { /* `common' yield? */ |
| 313 | int nresults; | 313 | /* finish interrupted execution of `OP_CALL' */ |
| 314 | lua_assert((ci-1)->state & CI_SAVEDPC); | 314 | int nresults; |
| 315 | lua_assert(GET_OPCODE(*((ci-1)->u.l.savedpc - 1)) == OP_CALL || | 315 | lua_assert((ci-1)->state & CI_SAVEDPC); |
| 316 | GET_OPCODE(*((ci-1)->u.l.savedpc - 1)) == OP_TAILCALL); | 316 | lua_assert(GET_OPCODE(*((ci-1)->u.l.savedpc - 1)) == OP_CALL || |
| 317 | nresults = GETARG_C(*((ci-1)->u.l.savedpc - 1)) - 1; | 317 | GET_OPCODE(*((ci-1)->u.l.savedpc - 1)) == OP_TAILCALL); |
| 318 | luaD_poscall(L, nresults, L->top - nargs); /* complete it */ | 318 | nresults = GETARG_C(*((ci-1)->u.l.savedpc - 1)) - 1; |
| 319 | if (nresults >= 0) L->top = L->ci->top; | 319 | luaD_poscall(L, nresults, L->top - nargs); /* complete it */ |
| 320 | if (nresults >= 0) L->top = L->ci->top; | ||
| 321 | } | ||
| 322 | else { /* yielded inside a hook: just continue its execution */ | ||
| 323 | ci->state &= ~CI_YIELD; | ||
| 324 | } | ||
| 320 | } | 325 | } |
| 321 | else | 326 | else |
| 322 | luaG_runerror(L, "cannot resume non-suspended coroutine"); | 327 | luaG_runerror(L, "cannot resume non-suspended coroutine"); |
| @@ -349,15 +354,18 @@ LUA_API int lua_yield (lua_State *L, int nresults) { | |||
| 349 | CallInfo *ci; | 354 | CallInfo *ci; |
| 350 | lua_lock(L); | 355 | lua_lock(L); |
| 351 | ci = L->ci; | 356 | ci = L->ci; |
| 352 | if ((ci-1)->state & CI_C) | 357 | if (ci->state & CI_C) { /* usual yield */ |
| 353 | luaG_runerror(L, "cannot yield a C function"); | 358 | if ((ci-1)->state & CI_C) |
| 354 | lua_assert(ci->state & CI_C); /* current function is not Lua */ | 359 | luaG_runerror(L, "cannot yield a C function"); |
| 355 | if (L->top - nresults > ci->base) { /* is there garbage in the stack? */ | 360 | if (L->top - nresults > ci->base) { /* is there garbage in the stack? */ |
| 356 | int i; | 361 | int i; |
| 357 | for (i=0; i<nresults; i++) /* move down results */ | 362 | for (i=0; i<nresults; i++) /* move down results */ |
| 358 | setobjs2s(ci->base + i, L->top - nresults + i); | 363 | setobjs2s(ci->base + i, L->top - nresults + i); |
| 359 | L->top = ci->base + nresults; | 364 | L->top = ci->base + nresults; |
| 365 | } | ||
| 360 | } | 366 | } |
| 367 | /* else it's an yield inside a hook: nothing to do */ | ||
| 368 | ci->state |= CI_YIELD; | ||
| 361 | lua_unlock(L); | 369 | lua_unlock(L); |
| 362 | return -1; | 370 | return -1; |
| 363 | } | 371 | } |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lvm.c,v 1.261 2002/11/14 16:15:53 roberto Exp roberto $ | 2 | ** $Id: lvm.c,v 1.262 2002/11/18 11:01:55 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 | */ |
| @@ -393,8 +393,14 @@ StkId luaV_execute (lua_State *L) { | |||
| 393 | const Instruction i = *pc++; | 393 | const Instruction i = *pc++; |
| 394 | StkId ra; | 394 | StkId ra; |
| 395 | if (L->hookmask >= LUA_MASKLINE && | 395 | if (L->hookmask >= LUA_MASKLINE && |
| 396 | (--L->hookcount == 0 || L->hookmask & LUA_MASKLINE)) | 396 | (--L->hookcount == 0 || L->hookmask & LUA_MASKLINE)) { |
| 397 | traceexec(L); | 397 | traceexec(L); |
| 398 | if (L->ci->state & CI_YIELD) { /* did hook yield? */ | ||
| 399 | L->ci->u.l.savedpc = pc - 1; | ||
| 400 | L->ci->state |= CI_SAVEDPC; | ||
| 401 | return NULL; | ||
| 402 | } | ||
| 403 | } | ||
| 398 | /* warning!! several calls may realloc the stack and invalidate `ra' */ | 404 | /* warning!! several calls may realloc the stack and invalidate `ra' */ |
| 399 | ra = RA(i); | 405 | ra = RA(i); |
| 400 | lua_assert(L->top <= L->stack + L->stacksize && L->top >= L->ci->base); | 406 | lua_assert(L->top <= L->stack + L->stacksize && L->top >= L->ci->base); |
| @@ -595,8 +601,7 @@ StkId luaV_execute (lua_State *L) { | |||
| 595 | if (firstResult) { | 601 | if (firstResult) { |
| 596 | if (firstResult > L->top) { /* yield? */ | 602 | if (firstResult > L->top) { /* yield? */ |
| 597 | (L->ci - 1)->u.l.savedpc = pc; | 603 | (L->ci - 1)->u.l.savedpc = pc; |
| 598 | (L->ci - 1)->state = CI_SAVEDPC; | 604 | (L->ci - 1)->state |= CI_SAVEDPC; |
| 599 | L->ci->state |= CI_YIELD; | ||
| 600 | return NULL; | 605 | return NULL; |
| 601 | } | 606 | } |
| 602 | /* it was a C function (`precall' called it); adjust results */ | 607 | /* it was a C function (`precall' called it); adjust results */ |
