aboutsummaryrefslogtreecommitdiff
path: root/ldo.c
diff options
context:
space:
mode:
Diffstat (limited to 'ldo.c')
-rw-r--r--ldo.c54
1 files changed, 30 insertions, 24 deletions
diff --git a/ldo.c b/ldo.c
index cbb1e0f3..3b01c8fb 100644
--- a/ldo.c
+++ b/ldo.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: ldo.c,v 2.165 2017/11/02 11:28:56 roberto Exp roberto $ 2** $Id: ldo.c,v 2.166 2017/11/03 12:12:30 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*/
@@ -280,17 +280,19 @@ void luaD_hook (lua_State *L, int event, int line) {
280} 280}
281 281
282 282
283static void callhook (lua_State *L, CallInfo *ci) { 283static void callhook (lua_State *L) {
284 int hook = LUA_HOOKCALL; 284 int hook = LUA_HOOKCALL;
285 StkId previous = L->func - L->func->stkci.previous; 285 StkId func = L->func;
286 ci->u.l.savedpc++; /* hooks assume 'pc' is already incremented */ 286 StkId previous = func - L->func->stkci.previous;
287 func->stkci.u.l.savedpc++; /* hooks assume 'pc' is already incremented */
287 if (isLua(previous) && 288 if (isLua(previous) &&
288 GET_OPCODE(*(ci->previous->u.l.savedpc - 1)) == OP_TAILCALL) { 289 GET_OPCODE(*(previous->stkci.u.l.savedpc - 1)) == OP_TAILCALL) {
289 callstatus(L->func) |= CIST_TAIL; 290 callstatus(L->func) |= CIST_TAIL;
290 hook = LUA_HOOKTAILCALL; 291 hook = LUA_HOOKTAILCALL;
291 } 292 }
292 luaD_hook(L, hook, -1); 293 luaD_hook(L, hook, -1);
293 ci->u.l.savedpc--; /* correct 'pc' */ 294 func = L->func; /* previous call can change stack */
295 func->stkci.u.l.savedpc--; /* correct 'pc' */
294} 296}
295 297
296 298
@@ -369,11 +371,13 @@ int luaD_poscall (lua_State *L, CallInfo *ci, StkId firstResult, int nres) {
369 ptrdiff_t fr = savestack(L, firstResult); /* hook may change stack */ 371 ptrdiff_t fr = savestack(L, firstResult); /* hook may change stack */
370 luaD_hook(L, LUA_HOOKRET, -1); 372 luaD_hook(L, LUA_HOOKRET, -1);
371 firstResult = restorestack(L, fr); 373 firstResult = restorestack(L, fr);
374 res = L->func;
372 } 375 }
373 L->oldpc = ci->previous->u.l.savedpc; /* 'oldpc' for caller function */ 376 /* 'oldpc' for caller function */
377 L->oldpc = (res - res->stkci.previous)->stkci.u.l.savedpc;
374 } 378 }
375 L->ci = ci->previous; /* back to caller */ 379 L->ci = ci->previous; /* back to caller */
376 L->func -= L->func->stkci.previous; 380 L->func = res - res->stkci.previous;
377 lua_assert(L->func == L->ci->func); 381 lua_assert(L->func == L->ci->func);
378 /* move results to proper place */ 382 /* move results to proper place */
379 return moveresults(L, firstResult, res, nres, wanted); 383 return moveresults(L, firstResult, res, nres, wanted);
@@ -436,10 +440,10 @@ int luaD_precall (lua_State *L, StkId func, int nresults) {
436 L->func = ci->func = func; 440 L->func = ci->func = func;
437 L->top = func + 1 + fsize; 441 L->top = func + 1 + fsize;
438 lua_assert(functop(func) <= L->stack_last); 442 lua_assert(functop(func) <= L->stack_last);
439 ci->u.l.savedpc = p->code; /* starting point */ 443 func->stkci.u.l.savedpc = p->code; /* starting point */
440 callstatus(func) = 0; 444 callstatus(func) = 0;
441 if (L->hookmask & LUA_MASKCALL) 445 if (L->hookmask & LUA_MASKCALL)
442 callhook(L, ci); 446 callhook(L);
443 return 0; 447 return 0;
444 } 448 }
445 default: { /* not a function */ 449 default: { /* not a function */
@@ -500,18 +504,19 @@ static void finishCcall (lua_State *L, int status) {
500 StkId func = L->func; 504 StkId func = L->func;
501 int n; 505 int n;
502 /* must have a continuation and must be able to call it */ 506 /* must have a continuation and must be able to call it */
503 lua_assert(ci->u.c.k != NULL && L->nny == 0); 507 lua_assert(func->stkci.u.c.k != NULL && L->nny == 0);
504 /* error status can only happen in a protected call */ 508 /* error status can only happen in a protected call */
505 lua_assert((callstatus(func) & CIST_YPCALL) || status == LUA_YIELD); 509 lua_assert((callstatus(func) & CIST_YPCALL) || status == LUA_YIELD);
506 if (callstatus(func) & CIST_YPCALL) { /* was inside a pcall? */ 510 if (callstatus(func) & CIST_YPCALL) { /* was inside a pcall? */
507 callstatus(func) &= ~CIST_YPCALL; /* continuation is also inside it */ 511 callstatus(func) &= ~CIST_YPCALL; /* continuation is also inside it */
508 L->errfunc = ci->u.c.old_errfunc; /* with the same error function */ 512 L->errfunc = func->stkci.u.c.old_errfunc; /* with same error function */
509 } 513 }
510 /* finish 'lua_callk'/'lua_pcall'; CIST_YPCALL and 'errfunc' already 514 /* finish 'lua_callk'/'lua_pcall'; CIST_YPCALL and 'errfunc' already
511 handled */ 515 handled */
512 adjustresults(L, func->stkci.nresults); 516 adjustresults(L, func->stkci.nresults);
513 lua_unlock(L); 517 lua_unlock(L);
514 n = (*ci->u.c.k)(L, status, ci->u.c.ctx); /* call continuation function */ 518 /* call continuation function */
519 n = (*func->stkci.u.c.k)(L, status, func->stkci.u.c.ctx);
515 lua_lock(L); 520 lua_lock(L);
516 api_checknelems(L, n); 521 api_checknelems(L, n);
517 luaD_poscall(L, ci, L->top - n, n); /* finish 'luaD_precall' */ 522 luaD_poscall(L, ci, L->top - n, n); /* finish 'luaD_precall' */
@@ -564,7 +569,7 @@ static int recover (lua_State *L, int status) {
564 CallInfo *ci = findpcall(L); 569 CallInfo *ci = findpcall(L);
565 if (ci == NULL) return 0; /* no recovery point */ 570 if (ci == NULL) return 0; /* no recovery point */
566 /* "finish" luaD_pcall */ 571 /* "finish" luaD_pcall */
567 oldtop = restorestack(L, ci->u2.funcidx); 572 oldtop = ci->func + ci->func->stkci.u2.funcidx;
568 luaF_close(L, oldtop); 573 luaF_close(L, oldtop);
569 seterrorobj(L, status, oldtop); 574 seterrorobj(L, status, oldtop);
570 L->ci = ci; 575 L->ci = ci;
@@ -572,7 +577,7 @@ static int recover (lua_State *L, int status) {
572 L->allowhook = getoah(callstatus(L->func)); /* restore original 'allowhook' */ 577 L->allowhook = getoah(callstatus(L->func)); /* restore original 'allowhook' */
573 L->nny = 0; /* should be zero to be yieldable */ 578 L->nny = 0; /* should be zero to be yieldable */
574 luaD_shrinkstack(L); 579 luaD_shrinkstack(L);
575 L->errfunc = ci->u.c.old_errfunc; 580 L->errfunc = ci->func->stkci.u.c.old_errfunc;
576 return 1; /* continue running the coroutine */ 581 return 1; /* continue running the coroutine */
577} 582}
578 583
@@ -602,6 +607,7 @@ static void resume (lua_State *L, void *ud) {
602 int n = *(cast(int*, ud)); /* number of arguments */ 607 int n = *(cast(int*, ud)); /* number of arguments */
603 StkId firstArg = L->top - n; /* first argument */ 608 StkId firstArg = L->top - n; /* first argument */
604 CallInfo *ci = L->ci; 609 CallInfo *ci = L->ci;
610 StkId func = L->func;
605 if (L->status == LUA_OK) { /* starting a coroutine? */ 611 if (L->status == LUA_OK) { /* starting a coroutine? */
606 if (!luaD_precall(L, firstArg - 1, LUA_MULTRET)) /* Lua function? */ 612 if (!luaD_precall(L, firstArg - 1, LUA_MULTRET)) /* Lua function? */
607 luaV_execute(L); /* call it */ 613 luaV_execute(L); /* call it */
@@ -609,12 +615,13 @@ static void resume (lua_State *L, void *ud) {
609 else { /* resuming from previous yield */ 615 else { /* resuming from previous yield */
610 lua_assert(L->status == LUA_YIELD); 616 lua_assert(L->status == LUA_YIELD);
611 L->status = LUA_OK; /* mark that it is running (again) */ 617 L->status = LUA_OK; /* mark that it is running (again) */
612 if (isLua(L->func)) /* yielded inside a hook? */ 618 if (isLua(func)) /* yielded inside a hook? */
613 luaV_execute(L); /* just continue running Lua code */ 619 luaV_execute(L); /* just continue running Lua code */
614 else { /* 'common' yield */ 620 else { /* 'common' yield */
615 if (ci->u.c.k != NULL) { /* does it have a continuation function? */ 621 if (func->stkci.u.c.k != NULL) { /* does it have a continuation? */
616 lua_unlock(L); 622 lua_unlock(L);
617 n = (*ci->u.c.k)(L, LUA_YIELD, ci->u.c.ctx); /* call continuation */ 623 /* call continuation */
624 n = (*func->stkci.u.c.k)(L, LUA_YIELD, func->stkci.u.c.ctx);
618 lua_lock(L); 625 lua_lock(L);
619 api_checknelems(L, n); 626 api_checknelems(L, n);
620 firstArg = L->top - n; /* yield results come from continuation */ 627 firstArg = L->top - n; /* yield results come from continuation */
@@ -658,7 +665,7 @@ LUA_API int lua_resume (lua_State *L, lua_State *from, int nargs,
658 } 665 }
659 else lua_assert(status == L->status); /* normal end or yield */ 666 else lua_assert(status == L->status); /* normal end or yield */
660 } 667 }
661 *nresults = (status == LUA_YIELD) ? L->ci->u2.nyield 668 *nresults = (status == LUA_YIELD) ? L->func->stkci.u2.nyield
662 : L->top - (L->func + 1); 669 : L->top - (L->func + 1);
663 L->nny = oldnny; /* restore 'nny' */ 670 L->nny = oldnny; /* restore 'nny' */
664 L->nCcalls--; 671 L->nCcalls--;
@@ -675,7 +682,6 @@ LUA_API int lua_isyieldable (lua_State *L) {
675 682
676LUA_API int lua_yieldk (lua_State *L, int nresults, lua_KContext ctx, 683LUA_API int lua_yieldk (lua_State *L, int nresults, lua_KContext ctx,
677 lua_KFunction k) { 684 lua_KFunction k) {
678 CallInfo *ci = L->ci;
679 StkId func = L->func; 685 StkId func = L->func;
680 luai_userstateyield(L, nresults); 686 luai_userstateyield(L, nresults);
681 lua_lock(L); 687 lua_lock(L);
@@ -689,12 +695,12 @@ LUA_API int lua_yieldk (lua_State *L, int nresults, lua_KContext ctx,
689 L->status = LUA_YIELD; 695 L->status = LUA_YIELD;
690 if (isLua(func)) { /* inside a hook? */ 696 if (isLua(func)) { /* inside a hook? */
691 api_check(L, k == NULL, "hooks cannot continue after yielding"); 697 api_check(L, k == NULL, "hooks cannot continue after yielding");
692 ci->u2.nyield = 0; /* no results */ 698 func->stkci.u2.nyield = 0; /* no results */
693 } 699 }
694 else { 700 else {
695 if ((ci->u.c.k = k) != NULL) /* is there a continuation? */ 701 if ((func->stkci.u.c.k = k) != NULL) /* is there a continuation? */
696 ci->u.c.ctx = ctx; /* save context */ 702 func->stkci.u.c.ctx = ctx; /* save context */
697 ci->u2.nyield = nresults; /* save number of results */ 703 func->stkci.u2.nyield = nresults; /* save number of results */
698 luaD_throw(L, LUA_YIELD); 704 luaD_throw(L, LUA_YIELD);
699 } 705 }
700 lua_assert(callstatus(func) & CIST_HOOKED); /* must be inside a hook */ 706 lua_assert(callstatus(func) & CIST_HOOKED); /* must be inside a hook */