diff options
| author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2017-11-03 10:12:30 -0200 |
|---|---|---|
| committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2017-11-03 10:12:30 -0200 |
| commit | 54eb35a8aa0f60265cf1b4764beabe1199d66f42 (patch) | |
| tree | 83bc4049d312bdbe0b8e78ed1745839fcf9a5a03 /ldo.c | |
| parent | ba36180fd7b68341ad57e0fbe7a55cdfb334908d (diff) | |
| download | lua-54eb35a8aa0f60265cf1b4764beabe1199d66f42.tar.gz lua-54eb35a8aa0f60265cf1b4764beabe1199d66f42.tar.bz2 lua-54eb35a8aa0f60265cf1b4764beabe1199d66f42.zip | |
more fields moved out of 'CallInfo'
Diffstat (limited to 'ldo.c')
| -rw-r--r-- | ldo.c | 80 |
1 files changed, 43 insertions, 37 deletions
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: ldo.c,v 2.164 2017/11/01 18:20:48 roberto Exp roberto $ | 2 | ** $Id: ldo.c,v 2.165 2017/11/02 11:28:56 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 | */ |
| @@ -123,8 +123,8 @@ l_noret luaD_throw (lua_State *L, int errcode) { | |||
| 123 | else { /* no handler at all; abort */ | 123 | else { /* no handler at all; abort */ |
| 124 | if (g->panic) { /* panic function? */ | 124 | if (g->panic) { /* panic function? */ |
| 125 | seterrorobj(L, errcode, L->top); /* assume EXTRA_STACK */ | 125 | seterrorobj(L, errcode, L->top); /* assume EXTRA_STACK */ |
| 126 | if (L->ci->top < L->top) | 126 | if (functop(L->func) < L->top) /* check invariant */ |
| 127 | L->ci->top = L->top; /* pushing msg. can break this invariant */ | 127 | setfunctop(L->func, L->top); |
| 128 | lua_unlock(L); | 128 | lua_unlock(L); |
| 129 | g->panic(L); /* call panic function (last chance to jump out) */ | 129 | g->panic(L); /* call panic function (last chance to jump out) */ |
| 130 | } | 130 | } |
| @@ -164,7 +164,6 @@ static void correctstack (lua_State *L, StkId oldstack) { | |||
| 164 | for (up = L->openupval; up != NULL; up = up->u.open.next) | 164 | for (up = L->openupval; up != NULL; up = up->u.open.next) |
| 165 | up->v = s2v((uplevel(up) - oldstack) + L->stack); | 165 | up->v = s2v((uplevel(up) - oldstack) + L->stack); |
| 166 | for (ci = L->ci; ci != NULL; ci = ci->previous) { | 166 | for (ci = L->ci; ci != NULL; ci = ci->previous) { |
| 167 | ci->top = (ci->top - oldstack) + L->stack; | ||
| 168 | ci->func = (ci->func - oldstack) + L->stack; | 167 | ci->func = (ci->func - oldstack) + L->stack; |
| 169 | } | 168 | } |
| 170 | } | 169 | } |
| @@ -208,10 +207,11 @@ void luaD_growstack (lua_State *L, int n) { | |||
| 208 | 207 | ||
| 209 | 208 | ||
| 210 | static int stackinuse (lua_State *L) { | 209 | static int stackinuse (lua_State *L) { |
| 211 | CallInfo *ci; | ||
| 212 | StkId lim = L->top; | 210 | StkId lim = L->top; |
| 213 | for (ci = L->ci; ci != NULL; ci = ci->previous) { | 211 | StkId func = L->func; |
| 214 | if (lim < ci->top) lim = ci->top; | 212 | for (; func->stkci.previous != 0; func -= func->stkci.previous) { |
| 213 | if (lim < functop(func)) | ||
| 214 | lim = functop(func); | ||
| 215 | } | 215 | } |
| 216 | lua_assert(lim <= L->stack_last); | 216 | lua_assert(lim <= L->stack_last); |
| 217 | return cast_int(lim - L->stack) + 1; /* part of stack in use */ | 217 | return cast_int(lim - L->stack) + 1; /* part of stack in use */ |
| @@ -255,34 +255,38 @@ void luaD_hook (lua_State *L, int event, int line) { | |||
| 255 | if (hook && L->allowhook) { /* make sure there is a hook */ | 255 | if (hook && L->allowhook) { /* make sure there is a hook */ |
| 256 | CallInfo *ci = L->ci; | 256 | CallInfo *ci = L->ci; |
| 257 | ptrdiff_t top = savestack(L, L->top); | 257 | ptrdiff_t top = savestack(L, L->top); |
| 258 | ptrdiff_t ci_top = savestack(L, ci->top); | 258 | int origframesize = L->func->stkci.framesize; |
| 259 | int tmpframesize; /* frame size to run hook */ | ||
| 259 | lua_Debug ar; | 260 | lua_Debug ar; |
| 260 | ar.event = event; | 261 | ar.event = event; |
| 261 | ar.currentline = line; | 262 | ar.currentline = line; |
| 262 | ar.i_ci = ci; | 263 | ar.i_ci = ci; |
| 263 | luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */ | 264 | luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */ |
| 264 | ci->top = L->top + LUA_MINSTACK; | 265 | tmpframesize = L->top - L->func + LUA_MINSTACK; |
| 265 | lua_assert(ci->top <= L->stack_last); | 266 | if (tmpframesize > origframesize) /* need to grow frame? */ |
| 267 | L->func->stkci.framesize = tmpframesize; | ||
| 268 | lua_assert(functop(L->func) <= L->stack_last); | ||
| 266 | L->allowhook = 0; /* cannot call hooks inside a hook */ | 269 | L->allowhook = 0; /* cannot call hooks inside a hook */ |
| 267 | ci->callstatus |= CIST_HOOKED; | 270 | callstatus(L->func) |= CIST_HOOKED; |
| 268 | lua_unlock(L); | 271 | lua_unlock(L); |
| 269 | (*hook)(L, &ar); | 272 | (*hook)(L, &ar); |
| 270 | lua_lock(L); | 273 | lua_lock(L); |
| 271 | lua_assert(!L->allowhook); | 274 | lua_assert(!L->allowhook); |
| 272 | L->allowhook = 1; | 275 | L->allowhook = 1; |
| 273 | ci->top = restorestack(L, ci_top); | 276 | L->func->stkci.framesize = origframesize; |
| 274 | L->top = restorestack(L, top); | 277 | L->top = restorestack(L, top); |
| 275 | ci->callstatus &= ~CIST_HOOKED; | 278 | callstatus(L->func) &= ~CIST_HOOKED; |
| 276 | } | 279 | } |
| 277 | } | 280 | } |
| 278 | 281 | ||
| 279 | 282 | ||
| 280 | static void callhook (lua_State *L, CallInfo *ci) { | 283 | static void callhook (lua_State *L, CallInfo *ci) { |
| 281 | int hook = LUA_HOOKCALL; | 284 | int hook = LUA_HOOKCALL; |
| 285 | StkId previous = L->func - L->func->stkci.previous; | ||
| 282 | ci->u.l.savedpc++; /* hooks assume 'pc' is already incremented */ | 286 | ci->u.l.savedpc++; /* hooks assume 'pc' is already incremented */ |
| 283 | if (isLua(ci->previous) && | 287 | if (isLua(previous) && |
| 284 | GET_OPCODE(*(ci->previous->u.l.savedpc - 1)) == OP_TAILCALL) { | 288 | GET_OPCODE(*(ci->previous->u.l.savedpc - 1)) == OP_TAILCALL) { |
| 285 | ci->callstatus |= CIST_TAIL; | 289 | callstatus(L->func) |= CIST_TAIL; |
| 286 | hook = LUA_HOOKTAILCALL; | 290 | hook = LUA_HOOKTAILCALL; |
| 287 | } | 291 | } |
| 288 | luaD_hook(L, hook, -1); | 292 | luaD_hook(L, hook, -1); |
| @@ -358,8 +362,8 @@ static int moveresults (lua_State *L, StkId firstResult, StkId res, | |||
| 358 | ** wanted multiple (variable number of) results. | 362 | ** wanted multiple (variable number of) results. |
| 359 | */ | 363 | */ |
| 360 | int luaD_poscall (lua_State *L, CallInfo *ci, StkId firstResult, int nres) { | 364 | int luaD_poscall (lua_State *L, CallInfo *ci, StkId firstResult, int nres) { |
| 361 | StkId res; | 365 | StkId res = L->func; /* res == final position of 1st result */ |
| 362 | int wanted = ci->nresults; | 366 | int wanted = res->stkci.nresults; |
| 363 | if (L->hookmask & (LUA_MASKRET | LUA_MASKLINE)) { | 367 | if (L->hookmask & (LUA_MASKRET | LUA_MASKLINE)) { |
| 364 | if (L->hookmask & LUA_MASKRET) { | 368 | if (L->hookmask & LUA_MASKRET) { |
| 365 | ptrdiff_t fr = savestack(L, firstResult); /* hook may change stack */ | 369 | ptrdiff_t fr = savestack(L, firstResult); /* hook may change stack */ |
| @@ -368,7 +372,6 @@ int luaD_poscall (lua_State *L, CallInfo *ci, StkId firstResult, int nres) { | |||
| 368 | } | 372 | } |
| 369 | L->oldpc = ci->previous->u.l.savedpc; /* 'oldpc' for caller function */ | 373 | L->oldpc = ci->previous->u.l.savedpc; /* 'oldpc' for caller function */ |
| 370 | } | 374 | } |
| 371 | res = L->func; /* res == final position of 1st result */ | ||
| 372 | L->ci = ci->previous; /* back to caller */ | 375 | L->ci = ci->previous; /* back to caller */ |
| 373 | L->func -= L->func->stkci.previous; | 376 | L->func -= L->func->stkci.previous; |
| 374 | lua_assert(L->func == L->ci->func); | 377 | lua_assert(L->func == L->ci->func); |
| @@ -402,12 +405,12 @@ int luaD_precall (lua_State *L, StkId func, int nresults) { | |||
| 402 | int n; /* number of returns */ | 405 | int n; /* number of returns */ |
| 403 | checkstackp(L, LUA_MINSTACK, func); /* ensure minimum stack size */ | 406 | checkstackp(L, LUA_MINSTACK, func); /* ensure minimum stack size */ |
| 404 | ci = next_ci(L); /* now 'enter' new function */ | 407 | ci = next_ci(L); /* now 'enter' new function */ |
| 405 | ci->nresults = nresults; | 408 | func->stkci.nresults = nresults; |
| 406 | func->stkci.previous = func - L->func; | 409 | func->stkci.previous = func - L->func; |
| 407 | L->func = ci->func = func; | 410 | L->func = ci->func = func; |
| 408 | ci->top = L->top + LUA_MINSTACK; | 411 | setfunctop(func, L->top + LUA_MINSTACK); |
| 409 | lua_assert(ci->top <= L->stack_last); | 412 | lua_assert(functop(func) <= L->stack_last); |
| 410 | ci->callstatus = 0; | 413 | callstatus(func) = 0; |
| 411 | if (L->hookmask & LUA_MASKCALL) | 414 | if (L->hookmask & LUA_MASKCALL) |
| 412 | luaD_hook(L, LUA_HOOKCALL, -1); | 415 | luaD_hook(L, LUA_HOOKCALL, -1); |
| 413 | lua_unlock(L); | 416 | lua_unlock(L); |
| @@ -427,13 +430,14 @@ int luaD_precall (lua_State *L, StkId func, int nresults) { | |||
| 427 | if (p->is_vararg) | 430 | if (p->is_vararg) |
| 428 | luaT_adjustvarargs(L, p, n); | 431 | luaT_adjustvarargs(L, p, n); |
| 429 | ci = next_ci(L); /* now 'enter' new function */ | 432 | ci = next_ci(L); /* now 'enter' new function */ |
| 430 | ci->nresults = nresults; | 433 | func->stkci.nresults = nresults; |
| 431 | func->stkci.previous = func - L->func; | 434 | func->stkci.previous = func - L->func; |
| 435 | func->stkci.framesize = fsize + 1; /* size includes function itself */ | ||
| 432 | L->func = ci->func = func; | 436 | L->func = ci->func = func; |
| 433 | L->top = ci->top = func + 1 + fsize; | 437 | L->top = func + 1 + fsize; |
| 434 | lua_assert(ci->top <= L->stack_last); | 438 | lua_assert(functop(func) <= L->stack_last); |
| 435 | ci->u.l.savedpc = p->code; /* starting point */ | 439 | ci->u.l.savedpc = p->code; /* starting point */ |
| 436 | ci->callstatus = CIST_LUA; | 440 | callstatus(func) = 0; |
| 437 | if (L->hookmask & LUA_MASKCALL) | 441 | if (L->hookmask & LUA_MASKCALL) |
| 438 | callhook(L, ci); | 442 | callhook(L, ci); |
| 439 | return 0; | 443 | return 0; |
| @@ -493,18 +497,19 @@ void luaD_callnoyield (lua_State *L, StkId func, int nResults) { | |||
| 493 | */ | 497 | */ |
| 494 | static void finishCcall (lua_State *L, int status) { | 498 | static void finishCcall (lua_State *L, int status) { |
| 495 | CallInfo *ci = L->ci; | 499 | CallInfo *ci = L->ci; |
| 500 | StkId func = L->func; | ||
| 496 | int n; | 501 | int n; |
| 497 | /* must have a continuation and must be able to call it */ | 502 | /* must have a continuation and must be able to call it */ |
| 498 | lua_assert(ci->u.c.k != NULL && L->nny == 0); | 503 | lua_assert(ci->u.c.k != NULL && L->nny == 0); |
| 499 | /* error status can only happen in a protected call */ | 504 | /* error status can only happen in a protected call */ |
| 500 | lua_assert((ci->callstatus & CIST_YPCALL) || status == LUA_YIELD); | 505 | lua_assert((callstatus(func) & CIST_YPCALL) || status == LUA_YIELD); |
| 501 | if (ci->callstatus & CIST_YPCALL) { /* was inside a pcall? */ | 506 | if (callstatus(func) & CIST_YPCALL) { /* was inside a pcall? */ |
| 502 | ci->callstatus &= ~CIST_YPCALL; /* continuation is also inside it */ | 507 | callstatus(func) &= ~CIST_YPCALL; /* continuation is also inside it */ |
| 503 | L->errfunc = ci->u.c.old_errfunc; /* with the same error function */ | 508 | L->errfunc = ci->u.c.old_errfunc; /* with the same error function */ |
| 504 | } | 509 | } |
| 505 | /* finish 'lua_callk'/'lua_pcall'; CIST_YPCALL and 'errfunc' already | 510 | /* finish 'lua_callk'/'lua_pcall'; CIST_YPCALL and 'errfunc' already |
| 506 | handled */ | 511 | handled */ |
| 507 | adjustresults(L, ci->nresults); | 512 | adjustresults(L, func->stkci.nresults); |
| 508 | lua_unlock(L); | 513 | lua_unlock(L); |
| 509 | n = (*ci->u.c.k)(L, status, ci->u.c.ctx); /* call continuation function */ | 514 | n = (*ci->u.c.k)(L, status, ci->u.c.ctx); /* call continuation function */ |
| 510 | lua_lock(L); | 515 | lua_lock(L); |
| @@ -525,7 +530,7 @@ static void unroll (lua_State *L, void *ud) { | |||
| 525 | if (ud != NULL) /* error status? */ | 530 | if (ud != NULL) /* error status? */ |
| 526 | finishCcall(L, *(int *)ud); /* finish 'lua_pcallk' callee */ | 531 | finishCcall(L, *(int *)ud); /* finish 'lua_pcallk' callee */ |
| 527 | while (L->ci != &L->base_ci) { /* something in the stack */ | 532 | while (L->ci != &L->base_ci) { /* something in the stack */ |
| 528 | if (!isLua(L->ci)) /* C function? */ | 533 | if (!isLua(L->func)) /* C function? */ |
| 529 | finishCcall(L, LUA_YIELD); /* complete its execution */ | 534 | finishCcall(L, LUA_YIELD); /* complete its execution */ |
| 530 | else { /* Lua function */ | 535 | else { /* Lua function */ |
| 531 | luaV_finishOp(L); /* finish interrupted instruction */ | 536 | luaV_finishOp(L); /* finish interrupted instruction */ |
| @@ -542,7 +547,7 @@ static void unroll (lua_State *L, void *ud) { | |||
| 542 | static CallInfo *findpcall (lua_State *L) { | 547 | static CallInfo *findpcall (lua_State *L) { |
| 543 | CallInfo *ci; | 548 | CallInfo *ci; |
| 544 | for (ci = L->ci; ci != NULL; ci = ci->previous) { /* search for a pcall */ | 549 | for (ci = L->ci; ci != NULL; ci = ci->previous) { /* search for a pcall */ |
| 545 | if (ci->callstatus & CIST_YPCALL) | 550 | if (callstatus(ci->func) & CIST_YPCALL) |
| 546 | return ci; | 551 | return ci; |
| 547 | } | 552 | } |
| 548 | return NULL; /* no pending pcall */ | 553 | return NULL; /* no pending pcall */ |
| @@ -564,7 +569,7 @@ static int recover (lua_State *L, int status) { | |||
| 564 | seterrorobj(L, status, oldtop); | 569 | seterrorobj(L, status, oldtop); |
| 565 | L->ci = ci; | 570 | L->ci = ci; |
| 566 | L->func = ci->func; | 571 | L->func = ci->func; |
| 567 | L->allowhook = getoah(ci->callstatus); /* restore original 'allowhook' */ | 572 | L->allowhook = getoah(callstatus(L->func)); /* restore original 'allowhook' */ |
| 568 | L->nny = 0; /* should be zero to be yieldable */ | 573 | L->nny = 0; /* should be zero to be yieldable */ |
| 569 | luaD_shrinkstack(L); | 574 | luaD_shrinkstack(L); |
| 570 | L->errfunc = ci->u.c.old_errfunc; | 575 | L->errfunc = ci->u.c.old_errfunc; |
| @@ -604,7 +609,7 @@ static void resume (lua_State *L, void *ud) { | |||
| 604 | else { /* resuming from previous yield */ | 609 | else { /* resuming from previous yield */ |
| 605 | lua_assert(L->status == LUA_YIELD); | 610 | lua_assert(L->status == LUA_YIELD); |
| 606 | L->status = LUA_OK; /* mark that it is running (again) */ | 611 | L->status = LUA_OK; /* mark that it is running (again) */ |
| 607 | if (isLua(ci)) /* yielded inside a hook? */ | 612 | if (isLua(L->func)) /* yielded inside a hook? */ |
| 608 | luaV_execute(L); /* just continue running Lua code */ | 613 | luaV_execute(L); /* just continue running Lua code */ |
| 609 | else { /* 'common' yield */ | 614 | else { /* 'common' yield */ |
| 610 | if (ci->u.c.k != NULL) { /* does it have a continuation function? */ | 615 | if (ci->u.c.k != NULL) { /* does it have a continuation function? */ |
| @@ -649,7 +654,7 @@ LUA_API int lua_resume (lua_State *L, lua_State *from, int nargs, | |||
| 649 | if (errorstatus(status)) { /* unrecoverable error? */ | 654 | if (errorstatus(status)) { /* unrecoverable error? */ |
| 650 | L->status = cast_byte(status); /* mark thread as 'dead' */ | 655 | L->status = cast_byte(status); /* mark thread as 'dead' */ |
| 651 | seterrorobj(L, status, L->top); /* push error message */ | 656 | seterrorobj(L, status, L->top); /* push error message */ |
| 652 | L->ci->top = L->top; | 657 | L->func->stkci.framesize = L->top - L->func; |
| 653 | } | 658 | } |
| 654 | else lua_assert(status == L->status); /* normal end or yield */ | 659 | else lua_assert(status == L->status); /* normal end or yield */ |
| 655 | } | 660 | } |
| @@ -671,6 +676,7 @@ LUA_API int lua_isyieldable (lua_State *L) { | |||
| 671 | LUA_API int lua_yieldk (lua_State *L, int nresults, lua_KContext ctx, | 676 | LUA_API int lua_yieldk (lua_State *L, int nresults, lua_KContext ctx, |
| 672 | lua_KFunction k) { | 677 | lua_KFunction k) { |
| 673 | CallInfo *ci = L->ci; | 678 | CallInfo *ci = L->ci; |
| 679 | StkId func = L->func; | ||
| 674 | luai_userstateyield(L, nresults); | 680 | luai_userstateyield(L, nresults); |
| 675 | lua_lock(L); | 681 | lua_lock(L); |
| 676 | api_checknelems(L, nresults); | 682 | api_checknelems(L, nresults); |
| @@ -681,7 +687,7 @@ LUA_API int lua_yieldk (lua_State *L, int nresults, lua_KContext ctx, | |||
| 681 | luaG_runerror(L, "attempt to yield from outside a coroutine"); | 687 | luaG_runerror(L, "attempt to yield from outside a coroutine"); |
| 682 | } | 688 | } |
| 683 | L->status = LUA_YIELD; | 689 | L->status = LUA_YIELD; |
| 684 | if (isLua(ci)) { /* inside a hook? */ | 690 | if (isLua(func)) { /* inside a hook? */ |
| 685 | api_check(L, k == NULL, "hooks cannot continue after yielding"); | 691 | api_check(L, k == NULL, "hooks cannot continue after yielding"); |
| 686 | ci->u2.nyield = 0; /* no results */ | 692 | ci->u2.nyield = 0; /* no results */ |
| 687 | } | 693 | } |
| @@ -691,7 +697,7 @@ LUA_API int lua_yieldk (lua_State *L, int nresults, lua_KContext ctx, | |||
| 691 | ci->u2.nyield = nresults; /* save number of results */ | 697 | ci->u2.nyield = nresults; /* save number of results */ |
| 692 | luaD_throw(L, LUA_YIELD); | 698 | luaD_throw(L, LUA_YIELD); |
| 693 | } | 699 | } |
| 694 | lua_assert(ci->callstatus & CIST_HOOKED); /* must be inside a hook */ | 700 | lua_assert(callstatus(func) & CIST_HOOKED); /* must be inside a hook */ |
| 695 | lua_unlock(L); | 701 | lua_unlock(L); |
| 696 | return 0; /* return to 'luaD_hook' */ | 702 | return 0; /* return to 'luaD_hook' */ |
| 697 | } | 703 | } |
