diff options
| author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2008-08-13 14:02:42 -0300 |
|---|---|---|
| committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2008-08-13 14:02:42 -0300 |
| commit | fdbb243ff9980870c54676f3b2597b110ab82864 (patch) | |
| tree | 37c1d31df7addd0638c8b26b28e6f4a0b6024a88 | |
| parent | c1565c16edc487f32d87d1742a7c8e76d0b10236 (diff) | |
| download | lua-fdbb243ff9980870c54676f3b2597b110ab82864.tar.gz lua-fdbb243ff9980870c54676f3b2597b110ab82864.tar.bz2 lua-fdbb243ff9980870c54676f3b2597b110ab82864.zip | |
first steps towards yielding through longjump
| -rw-r--r-- | ldo.c | 33 | ||||
| -rw-r--r-- | ldo.h | 8 | ||||
| -rw-r--r-- | lvm.c | 71 |
3 files changed, 50 insertions, 62 deletions
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: ldo.c,v 2.45 2007/03/27 14:11:38 roberto Exp roberto $ | 2 | ** $Id: ldo.c,v 2.46 2008/01/18 22:36:50 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 | */ |
| @@ -193,6 +193,7 @@ void luaD_callhook (lua_State *L, int event, int line) { | |||
| 193 | ar.i_ci = cast_int(L->ci - L->base_ci); | 193 | ar.i_ci = cast_int(L->ci - L->base_ci); |
| 194 | luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */ | 194 | luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */ |
| 195 | L->ci->top = L->top + LUA_MINSTACK; | 195 | L->ci->top = L->top + LUA_MINSTACK; |
| 196 | L->ci->status |= 1; /* this level is running a hook */ | ||
| 196 | lua_assert(L->ci->top <= L->stack_last); | 197 | lua_assert(L->ci->top <= L->stack_last); |
| 197 | L->allowhook = 0; /* cannot call hooks inside a hook */ | 198 | L->allowhook = 0; /* cannot call hooks inside a hook */ |
| 198 | lua_unlock(L); | 199 | lua_unlock(L); |
| @@ -202,6 +203,7 @@ void luaD_callhook (lua_State *L, int event, int line) { | |||
| 202 | L->allowhook = 1; | 203 | L->allowhook = 1; |
| 203 | L->ci->top = restorestack(L, ci_top); | 204 | L->ci->top = restorestack(L, ci_top); |
| 204 | L->top = restorestack(L, top); | 205 | L->top = restorestack(L, top); |
| 206 | L->ci->status &= ~1; /* this level is not running a hook anymore */ | ||
| 205 | } | 207 | } |
| 206 | } | 208 | } |
| 207 | 209 | ||
| @@ -264,6 +266,9 @@ static StkId tryfuncTM (lua_State *L, StkId func) { | |||
| 264 | (condhardstacktests(luaD_reallocCI(L, L->size_ci)), ++L->ci)) | 266 | (condhardstacktests(luaD_reallocCI(L, L->size_ci)), ++L->ci)) |
| 265 | 267 | ||
| 266 | 268 | ||
| 269 | /* | ||
| 270 | ** returns true if function has been executed (C function) | ||
| 271 | */ | ||
| 267 | int luaD_precall (lua_State *L, StkId func, int nresults) { | 272 | int luaD_precall (lua_State *L, StkId func, int nresults) { |
| 268 | LClosure *cl; | 273 | LClosure *cl; |
| 269 | ptrdiff_t funcr; | 274 | ptrdiff_t funcr; |
| @@ -292,6 +297,7 @@ int luaD_precall (lua_State *L, StkId func, int nresults) { | |||
| 292 | lua_assert(ci->top <= L->stack_last); | 297 | lua_assert(ci->top <= L->stack_last); |
| 293 | L->savedpc = p->code; /* starting point */ | 298 | L->savedpc = p->code; /* starting point */ |
| 294 | ci->tailcalls = 0; | 299 | ci->tailcalls = 0; |
| 300 | ci->status = 0; | ||
| 295 | ci->nresults = nresults; | 301 | ci->nresults = nresults; |
| 296 | for (st = L->top; st < ci->top; st++) | 302 | for (st = L->top; st < ci->top; st++) |
| 297 | setnilvalue(st); | 303 | setnilvalue(st); |
| @@ -301,7 +307,7 @@ int luaD_precall (lua_State *L, StkId func, int nresults) { | |||
| 301 | luaD_callhook(L, LUA_HOOKCALL, -1); | 307 | luaD_callhook(L, LUA_HOOKCALL, -1); |
| 302 | L->savedpc--; /* correct 'pc' */ | 308 | L->savedpc--; /* correct 'pc' */ |
| 303 | } | 309 | } |
| 304 | return PCRLUA; | 310 | return 0; |
| 305 | } | 311 | } |
| 306 | else { /* if is a C function, call it */ | 312 | else { /* if is a C function, call it */ |
| 307 | CallInfo *ci; | 313 | CallInfo *ci; |
| @@ -318,12 +324,8 @@ int luaD_precall (lua_State *L, StkId func, int nresults) { | |||
| 318 | lua_unlock(L); | 324 | lua_unlock(L); |
| 319 | n = (*curr_func(L)->c.f)(L); /* do the actual call */ | 325 | n = (*curr_func(L)->c.f)(L); /* do the actual call */ |
| 320 | lua_lock(L); | 326 | lua_lock(L); |
| 321 | if (n < 0) /* yielding? */ | 327 | luaD_poscall(L, L->top - n); |
| 322 | return PCRYIELD; | 328 | return 1; |
| 323 | else { | ||
| 324 | luaD_poscall(L, L->top - n); | ||
| 325 | return PCRC; | ||
| 326 | } | ||
| 327 | } | 329 | } |
| 328 | } | 330 | } |
| 329 | 331 | ||
| @@ -378,7 +380,7 @@ void luaD_call (lua_State *L, StkId func, int nResults) { | |||
| 378 | else if (g->nCcalls >= (LUAI_MAXCCALLS + (LUAI_MAXCCALLS>>3))) | 380 | else if (g->nCcalls >= (LUAI_MAXCCALLS + (LUAI_MAXCCALLS>>3))) |
| 379 | luaD_throw(L, LUA_ERRERR); /* error while handing stack error */ | 381 | luaD_throw(L, LUA_ERRERR); /* error while handing stack error */ |
| 380 | } | 382 | } |
| 381 | if (luaD_precall(L, func, nResults) == PCRLUA) /* is a Lua function? */ | 383 | if (!luaD_precall(L, func, nResults)) /* is a Lua function? */ |
| 382 | luaV_execute(L, 1); /* call it */ | 384 | luaV_execute(L, 1); /* call it */ |
| 383 | g->nCcalls--; | 385 | g->nCcalls--; |
| 384 | luaC_checkGC(L); | 386 | luaC_checkGC(L); |
| @@ -390,8 +392,8 @@ static void resume (lua_State *L, void *ud) { | |||
| 390 | CallInfo *ci = L->ci; | 392 | CallInfo *ci = L->ci; |
| 391 | if (L->status == LUA_OK) { /* start coroutine? */ | 393 | if (L->status == LUA_OK) { /* start coroutine? */ |
| 392 | lua_assert(ci == L->base_ci && firstArg > L->base); | 394 | lua_assert(ci == L->base_ci && firstArg > L->base); |
| 393 | if (luaD_precall(L, firstArg - 1, LUA_MULTRET) != PCRLUA) | 395 | if (luaD_precall(L, firstArg - 1, LUA_MULTRET)) /* C function? */ |
| 394 | return; | 396 | return; /* done */ |
| 395 | } | 397 | } |
| 396 | else { /* resuming from previous yield */ | 398 | else { /* resuming from previous yield */ |
| 397 | lua_assert(L->status == LUA_YIELD); | 399 | lua_assert(L->status == LUA_YIELD); |
| @@ -434,14 +436,14 @@ LUA_API int lua_resume (lua_State *L, int nargs) { | |||
| 434 | return resume_error(L, "C stack overflow"); | 436 | return resume_error(L, "C stack overflow"); |
| 435 | L->baseCcalls = ++G(L)->nCcalls; | 437 | L->baseCcalls = ++G(L)->nCcalls; |
| 436 | status = luaD_rawrunprotected(L, resume, L->top - nargs); | 438 | status = luaD_rawrunprotected(L, resume, L->top - nargs); |
| 437 | if (status != LUA_OK) { /* error? */ | 439 | if (status != LUA_OK && status != LUA_YIELD) { /* error? */ |
| 438 | L->status = cast_byte(status); /* mark thread as `dead' */ | 440 | L->status = cast_byte(status); /* mark thread as `dead' */ |
| 439 | luaD_seterrorobj(L, status, L->top); | 441 | luaD_seterrorobj(L, status, L->top); |
| 440 | L->ci->top = L->top; | 442 | L->ci->top = L->top; |
| 441 | } | 443 | } |
| 442 | else { | 444 | else { |
| 443 | lua_assert(L->baseCcalls == G(L)->nCcalls); | 445 | lua_assert(L->baseCcalls == G(L)->nCcalls); |
| 444 | status = L->status; | 446 | lua_assert(status == L->status); |
| 445 | } | 447 | } |
| 446 | --G(L)->nCcalls; | 448 | --G(L)->nCcalls; |
| 447 | L->baseCcalls = 0; | 449 | L->baseCcalls = 0; |
| @@ -457,8 +459,11 @@ LUA_API int lua_yield (lua_State *L, int nresults) { | |||
| 457 | luaG_runerror(L, "attempt to yield across metamethod/C-call boundary"); | 459 | luaG_runerror(L, "attempt to yield across metamethod/C-call boundary"); |
| 458 | L->base = L->top - nresults; /* protect stack slots below */ | 460 | L->base = L->top - nresults; /* protect stack slots below */ |
| 459 | L->status = LUA_YIELD; | 461 | L->status = LUA_YIELD; |
| 462 | if (!isLua(L->ci)) /* not inside a hook? */ | ||
| 463 | luaD_throw(L, LUA_YIELD); | ||
| 464 | lua_assert(L->ci->status & 1); /* must be inside a hook */ | ||
| 460 | lua_unlock(L); | 465 | lua_unlock(L); |
| 461 | return -1; | 466 | return 0; /* otherwise, return to 'luaD_callhook' */ |
| 462 | } | 467 | } |
| 463 | 468 | ||
| 464 | 469 | ||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: ldo.h,v 2.8 2006/07/11 15:53:29 roberto Exp roberto $ | 2 | ** $Id: ldo.h,v 2.9 2008/07/03 14:24: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 | */ |
| @@ -28,12 +28,6 @@ | |||
| 28 | #define restoreci(L,n) ((CallInfo *)((char *)L->base_ci + (n))) | 28 | #define restoreci(L,n) ((CallInfo *)((char *)L->base_ci + (n))) |
| 29 | 29 | ||
| 30 | 30 | ||
| 31 | /* results from luaD_precall */ | ||
| 32 | #define PCRLUA 0 /* initiated a call to a Lua function */ | ||
| 33 | #define PCRC 1 /* did a call to a C function */ | ||
| 34 | #define PCRYIELD 2 /* C funtion yielded */ | ||
| 35 | |||
| 36 | |||
| 37 | /* type of protected functions, to be ran by `runprotected' */ | 31 | /* type of protected functions, to be ran by `runprotected' */ |
| 38 | typedef void (*Pfunc) (lua_State *L, void *ud); | 32 | typedef void (*Pfunc) (lua_State *L, void *ud); |
| 39 | 33 | ||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lvm.c,v 2.73 2007/09/10 17:59:32 roberto Exp roberto $ | 2 | ** $Id: lvm.c,v 2.74 2008/04/02 16:16:06 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 | */ |
| @@ -415,7 +415,7 @@ void luaV_execute (lua_State *L, int nexeccalls) { | |||
| 415 | traceexec(L); | 415 | traceexec(L); |
| 416 | if (L->status == LUA_YIELD) { /* did hook yield? */ | 416 | if (L->status == LUA_YIELD) { /* did hook yield? */ |
| 417 | L->savedpc--; /* undo increment */ | 417 | L->savedpc--; /* undo increment */ |
| 418 | return; | 418 | luaD_throw(L, LUA_YIELD); |
| 419 | } | 419 | } |
| 420 | base = L->base; | 420 | base = L->base; |
| 421 | } | 421 | } |
| @@ -595,51 +595,40 @@ void luaV_execute (lua_State *L, int nexeccalls) { | |||
| 595 | int b = GETARG_B(i); | 595 | int b = GETARG_B(i); |
| 596 | int nresults = GETARG_C(i) - 1; | 596 | int nresults = GETARG_C(i) - 1; |
| 597 | if (b != 0) L->top = ra+b; /* else previous instruction set top */ | 597 | if (b != 0) L->top = ra+b; /* else previous instruction set top */ |
| 598 | switch (luaD_precall(L, ra, nresults)) { | 598 | if (luaD_precall(L, ra, nresults)) { /* C function? */ |
| 599 | case PCRLUA: { | 599 | if (nresults >= 0) L->top = L->ci->top; /* adjust results */ |
| 600 | nexeccalls++; | 600 | base = L->base; |
| 601 | goto reentry; /* restart luaV_execute over new Lua function */ | 601 | continue; |
| 602 | } | 602 | } |
| 603 | case PCRC: { | 603 | else { /* Lua function */ |
| 604 | /* it was a C function (`precall' called it); adjust results */ | 604 | nexeccalls++; |
| 605 | if (nresults >= 0) L->top = L->ci->top; | 605 | goto reentry; /* restart luaV_execute over new Lua function */ |
| 606 | base = L->base; | ||
| 607 | continue; | ||
| 608 | } | ||
| 609 | default: { | ||
| 610 | return; /* yield */ | ||
| 611 | } | ||
| 612 | } | 606 | } |
| 613 | } | 607 | } |
| 614 | case OP_TAILCALL: { | 608 | case OP_TAILCALL: { |
| 615 | int b = GETARG_B(i); | 609 | int b = GETARG_B(i); |
| 616 | if (b != 0) L->top = ra+b; /* else previous instruction set top */ | 610 | if (b != 0) L->top = ra+b; /* else previous instruction set top */ |
| 617 | lua_assert(GETARG_C(i) - 1 == LUA_MULTRET); | 611 | lua_assert(GETARG_C(i) - 1 == LUA_MULTRET); |
| 618 | switch (luaD_precall(L, ra, LUA_MULTRET)) { | 612 | if (luaD_precall(L, ra, LUA_MULTRET)) { /* C function? */ |
| 619 | case PCRLUA: { | 613 | base = L->base; |
| 620 | /* tail call: put new frame in place of previous one */ | 614 | continue; |
| 621 | CallInfo *ci = L->ci - 1; /* previous frame */ | 615 | } |
| 622 | int aux; | 616 | else { |
| 623 | StkId func = ci->func; | 617 | /* tail call: put new frame in place of previous one */ |
| 624 | StkId pfunc = (ci+1)->func; /* previous function index */ | 618 | CallInfo *ci = L->ci - 1; /* previous frame */ |
| 625 | if (L->openupval) luaF_close(L, ci->base); | 619 | int aux; |
| 626 | L->base = ci->base = ci->func + ((ci+1)->base - pfunc); | 620 | StkId func = ci->func; |
| 627 | for (aux = 0; pfunc+aux < L->top; aux++) /* move frame down */ | 621 | StkId pfunc = (ci+1)->func; /* previous function index */ |
| 628 | setobjs2s(L, func+aux, pfunc+aux); | 622 | if (L->openupval) luaF_close(L, ci->base); |
| 629 | ci->top = L->top = func+aux; /* correct top */ | 623 | L->base = ci->base = ci->func + ((ci+1)->base - pfunc); |
| 630 | lua_assert(L->top == L->base + clvalue(func)->l.p->maxstacksize); | 624 | for (aux = 0; pfunc+aux < L->top; aux++) /* move frame down */ |
| 631 | ci->savedpc = L->savedpc; | 625 | setobjs2s(L, func+aux, pfunc+aux); |
| 632 | ci->tailcalls++; /* one more call lost */ | 626 | ci->top = L->top = func+aux; /* correct top */ |
| 633 | L->ci--; /* remove new frame */ | 627 | lua_assert(L->top == L->base + clvalue(func)->l.p->maxstacksize); |
| 634 | goto reentry; | 628 | ci->savedpc = L->savedpc; |
| 635 | } | 629 | ci->tailcalls++; /* one more call lost */ |
| 636 | case PCRC: { /* it was a C function (`precall' called it) */ | 630 | L->ci--; /* remove new frame */ |
| 637 | base = L->base; | 631 | goto reentry; |
| 638 | continue; | ||
| 639 | } | ||
| 640 | default: { | ||
| 641 | return; /* yield */ | ||
| 642 | } | ||
| 643 | } | 632 | } |
| 644 | } | 633 | } |
| 645 | case OP_RETURN: { | 634 | case OP_RETURN: { |
