diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2017-11-23 14:41:16 -0200 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2017-11-23 14:41:16 -0200 |
commit | 196c87c9cecfacf978f37de4ec69eba0a5971256 (patch) | |
tree | ce434c8a63228cf1f25adcc2210ba741ee899887 /ldo.c | |
parent | 39f26b1480502cc2f75a5af6e06e5410e06634ba (diff) | |
download | lua-196c87c9cecfacf978f37de4ec69eba0a5971256.tar.gz lua-196c87c9cecfacf978f37de4ec69eba0a5971256.tar.bz2 lua-196c87c9cecfacf978f37de4ec69eba0a5971256.zip |
no more 'stackless' implementation; 'luaV_execute' calls itself
recursively to execute function calls. 'unroll' continues all
executions suspended by an yield (through a long jump)
Diffstat (limited to 'ldo.c')
-rw-r--r-- | ldo.c | 66 |
1 files changed, 18 insertions, 48 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: ldo.c,v 2.172 2017/11/13 15:36:52 roberto Exp roberto $ | 2 | ** $Id: ldo.c,v 2.173 2017/11/21 14:17:35 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 | */ |
@@ -135,7 +135,7 @@ l_noret luaD_throw (lua_State *L, int errcode) { | |||
135 | 135 | ||
136 | 136 | ||
137 | int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud) { | 137 | int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud) { |
138 | unsigned short oldnCcalls = L->nCcalls; | 138 | unsigned short oldnCcalls = L->nCcalls - L->nci; |
139 | struct lua_longjmp lj; | 139 | struct lua_longjmp lj; |
140 | lj.status = LUA_OK; | 140 | lj.status = LUA_OK; |
141 | lj.previous = L->errorJmp; /* chain new error handler */ | 141 | lj.previous = L->errorJmp; /* chain new error handler */ |
@@ -144,7 +144,7 @@ int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud) { | |||
144 | (*f)(L, ud); | 144 | (*f)(L, ud); |
145 | ); | 145 | ); |
146 | L->errorJmp = lj.previous; /* restore old error handler */ | 146 | L->errorJmp = lj.previous; /* restore old error handler */ |
147 | L->nCcalls = oldnCcalls; | 147 | L->nCcalls = oldnCcalls + L->nci; |
148 | return lj.status; | 148 | return lj.status; |
149 | } | 149 | } |
150 | 150 | ||
@@ -299,7 +299,7 @@ static void callhook (lua_State *L, CallInfo *ci, int istail) { | |||
299 | 299 | ||
300 | /* | 300 | /* |
301 | ** Check whether __call metafield of 'func' is a function. If so, put | 301 | ** Check whether __call metafield of 'func' is a function. If so, put |
302 | ** it in stack below original 'func' so that 'luaD_precall' can call | 302 | ** it in stack below original 'func' so that 'luaD_call' can call |
303 | ** it. Raise an error if __call metafield is not a function. | 303 | ** it. Raise an error if __call metafield is not a function. |
304 | */ | 304 | */ |
305 | StkId luaD_tryfuncTM (lua_State *L, StkId func) { | 305 | StkId luaD_tryfuncTM (lua_State *L, StkId func) { |
@@ -417,13 +417,12 @@ void luaD_pretailcall (lua_State *L, CallInfo *ci, StkId func, int n) { | |||
417 | 417 | ||
418 | 418 | ||
419 | /* | 419 | /* |
420 | ** Prepares a function call: checks the stack, creates a new CallInfo | 420 | ** Call a function (C or Lua). The function to be called is at *func. |
421 | ** entry, fills in the relevant information, calls hook if needed. | 421 | ** The arguments are on the stack, right after the function. |
422 | ** If function is a C function, does the call, too. (Otherwise, leave | 422 | ** When returns, all the results are on the stack, starting at the original |
423 | ** the execution ('luaV_execute') to the caller, to allow stackless | 423 | ** function position. |
424 | ** calls.) Returns true iff function has been executed (C function). | ||
425 | */ | 424 | */ |
426 | int luaD_precall (lua_State *L, StkId func, int nresults) { | 425 | void luaD_call (lua_State *L, StkId func, int nresults) { |
427 | lua_CFunction f; | 426 | lua_CFunction f; |
428 | TValue *funcv = s2v(func); | 427 | TValue *funcv = s2v(func); |
429 | CallInfo *ci; | 428 | CallInfo *ci; |
@@ -449,7 +448,7 @@ int luaD_precall (lua_State *L, StkId func, int nresults) { | |||
449 | lua_lock(L); | 448 | lua_lock(L); |
450 | api_checknelems(L, n); | 449 | api_checknelems(L, n); |
451 | luaD_poscall(L, ci, L->top - n, n); | 450 | luaD_poscall(L, ci, L->top - n, n); |
452 | return 1; | 451 | break; |
453 | } | 452 | } |
454 | case LUA_TLCL: { /* Lua function: prepare its call */ | 453 | case LUA_TLCL: { /* Lua function: prepare its call */ |
455 | Proto *p = clLvalue(funcv)->p; | 454 | Proto *p = clLvalue(funcv)->p; |
@@ -469,47 +468,19 @@ int luaD_precall (lua_State *L, StkId func, int nresults) { | |||
469 | ci->callstatus = CIST_LUA; | 468 | ci->callstatus = CIST_LUA; |
470 | if (L->hookmask) | 469 | if (L->hookmask) |
471 | callhook(L, ci, 0); | 470 | callhook(L, ci, 0); |
472 | return 0; | 471 | luaV_execute(L); /* run the function */ |
472 | break; | ||
473 | } | 473 | } |
474 | default: { /* not a function */ | 474 | default: { /* not a function */ |
475 | func = luaD_tryfuncTM(L, func); /* try to get '__call' metamethod */ | 475 | func = luaD_tryfuncTM(L, func); /* try to get '__call' metamethod */ |
476 | return luaD_precall(L, func, nresults); /* now it must be a function */ | 476 | luaD_call(L, func, nresults); /* now it must be a function */ |
477 | break; | ||
477 | } | 478 | } |
478 | } | 479 | } |
479 | } | 480 | } |
480 | 481 | ||
481 | 482 | ||
482 | /* | 483 | /* |
483 | ** Check appropriate error for stack overflow ("regular" overflow or | ||
484 | ** overflow while handling stack overflow). If 'nCalls' is larger than | ||
485 | ** LUAI_MAXCCALLS (which means it is handling a "regular" overflow) but | ||
486 | ** smaller than 9/8 of LUAI_MAXCCALLS, does not report an error (to | ||
487 | ** allow overflow handling to work) | ||
488 | */ | ||
489 | static void stackerror (lua_State *L) { | ||
490 | if (L->nCcalls == LUAI_MAXCCALLS) | ||
491 | luaG_runerror(L, "C stack overflow"); | ||
492 | else if (L->nCcalls >= (LUAI_MAXCCALLS + (LUAI_MAXCCALLS>>3))) | ||
493 | luaD_throw(L, LUA_ERRERR); /* error while handing stack error */ | ||
494 | } | ||
495 | |||
496 | |||
497 | /* | ||
498 | ** Call a function (C or Lua). The function to be called is at *func. | ||
499 | ** The arguments are on the stack, right after the function. | ||
500 | ** When returns, all the results are on the stack, starting at the original | ||
501 | ** function position. | ||
502 | */ | ||
503 | void luaD_call (lua_State *L, StkId func, int nResults) { | ||
504 | if (++L->nCcalls >= LUAI_MAXCCALLS) | ||
505 | stackerror(L); | ||
506 | if (!luaD_precall(L, func, nResults)) /* is a Lua function? */ | ||
507 | luaV_execute(L); /* call it */ | ||
508 | L->nCcalls--; | ||
509 | } | ||
510 | |||
511 | |||
512 | /* | ||
513 | ** Similar to 'luaD_call', but does not allow yields during the call | 484 | ** Similar to 'luaD_call', but does not allow yields during the call |
514 | */ | 485 | */ |
515 | void luaD_callnoyield (lua_State *L, StkId func, int nResults) { | 486 | void luaD_callnoyield (lua_State *L, StkId func, int nResults) { |
@@ -541,7 +512,7 @@ static void finishCcall (lua_State *L, int status) { | |||
541 | n = (*ci->u.c.k)(L, status, ci->u.c.ctx); /* call continuation function */ | 512 | n = (*ci->u.c.k)(L, status, ci->u.c.ctx); /* call continuation function */ |
542 | lua_lock(L); | 513 | lua_lock(L); |
543 | api_checknelems(L, n); | 514 | api_checknelems(L, n); |
544 | luaD_poscall(L, ci, L->top - n, n); /* finish 'luaD_precall' */ | 515 | luaD_poscall(L, ci, L->top - n, n); /* finish 'luaD_call' */ |
545 | } | 516 | } |
546 | 517 | ||
547 | 518 | ||
@@ -629,8 +600,7 @@ static void resume (lua_State *L, void *ud) { | |||
629 | StkId firstArg = L->top - n; /* first argument */ | 600 | StkId firstArg = L->top - n; /* first argument */ |
630 | CallInfo *ci = L->ci; | 601 | CallInfo *ci = L->ci; |
631 | if (L->status == LUA_OK) { /* starting a coroutine? */ | 602 | if (L->status == LUA_OK) { /* starting a coroutine? */ |
632 | if (!luaD_precall(L, firstArg - 1, LUA_MULTRET)) /* Lua function? */ | 603 | luaD_call(L, firstArg - 1, LUA_MULTRET); |
633 | luaV_execute(L); /* call it */ | ||
634 | } | 604 | } |
635 | else { /* resuming from previous yield */ | 605 | else { /* resuming from previous yield */ |
636 | lua_assert(L->status == LUA_YIELD); | 606 | lua_assert(L->status == LUA_YIELD); |
@@ -645,7 +615,7 @@ static void resume (lua_State *L, void *ud) { | |||
645 | api_checknelems(L, n); | 615 | api_checknelems(L, n); |
646 | firstArg = L->top - n; /* yield results come from continuation */ | 616 | firstArg = L->top - n; /* yield results come from continuation */ |
647 | } | 617 | } |
648 | luaD_poscall(L, ci, firstArg, n); /* finish 'luaD_precall' */ | 618 | luaD_poscall(L, ci, firstArg, n); /* finish 'luaD_call' */ |
649 | } | 619 | } |
650 | unroll(L, NULL); /* run continuation */ | 620 | unroll(L, NULL); /* run continuation */ |
651 | } | 621 | } |
@@ -688,7 +658,7 @@ LUA_API int lua_resume (lua_State *L, lua_State *from, int nargs, | |||
688 | : L->top - (L->ci->func + 1); | 658 | : L->top - (L->ci->func + 1); |
689 | L->nny = oldnny; /* restore 'nny' */ | 659 | L->nny = oldnny; /* restore 'nny' */ |
690 | L->nCcalls--; | 660 | L->nCcalls--; |
691 | lua_assert(L->nCcalls == ((from) ? from->nCcalls : 0)); | 661 | // lua_assert(L->nCcalls == ((from) ? from->nCcalls : 0)); |
692 | lua_unlock(L); | 662 | lua_unlock(L); |
693 | return status; | 663 | return status; |
694 | } | 664 | } |