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 | } |