diff options
| author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2017-11-07 11:25:26 -0200 |
|---|---|---|
| committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2017-11-07 11:25:26 -0200 |
| commit | ad0704e40cc7b3135fedc6d40a522addb039e090 (patch) | |
| tree | 4bcd104de4941239e09316efcee5e5e3566b8b81 /ldo.c | |
| parent | 5a3f26f85558bedfa439027919d928abfdd00b6d (diff) | |
| download | lua-ad0704e40cc7b3135fedc6d40a522addb039e090.tar.gz lua-ad0704e40cc7b3135fedc6d40a522addb039e090.tar.bz2 lua-ad0704e40cc7b3135fedc6d40a522addb039e090.zip | |
back to 'CallInfo' (no gains with its removal)
Diffstat (limited to 'ldo.c')
| -rw-r--r-- | ldo.c | 190 |
1 files changed, 95 insertions, 95 deletions
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: ldo.c,v 2.168 2017/11/03 20:41:05 roberto Exp roberto $ | 2 | ** $Id: ldo.c,v 2.165 2017/11/02 11:28:56 roberto Exp $ |
| 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 (functop(L->func) < L->top) /* check invariant */ | 126 | if (L->ci->top < L->top) |
| 127 | setfunctop(L->func, L->top); | 127 | L->ci->top = L->top; /* pushing msg. can break this invariant */ |
| 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 | } |
| @@ -157,11 +157,15 @@ int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud) { | |||
| 157 | ** =================================================================== | 157 | ** =================================================================== |
| 158 | */ | 158 | */ |
| 159 | static void correctstack (lua_State *L, StkId oldstack) { | 159 | static void correctstack (lua_State *L, StkId oldstack) { |
| 160 | CallInfo *ci; | ||
| 160 | UpVal *up; | 161 | UpVal *up; |
| 161 | L->top = (L->top - oldstack) + L->stack; | 162 | L->top = (L->top - oldstack) + L->stack; |
| 162 | L->func = (L->func - oldstack) + L->stack; | ||
| 163 | for (up = L->openupval; up != NULL; up = up->u.open.next) | 163 | for (up = L->openupval; up != NULL; up = up->u.open.next) |
| 164 | up->v = s2v((uplevel(up) - oldstack) + L->stack); | 164 | up->v = s2v((uplevel(up) - oldstack) + L->stack); |
| 165 | for (ci = L->ci; ci != NULL; ci = ci->previous) { | ||
| 166 | ci->top = (ci->top - oldstack) + L->stack; | ||
| 167 | ci->func = (ci->func - oldstack) + L->stack; | ||
| 168 | } | ||
| 165 | } | 169 | } |
| 166 | 170 | ||
| 167 | 171 | ||
| @@ -203,11 +207,10 @@ void luaD_growstack (lua_State *L, int n) { | |||
| 203 | 207 | ||
| 204 | 208 | ||
| 205 | static int stackinuse (lua_State *L) { | 209 | static int stackinuse (lua_State *L) { |
| 210 | CallInfo *ci; | ||
| 206 | StkId lim = L->top; | 211 | StkId lim = L->top; |
| 207 | StkId func = L->func; | 212 | for (ci = L->ci; ci != NULL; ci = ci->previous) { |
| 208 | for (; func->stkci.previous != 0; func -= func->stkci.previous) { | 213 | if (lim < ci->top) lim = ci->top; |
| 209 | if (lim < functop(func)) | ||
| 210 | lim = functop(func); | ||
| 211 | } | 214 | } |
| 212 | lua_assert(lim <= L->stack_last); | 215 | lua_assert(lim <= L->stack_last); |
| 213 | return cast_int(lim - L->stack) + 1; /* part of stack in use */ | 216 | return cast_int(lim - L->stack) + 1; /* part of stack in use */ |
| @@ -219,6 +222,10 @@ void luaD_shrinkstack (lua_State *L) { | |||
| 219 | int goodsize = inuse + (inuse / 8) + 2*EXTRA_STACK; | 222 | int goodsize = inuse + (inuse / 8) + 2*EXTRA_STACK; |
| 220 | if (goodsize > LUAI_MAXSTACK) | 223 | if (goodsize > LUAI_MAXSTACK) |
| 221 | goodsize = LUAI_MAXSTACK; /* respect stack limit */ | 224 | goodsize = LUAI_MAXSTACK; /* respect stack limit */ |
| 225 | if (L->stacksize > LUAI_MAXSTACK) /* had been handling stack overflow? */ | ||
| 226 | luaE_freeCI(L); /* free all CIs (list grew because of an error) */ | ||
| 227 | else | ||
| 228 | luaE_shrinkCI(L); /* shrink list */ | ||
| 222 | /* if thread is currently not handling a stack overflow and its | 229 | /* if thread is currently not handling a stack overflow and its |
| 223 | good size is smaller than current size, shrink its stack */ | 230 | good size is smaller than current size, shrink its stack */ |
| 224 | if (inuse <= (LUAI_MAXSTACK - EXTRA_STACK) && | 231 | if (inuse <= (LUAI_MAXSTACK - EXTRA_STACK) && |
| @@ -245,46 +252,40 @@ void luaD_inctop (lua_State *L) { | |||
| 245 | void luaD_hook (lua_State *L, int event, int line) { | 252 | void luaD_hook (lua_State *L, int event, int line) { |
| 246 | lua_Hook hook = L->hook; | 253 | lua_Hook hook = L->hook; |
| 247 | if (hook && L->allowhook) { /* make sure there is a hook */ | 254 | if (hook && L->allowhook) { /* make sure there is a hook */ |
| 255 | CallInfo *ci = L->ci; | ||
| 248 | ptrdiff_t top = savestack(L, L->top); | 256 | ptrdiff_t top = savestack(L, L->top); |
| 249 | int origframesize = L->func->stkci.framesize; | 257 | ptrdiff_t ci_top = savestack(L, ci->top); |
| 250 | int tmpframesize; /* frame size to run hook */ | ||
| 251 | lua_Debug ar; | 258 | lua_Debug ar; |
| 252 | ar.event = event; | 259 | ar.event = event; |
| 253 | ar.currentline = line; | 260 | ar.currentline = line; |
| 254 | ar.i_actf = L->func - L->stack; | 261 | ar.i_ci = ci; |
| 255 | ar.i_actL = L; | ||
| 256 | luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */ | 262 | luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */ |
| 257 | tmpframesize = L->top - L->func + LUA_MINSTACK; | 263 | ci->top = L->top + LUA_MINSTACK; |
| 258 | if (tmpframesize > origframesize) /* need to grow frame? */ | 264 | lua_assert(ci->top <= L->stack_last); |
| 259 | L->func->stkci.framesize = tmpframesize; | ||
| 260 | lua_assert(functop(L->func) <= L->stack_last); | ||
| 261 | L->allowhook = 0; /* cannot call hooks inside a hook */ | 265 | L->allowhook = 0; /* cannot call hooks inside a hook */ |
| 262 | callstatus(L->func) |= CIST_HOOKED; | 266 | ci->callstatus |= CIST_HOOKED; |
| 263 | lua_unlock(L); | 267 | lua_unlock(L); |
| 264 | (*hook)(L, &ar); | 268 | (*hook)(L, &ar); |
| 265 | lua_lock(L); | 269 | lua_lock(L); |
| 266 | lua_assert(!L->allowhook); | 270 | lua_assert(!L->allowhook); |
| 267 | L->allowhook = 1; | 271 | L->allowhook = 1; |
| 268 | L->func->stkci.framesize = origframesize; | 272 | ci->top = restorestack(L, ci_top); |
| 269 | L->top = restorestack(L, top); | 273 | L->top = restorestack(L, top); |
| 270 | callstatus(L->func) &= ~CIST_HOOKED; | 274 | ci->callstatus &= ~CIST_HOOKED; |
| 271 | } | 275 | } |
| 272 | } | 276 | } |
| 273 | 277 | ||
| 274 | 278 | ||
| 275 | static void callhook (lua_State *L) { | 279 | static void callhook (lua_State *L, CallInfo *ci) { |
| 276 | int hook = LUA_HOOKCALL; | 280 | int hook = LUA_HOOKCALL; |
| 277 | StkId func = L->func; | 281 | ci->u.l.savedpc++; /* hooks assume 'pc' is already incremented */ |
| 278 | StkId previous = func - L->func->stkci.previous; | 282 | if (isLua(ci->previous) && |
| 279 | func->stkci.u.l.savedpc++; /* hooks assume 'pc' is already incremented */ | 283 | GET_OPCODE(*(ci->previous->u.l.savedpc - 1)) == OP_TAILCALL) { |
| 280 | if (isLua(previous) && | 284 | ci->callstatus |= CIST_TAIL; |
| 281 | GET_OPCODE(*(previous->stkci.u.l.savedpc - 1)) == OP_TAILCALL) { | ||
| 282 | callstatus(L->func) |= CIST_TAIL; | ||
| 283 | hook = LUA_HOOKTAILCALL; | 285 | hook = LUA_HOOKTAILCALL; |
| 284 | } | 286 | } |
| 285 | luaD_hook(L, hook, -1); | 287 | luaD_hook(L, hook, -1); |
| 286 | func = L->func; /* previous call can change stack */ | 288 | ci->u.l.savedpc--; /* correct 'pc' */ |
| 287 | func->stkci.u.l.savedpc--; /* correct 'pc' */ | ||
| 288 | } | 289 | } |
| 289 | 290 | ||
| 290 | 291 | ||
| @@ -355,25 +356,28 @@ static int moveresults (lua_State *L, StkId firstResult, StkId res, | |||
| 355 | ** moves current number of results to proper place; returns 0 iff call | 356 | ** moves current number of results to proper place; returns 0 iff call |
| 356 | ** wanted multiple (variable number of) results. | 357 | ** wanted multiple (variable number of) results. |
| 357 | */ | 358 | */ |
| 358 | int luaD_poscall (lua_State *L, StkId firstResult, int nres) { | 359 | int luaD_poscall (lua_State *L, CallInfo *ci, StkId firstResult, int nres) { |
| 359 | StkId res = L->func; /* res == final position of 1st result */ | 360 | StkId res; |
| 360 | int wanted = res->stkci.nresults; | 361 | int wanted = ci->nresults; |
| 361 | if (L->hookmask & (LUA_MASKRET | LUA_MASKLINE)) { | 362 | if (L->hookmask & (LUA_MASKRET | LUA_MASKLINE)) { |
| 362 | if (L->hookmask & LUA_MASKRET) { | 363 | if (L->hookmask & LUA_MASKRET) { |
| 363 | ptrdiff_t fr = savestack(L, firstResult); /* hook may change stack */ | 364 | ptrdiff_t fr = savestack(L, firstResult); /* hook may change stack */ |
| 364 | luaD_hook(L, LUA_HOOKRET, -1); | 365 | luaD_hook(L, LUA_HOOKRET, -1); |
| 365 | firstResult = restorestack(L, fr); | 366 | firstResult = restorestack(L, fr); |
| 366 | res = L->func; | ||
| 367 | } | 367 | } |
| 368 | /* 'oldpc' for caller function */ | 368 | L->oldpc = ci->previous->u.l.savedpc; /* 'oldpc' for caller function */ |
| 369 | L->oldpc = (res - res->stkci.previous)->stkci.u.l.savedpc; | ||
| 370 | } | 369 | } |
| 371 | L->func = res - res->stkci.previous; | 370 | res = ci->func; /* res == final position of 1st result */ |
| 371 | L->ci = ci->previous; /* back to caller */ | ||
| 372 | /* move results to proper place */ | 372 | /* move results to proper place */ |
| 373 | return moveresults(L, firstResult, res, nres, wanted); | 373 | return moveresults(L, firstResult, res, nres, wanted); |
| 374 | } | 374 | } |
| 375 | 375 | ||
| 376 | 376 | ||
| 377 | |||
| 378 | #define next_ci(L) (L->ci = (L->ci->next ? L->ci->next : luaE_extendCI(L))) | ||
| 379 | |||
| 380 | |||
| 377 | /* | 381 | /* |
| 378 | ** Prepares a function call: checks the stack, creates a new CallInfo | 382 | ** Prepares a function call: checks the stack, creates a new CallInfo |
| 379 | ** entry, fills in the relevant information, calls hook if needed. | 383 | ** entry, fills in the relevant information, calls hook if needed. |
| @@ -384,6 +388,7 @@ int luaD_poscall (lua_State *L, StkId firstResult, int nres) { | |||
| 384 | int luaD_precall (lua_State *L, StkId func, int nresults) { | 388 | int luaD_precall (lua_State *L, StkId func, int nresults) { |
| 385 | lua_CFunction f; | 389 | lua_CFunction f; |
| 386 | TValue *funcv = s2v(func); | 390 | TValue *funcv = s2v(func); |
| 391 | CallInfo *ci; | ||
| 387 | switch (ttype(funcv)) { | 392 | switch (ttype(funcv)) { |
| 388 | case LUA_TCCL: /* C closure */ | 393 | case LUA_TCCL: /* C closure */ |
| 389 | f = clCvalue(funcv)->f; | 394 | f = clCvalue(funcv)->f; |
| @@ -393,19 +398,19 @@ int luaD_precall (lua_State *L, StkId func, int nresults) { | |||
| 393 | Cfunc: { | 398 | Cfunc: { |
| 394 | int n; /* number of returns */ | 399 | int n; /* number of returns */ |
| 395 | checkstackp(L, LUA_MINSTACK, func); /* ensure minimum stack size */ | 400 | checkstackp(L, LUA_MINSTACK, func); /* ensure minimum stack size */ |
| 396 | func->stkci.nresults = nresults; | 401 | ci = next_ci(L); /* now 'enter' new function */ |
| 397 | func->stkci.previous = func - L->func; | 402 | ci->nresults = nresults; |
| 398 | L->func = func; | 403 | ci->func = func; |
| 399 | setfunctop(func, L->top + LUA_MINSTACK); | 404 | ci->top = L->top + LUA_MINSTACK; |
| 400 | lua_assert(functop(func) <= L->stack_last); | 405 | lua_assert(ci->top <= L->stack_last); |
| 401 | callstatus(func) = 0; | 406 | ci->callstatus = 0; |
| 402 | if (L->hookmask & LUA_MASKCALL) | 407 | if (L->hookmask & LUA_MASKCALL) |
| 403 | luaD_hook(L, LUA_HOOKCALL, -1); | 408 | luaD_hook(L, LUA_HOOKCALL, -1); |
| 404 | lua_unlock(L); | 409 | lua_unlock(L); |
| 405 | n = (*f)(L); /* do the actual call */ | 410 | n = (*f)(L); /* do the actual call */ |
| 406 | lua_lock(L); | 411 | lua_lock(L); |
| 407 | api_checknelems(L, n); | 412 | api_checknelems(L, n); |
| 408 | luaD_poscall(L, L->top - n, n); | 413 | luaD_poscall(L, ci, L->top - n, n); |
| 409 | return 1; | 414 | return 1; |
| 410 | } | 415 | } |
| 411 | case LUA_TLCL: { /* Lua function: prepare its call */ | 416 | case LUA_TLCL: { /* Lua function: prepare its call */ |
| @@ -417,16 +422,15 @@ int luaD_precall (lua_State *L, StkId func, int nresults) { | |||
| 417 | setnilvalue(s2v(L->top++)); /* complete missing arguments */ | 422 | setnilvalue(s2v(L->top++)); /* complete missing arguments */ |
| 418 | if (p->is_vararg) | 423 | if (p->is_vararg) |
| 419 | luaT_adjustvarargs(L, p, n); | 424 | luaT_adjustvarargs(L, p, n); |
| 420 | func->stkci.nresults = nresults; | 425 | ci = next_ci(L); /* now 'enter' new function */ |
| 421 | func->stkci.previous = func - L->func; | 426 | ci->nresults = nresults; |
| 422 | func->stkci.framesize = fsize + 1; /* size includes function itself */ | 427 | ci->func = func; |
| 423 | L->func = func; | 428 | L->top = ci->top = func + 1 + fsize; |
| 424 | L->top = func + 1 + fsize; | 429 | lua_assert(ci->top <= L->stack_last); |
| 425 | lua_assert(functop(func) <= L->stack_last); | 430 | ci->u.l.savedpc = p->code; /* starting point */ |
| 426 | func->stkci.u.l.savedpc = p->code; /* starting point */ | 431 | ci->callstatus = CIST_LUA; |
| 427 | callstatus(func) = 0; | ||
| 428 | if (L->hookmask & LUA_MASKCALL) | 432 | if (L->hookmask & LUA_MASKCALL) |
| 429 | callhook(L); | 433 | callhook(L, ci); |
| 430 | return 0; | 434 | return 0; |
| 431 | } | 435 | } |
| 432 | default: { /* not a function */ | 436 | default: { /* not a function */ |
| @@ -483,25 +487,24 @@ void luaD_callnoyield (lua_State *L, StkId func, int nResults) { | |||
| 483 | ** continuation function. | 487 | ** continuation function. |
| 484 | */ | 488 | */ |
| 485 | static void finishCcall (lua_State *L, int status) { | 489 | static void finishCcall (lua_State *L, int status) { |
| 486 | StkId func = L->func; | 490 | CallInfo *ci = L->ci; |
| 487 | int n; | 491 | int n; |
| 488 | /* must have a continuation and must be able to call it */ | 492 | /* must have a continuation and must be able to call it */ |
| 489 | lua_assert(func->stkci.u.c.k != NULL && L->nny == 0); | 493 | lua_assert(ci->u.c.k != NULL && L->nny == 0); |
| 490 | /* error status can only happen in a protected call */ | 494 | /* error status can only happen in a protected call */ |
| 491 | lua_assert((callstatus(func) & CIST_YPCALL) || status == LUA_YIELD); | 495 | lua_assert((ci->callstatus & CIST_YPCALL) || status == LUA_YIELD); |
| 492 | if (callstatus(func) & CIST_YPCALL) { /* was inside a pcall? */ | 496 | if (ci->callstatus & CIST_YPCALL) { /* was inside a pcall? */ |
| 493 | callstatus(func) &= ~CIST_YPCALL; /* continuation is also inside it */ | 497 | ci->callstatus &= ~CIST_YPCALL; /* continuation is also inside it */ |
| 494 | L->errfunc = func->stkci.u.c.old_errfunc; /* with same error function */ | 498 | L->errfunc = ci->u.c.old_errfunc; /* with the same error function */ |
| 495 | } | 499 | } |
| 496 | /* finish 'lua_callk'/'lua_pcall'; CIST_YPCALL and 'errfunc' already | 500 | /* finish 'lua_callk'/'lua_pcall'; CIST_YPCALL and 'errfunc' already |
| 497 | handled */ | 501 | handled */ |
| 498 | adjustresults(L, func->stkci.nresults); | 502 | adjustresults(L, ci->nresults); |
| 499 | lua_unlock(L); | 503 | lua_unlock(L); |
| 500 | /* call continuation function */ | 504 | n = (*ci->u.c.k)(L, status, ci->u.c.ctx); /* call continuation function */ |
| 501 | n = (*func->stkci.u.c.k)(L, status, func->stkci.u.c.ctx); | ||
| 502 | lua_lock(L); | 505 | lua_lock(L); |
| 503 | api_checknelems(L, n); | 506 | api_checknelems(L, n); |
| 504 | luaD_poscall(L, L->top - n, n); /* finish 'luaD_precall' */ | 507 | luaD_poscall(L, ci, L->top - n, n); /* finish 'luaD_precall' */ |
| 505 | } | 508 | } |
| 506 | 509 | ||
| 507 | 510 | ||
| @@ -516,8 +519,8 @@ static void finishCcall (lua_State *L, int status) { | |||
| 516 | static void unroll (lua_State *L, void *ud) { | 519 | static void unroll (lua_State *L, void *ud) { |
| 517 | if (ud != NULL) /* error status? */ | 520 | if (ud != NULL) /* error status? */ |
| 518 | finishCcall(L, *(int *)ud); /* finish 'lua_pcallk' callee */ | 521 | finishCcall(L, *(int *)ud); /* finish 'lua_pcallk' callee */ |
| 519 | while (L->func != L->stack) { /* something in the stack */ | 522 | while (L->ci != &L->base_ci) { /* something in the stack */ |
| 520 | if (!isLua(L->func)) /* C function? */ | 523 | if (!isLua(L->ci)) /* C function? */ |
| 521 | finishCcall(L, LUA_YIELD); /* complete its execution */ | 524 | finishCcall(L, LUA_YIELD); /* complete its execution */ |
| 522 | else { /* Lua function */ | 525 | else { /* Lua function */ |
| 523 | luaV_finishOp(L); /* finish interrupted instruction */ | 526 | luaV_finishOp(L); /* finish interrupted instruction */ |
| @@ -531,13 +534,11 @@ static void unroll (lua_State *L, void *ud) { | |||
| 531 | ** Try to find a suspended protected call (a "recover point") for the | 534 | ** Try to find a suspended protected call (a "recover point") for the |
| 532 | ** given thread. | 535 | ** given thread. |
| 533 | */ | 536 | */ |
| 534 | static StkId findpcall (lua_State *L) { | 537 | static CallInfo *findpcall (lua_State *L) { |
| 535 | StkId func; | 538 | CallInfo *ci; |
| 536 | for (func = L->func; | 539 | for (ci = L->ci; ci != NULL; ci = ci->previous) { /* search for a pcall */ |
| 537 | func->stkci.previous != 0; | 540 | if (ci->callstatus & CIST_YPCALL) |
| 538 | func -= func->stkci.previous) { | 541 | return ci; |
| 539 | if (callstatus(func) & CIST_YPCALL) | ||
| 540 | return func; | ||
| 541 | } | 542 | } |
| 542 | return NULL; /* no pending pcall */ | 543 | return NULL; /* no pending pcall */ |
| 543 | } | 544 | } |
| @@ -550,17 +551,17 @@ static StkId findpcall (lua_State *L) { | |||
| 550 | */ | 551 | */ |
| 551 | static int recover (lua_State *L, int status) { | 552 | static int recover (lua_State *L, int status) { |
| 552 | StkId oldtop; | 553 | StkId oldtop; |
| 553 | StkId recf = findpcall(L); | 554 | CallInfo *ci = findpcall(L); |
| 554 | if (recf == NULL) return 0; /* no recovery point */ | 555 | if (ci == NULL) return 0; /* no recovery point */ |
| 555 | /* "finish" luaD_pcall */ | 556 | /* "finish" luaD_pcall */ |
| 556 | oldtop = recf + recf->stkci.u2.funcidx; | 557 | oldtop = restorestack(L, ci->u2.funcidx); |
| 557 | luaF_close(L, oldtop); | 558 | luaF_close(L, oldtop); |
| 558 | seterrorobj(L, status, oldtop); | 559 | seterrorobj(L, status, oldtop); |
| 559 | L->func = recf; | 560 | L->ci = ci; |
| 560 | L->allowhook = getoah(callstatus(recf)); /* restore original 'allowhook' */ | 561 | L->allowhook = getoah(ci->callstatus); /* restore original 'allowhook' */ |
| 561 | L->nny = 0; /* should be zero to be yieldable */ | 562 | L->nny = 0; /* should be zero to be yieldable */ |
| 562 | luaD_shrinkstack(L); | 563 | luaD_shrinkstack(L); |
| 563 | L->errfunc = recf->stkci.u.c.old_errfunc; | 564 | L->errfunc = ci->u.c.old_errfunc; |
| 564 | return 1; /* continue running the coroutine */ | 565 | return 1; /* continue running the coroutine */ |
| 565 | } | 566 | } |
| 566 | 567 | ||
| @@ -589,7 +590,7 @@ static int resume_error (lua_State *L, const char *msg, int narg) { | |||
| 589 | static void resume (lua_State *L, void *ud) { | 590 | static void resume (lua_State *L, void *ud) { |
| 590 | int n = *(cast(int*, ud)); /* number of arguments */ | 591 | int n = *(cast(int*, ud)); /* number of arguments */ |
| 591 | StkId firstArg = L->top - n; /* first argument */ | 592 | StkId firstArg = L->top - n; /* first argument */ |
| 592 | StkId func = L->func; | 593 | CallInfo *ci = L->ci; |
| 593 | if (L->status == LUA_OK) { /* starting a coroutine? */ | 594 | if (L->status == LUA_OK) { /* starting a coroutine? */ |
| 594 | if (!luaD_precall(L, firstArg - 1, LUA_MULTRET)) /* Lua function? */ | 595 | if (!luaD_precall(L, firstArg - 1, LUA_MULTRET)) /* Lua function? */ |
| 595 | luaV_execute(L); /* call it */ | 596 | luaV_execute(L); /* call it */ |
| @@ -597,18 +598,17 @@ static void resume (lua_State *L, void *ud) { | |||
| 597 | else { /* resuming from previous yield */ | 598 | else { /* resuming from previous yield */ |
| 598 | lua_assert(L->status == LUA_YIELD); | 599 | lua_assert(L->status == LUA_YIELD); |
| 599 | L->status = LUA_OK; /* mark that it is running (again) */ | 600 | L->status = LUA_OK; /* mark that it is running (again) */ |
| 600 | if (isLua(func)) /* yielded inside a hook? */ | 601 | if (isLua(ci)) /* yielded inside a hook? */ |
| 601 | luaV_execute(L); /* just continue running Lua code */ | 602 | luaV_execute(L); /* just continue running Lua code */ |
| 602 | else { /* 'common' yield */ | 603 | else { /* 'common' yield */ |
| 603 | if (func->stkci.u.c.k != NULL) { /* does it have a continuation? */ | 604 | if (ci->u.c.k != NULL) { /* does it have a continuation function? */ |
| 604 | lua_unlock(L); | 605 | lua_unlock(L); |
| 605 | /* call continuation */ | 606 | n = (*ci->u.c.k)(L, LUA_YIELD, ci->u.c.ctx); /* call continuation */ |
| 606 | n = (*func->stkci.u.c.k)(L, LUA_YIELD, func->stkci.u.c.ctx); | ||
| 607 | lua_lock(L); | 607 | lua_lock(L); |
| 608 | api_checknelems(L, n); | 608 | api_checknelems(L, n); |
| 609 | firstArg = L->top - n; /* yield results come from continuation */ | 609 | firstArg = L->top - n; /* yield results come from continuation */ |
| 610 | } | 610 | } |
| 611 | luaD_poscall(L, firstArg, n); /* finish 'luaD_precall' */ | 611 | luaD_poscall(L, ci, firstArg, n); /* finish 'luaD_precall' */ |
| 612 | } | 612 | } |
| 613 | unroll(L, NULL); /* run continuation */ | 613 | unroll(L, NULL); /* run continuation */ |
| 614 | } | 614 | } |
| @@ -621,7 +621,7 @@ LUA_API int lua_resume (lua_State *L, lua_State *from, int nargs, | |||
| 621 | unsigned short oldnny = L->nny; /* save "number of non-yieldable" calls */ | 621 | unsigned short oldnny = L->nny; /* save "number of non-yieldable" calls */ |
| 622 | lua_lock(L); | 622 | lua_lock(L); |
| 623 | if (L->status == LUA_OK) { /* may be starting a coroutine */ | 623 | if (L->status == LUA_OK) { /* may be starting a coroutine */ |
| 624 | if (L->func != L->stack) /* not in base level? */ | 624 | if (L->ci != &L->base_ci) /* not in base level? */ |
| 625 | return resume_error(L, "cannot resume non-suspended coroutine", nargs); | 625 | return resume_error(L, "cannot resume non-suspended coroutine", nargs); |
| 626 | } | 626 | } |
| 627 | else if (L->status != LUA_YIELD) | 627 | else if (L->status != LUA_YIELD) |
| @@ -643,12 +643,12 @@ LUA_API int lua_resume (lua_State *L, lua_State *from, int nargs, | |||
| 643 | if (errorstatus(status)) { /* unrecoverable error? */ | 643 | if (errorstatus(status)) { /* unrecoverable error? */ |
| 644 | L->status = cast_byte(status); /* mark thread as 'dead' */ | 644 | L->status = cast_byte(status); /* mark thread as 'dead' */ |
| 645 | seterrorobj(L, status, L->top); /* push error message */ | 645 | seterrorobj(L, status, L->top); /* push error message */ |
| 646 | L->func->stkci.framesize = L->top - L->func; | 646 | L->ci->top = L->top; |
| 647 | } | 647 | } |
| 648 | else lua_assert(status == L->status); /* normal end or yield */ | 648 | else lua_assert(status == L->status); /* normal end or yield */ |
| 649 | } | 649 | } |
| 650 | *nresults = (status == LUA_YIELD) ? L->func->stkci.u2.nyield | 650 | *nresults = (status == LUA_YIELD) ? L->ci->u2.nyield |
| 651 | : L->top - (L->func + 1); | 651 | : L->top - (L->ci->func + 1); |
| 652 | L->nny = oldnny; /* restore 'nny' */ | 652 | L->nny = oldnny; /* restore 'nny' */ |
| 653 | L->nCcalls--; | 653 | L->nCcalls--; |
| 654 | lua_assert(L->nCcalls == ((from) ? from->nCcalls : 0)); | 654 | lua_assert(L->nCcalls == ((from) ? from->nCcalls : 0)); |
| @@ -664,7 +664,7 @@ LUA_API int lua_isyieldable (lua_State *L) { | |||
| 664 | 664 | ||
| 665 | LUA_API int lua_yieldk (lua_State *L, int nresults, lua_KContext ctx, | 665 | LUA_API int lua_yieldk (lua_State *L, int nresults, lua_KContext ctx, |
| 666 | lua_KFunction k) { | 666 | lua_KFunction k) { |
| 667 | StkId func = L->func; | 667 | CallInfo *ci = L->ci; |
| 668 | luai_userstateyield(L, nresults); | 668 | luai_userstateyield(L, nresults); |
| 669 | lua_lock(L); | 669 | lua_lock(L); |
| 670 | api_checknelems(L, nresults); | 670 | api_checknelems(L, nresults); |
| @@ -675,17 +675,17 @@ LUA_API int lua_yieldk (lua_State *L, int nresults, lua_KContext ctx, | |||
| 675 | luaG_runerror(L, "attempt to yield from outside a coroutine"); | 675 | luaG_runerror(L, "attempt to yield from outside a coroutine"); |
| 676 | } | 676 | } |
| 677 | L->status = LUA_YIELD; | 677 | L->status = LUA_YIELD; |
| 678 | if (isLua(func)) { /* inside a hook? */ | 678 | if (isLua(ci)) { /* inside a hook? */ |
| 679 | api_check(L, k == NULL, "hooks cannot continue after yielding"); | 679 | api_check(L, k == NULL, "hooks cannot continue after yielding"); |
| 680 | func->stkci.u2.nyield = 0; /* no results */ | 680 | ci->u2.nyield = 0; /* no results */ |
| 681 | } | 681 | } |
| 682 | else { | 682 | else { |
| 683 | if ((func->stkci.u.c.k = k) != NULL) /* is there a continuation? */ | 683 | if ((ci->u.c.k = k) != NULL) /* is there a continuation? */ |
| 684 | func->stkci.u.c.ctx = ctx; /* save context */ | 684 | ci->u.c.ctx = ctx; /* save context */ |
| 685 | func->stkci.u2.nyield = nresults; /* save number of results */ | 685 | ci->u2.nyield = nresults; /* save number of results */ |
| 686 | luaD_throw(L, LUA_YIELD); | 686 | luaD_throw(L, LUA_YIELD); |
| 687 | } | 687 | } |
| 688 | lua_assert(callstatus(func) & CIST_HOOKED); /* must be inside a hook */ | 688 | lua_assert(ci->callstatus & CIST_HOOKED); /* must be inside a hook */ |
| 689 | lua_unlock(L); | 689 | lua_unlock(L); |
| 690 | return 0; /* return to 'luaD_hook' */ | 690 | return 0; /* return to 'luaD_hook' */ |
| 691 | } | 691 | } |
| @@ -694,7 +694,7 @@ LUA_API int lua_yieldk (lua_State *L, int nresults, lua_KContext ctx, | |||
| 694 | int luaD_pcall (lua_State *L, Pfunc func, void *u, | 694 | int luaD_pcall (lua_State *L, Pfunc func, void *u, |
| 695 | ptrdiff_t old_top, ptrdiff_t ef) { | 695 | ptrdiff_t old_top, ptrdiff_t ef) { |
| 696 | int status; | 696 | int status; |
| 697 | ptrdiff_t oldfunc = savestack(L, L->func); | 697 | CallInfo *old_ci = L->ci; |
| 698 | lu_byte old_allowhooks = L->allowhook; | 698 | lu_byte old_allowhooks = L->allowhook; |
| 699 | unsigned short old_nny = L->nny; | 699 | unsigned short old_nny = L->nny; |
| 700 | ptrdiff_t old_errfunc = L->errfunc; | 700 | ptrdiff_t old_errfunc = L->errfunc; |
| @@ -704,7 +704,7 @@ int luaD_pcall (lua_State *L, Pfunc func, void *u, | |||
| 704 | StkId oldtop = restorestack(L, old_top); | 704 | StkId oldtop = restorestack(L, old_top); |
| 705 | luaF_close(L, oldtop); /* close possible pending closures */ | 705 | luaF_close(L, oldtop); /* close possible pending closures */ |
| 706 | seterrorobj(L, status, oldtop); | 706 | seterrorobj(L, status, oldtop); |
| 707 | L->func = restorestack(L, oldfunc); | 707 | L->ci = old_ci; |
| 708 | L->allowhook = old_allowhooks; | 708 | L->allowhook = old_allowhooks; |
| 709 | L->nny = old_nny; | 709 | L->nny = old_nny; |
| 710 | luaD_shrinkstack(L); | 710 | luaD_shrinkstack(L); |
