aboutsummaryrefslogtreecommitdiff
path: root/ldo.c
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2020-09-21 10:31:03 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2020-10-12 12:29:09 -0300
commit5d8ce05b3f6fad79e37ed21c1076e47a322472c6 (patch)
tree7629a59887da63d44267e872bc8e33be6db36582 /ldo.c
parentf83de8e34e24e30acf277f60de62a33bd51d1ddd (diff)
downloadlua-5d8ce05b3f6fad79e37ed21c1076e47a322472c6.tar.gz
lua-5d8ce05b3f6fad79e37ed21c1076e47a322472c6.tar.bz2
lua-5d8ce05b3f6fad79e37ed21c1076e47a322472c6.zip
Back to a stackless implementation
A "with stack" implementation gains too little in performance to be worth all the noise from C-stack overflows. This commit is almost a sketch, to test performance. There are several pending stuff: - review control of C-stack overflow and error messages; - what to do with setcstacklimit; - review comments; - review unroll of Lua calls.
Diffstat (limited to 'ldo.c')
-rw-r--r--ldo.c51
1 files changed, 31 insertions, 20 deletions
diff --git a/ldo.c b/ldo.c
index 5473815a..dc3cc9fd 100644
--- a/ldo.c
+++ b/ldo.c
@@ -139,8 +139,7 @@ l_noret luaD_throw (lua_State *L, int errcode) {
139 139
140 140
141int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud) { 141int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud) {
142 global_State *g = G(L); 142 l_uint32 oldnCcalls = L->nCcalls;
143 l_uint32 oldnCcalls = g->Cstacklimit - (L->nCcalls + L->nci);
144 struct lua_longjmp lj; 143 struct lua_longjmp lj;
145 lj.status = LUA_OK; 144 lj.status = LUA_OK;
146 lj.previous = L->errorJmp; /* chain new error handler */ 145 lj.previous = L->errorJmp; /* chain new error handler */
@@ -149,7 +148,7 @@ int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud) {
149 (*f)(L, ud); 148 (*f)(L, ud);
150 ); 149 );
151 L->errorJmp = lj.previous; /* restore old error handler */ 150 L->errorJmp = lj.previous; /* restore old error handler */
152 L->nCcalls = g->Cstacklimit - oldnCcalls - L->nci; 151 L->nCcalls = oldnCcalls;
153 return lj.status; 152 return lj.status;
154} 153}
155 154
@@ -348,7 +347,7 @@ static StkId rethook (lua_State *L, CallInfo *ci, StkId firstres, int nres) {
348 347
349/* 348/*
350** Check whether 'func' has a '__call' metafield. If so, put it in the 349** Check whether 'func' has a '__call' metafield. If so, put it in the
351** stack, below original 'func', so that 'luaD_call' can call it. Raise 350** stack, below original 'func', so that 'luaD_precall' can call it. Raise
352** an error if there is no '__call' metafield. 351** an error if there is no '__call' metafield.
353*/ 352*/
354void luaD_tryfuncTM (lua_State *L, StkId func) { 353void luaD_tryfuncTM (lua_State *L, StkId func) {
@@ -454,7 +453,7 @@ void luaD_pretailcall (lua_State *L, CallInfo *ci, StkId func, int narg1) {
454** When returns, all the results are on the stack, starting at the original 453** When returns, all the results are on the stack, starting at the original
455** function position. 454** function position.
456*/ 455*/
457void luaD_call (lua_State *L, StkId func, int nresults) { 456int luaD_precall (lua_State *L, StkId func, int nresults) {
458 lua_CFunction f; 457 lua_CFunction f;
459 retry: 458 retry:
460 switch (ttypetag(s2v(func))) { 459 switch (ttypetag(s2v(func))) {
@@ -482,7 +481,7 @@ void luaD_call (lua_State *L, StkId func, int nresults) {
482 lua_lock(L); 481 lua_lock(L);
483 api_checknelems(L, n); 482 api_checknelems(L, n);
484 luaD_poscall(L, ci, n); 483 luaD_poscall(L, ci, n);
485 break; 484 return 1;
486 } 485 }
487 case LUA_VLCL: { /* Lua function */ 486 case LUA_VLCL: { /* Lua function */
488 CallInfo *ci; 487 CallInfo *ci;
@@ -501,8 +500,7 @@ void luaD_call (lua_State *L, StkId func, int nresults) {
501 for (; narg < nfixparams; narg++) 500 for (; narg < nfixparams; narg++)
502 setnilvalue(s2v(L->top++)); /* complete missing arguments */ 501 setnilvalue(s2v(L->top++)); /* complete missing arguments */
503 lua_assert(ci->top <= L->stack_last); 502 lua_assert(ci->top <= L->stack_last);
504 luaV_execute(L, ci); /* run the function */ 503 return 0;
505 break;
506 } 504 }
507 default: { /* not a function */ 505 default: { /* not a function */
508 checkstackGCp(L, 1, func); /* space for metamethod */ 506 checkstackGCp(L, 1, func); /* space for metamethod */
@@ -513,17 +511,32 @@ void luaD_call (lua_State *L, StkId func, int nresults) {
513} 511}
514 512
515 513
514static void stackerror (lua_State *L) {
515 if (getCcalls(L) == LUAI_MAXCCALLS)
516 luaG_runerror(L, "C stack overflow");
517 else if (getCcalls(L) >= (LUAI_MAXCCALLS + (LUAI_MAXCCALLS>>3)))
518 luaD_throw(L, LUA_ERRERR); /* error while handing stack error */
519}
520
521
522void luaD_call (lua_State *L, StkId func, int nResults) {
523 L->nCcalls++;
524 if (getCcalls(L) >= LUAI_MAXCCALLS)
525 stackerror(L);
526 if (!luaD_precall(L, func, nResults)) /* is a Lua function? */
527 luaV_execute(L, L->ci); /* call it */
528 L->nCcalls--;
529}
530
531
532
516/* 533/*
517** Similar to 'luaD_call', but does not allow yields during the call. 534** Similar to 'luaD_call', but does not allow yields during the call.
518*/ 535*/
519void luaD_callnoyield (lua_State *L, StkId func, int nResults) { 536void luaD_callnoyield (lua_State *L, StkId func, int nResults) {
520 incXCcalls(L); 537 incnny(L);
521 if (getCcalls(L) <= CSTACKERR) { /* possible C stack overflow? */
522 luaE_exitCcall(L); /* to compensate decrement in next call */
523 luaE_enterCcall(L); /* check properly */
524 }
525 luaD_call(L, func, nResults); 538 luaD_call(L, func, nResults);
526 decXCcalls(L); 539 decnny(L);
527} 540}
528 541
529 542
@@ -638,7 +651,8 @@ static void resume (lua_State *L, void *ud) {
638 StkId firstArg = L->top - n; /* first argument */ 651 StkId firstArg = L->top - n; /* first argument */
639 CallInfo *ci = L->ci; 652 CallInfo *ci = L->ci;
640 if (L->status == LUA_OK) { /* starting a coroutine? */ 653 if (L->status == LUA_OK) { /* starting a coroutine? */
641 luaD_call(L, firstArg - 1, LUA_MULTRET); 654 if (!luaD_precall(L, firstArg - 1, LUA_MULTRET)) /* Lua function? */
655 luaV_execute(L, L->ci); /* call it */
642 } 656 }
643 else { /* resuming from previous yield */ 657 else { /* resuming from previous yield */
644 lua_assert(L->status == LUA_YIELD); 658 lua_assert(L->status == LUA_YIELD);
@@ -670,11 +684,8 @@ LUA_API int lua_resume (lua_State *L, lua_State *from, int nargs,
670 } 684 }
671 else if (L->status != LUA_YIELD) /* ended with errors? */ 685 else if (L->status != LUA_YIELD) /* ended with errors? */
672 return resume_error(L, "cannot resume dead coroutine", nargs); 686 return resume_error(L, "cannot resume dead coroutine", nargs);
673 if (from == NULL) 687 L->nCcalls = (from) ? getCcalls(from) + 1 : 1;
674 L->nCcalls = CSTACKTHREAD; 688 if (getCcalls(L) >= LUAI_MAXCCALLS)
675 else /* correct 'nCcalls' for this thread */
676 L->nCcalls = getCcalls(from) - L->nci - CSTACKCF;
677 if (L->nCcalls <= CSTACKERR)
678 return resume_error(L, "C stack overflow", nargs); 689 return resume_error(L, "C stack overflow", nargs);
679 luai_userstateresume(L, nargs); 690 luai_userstateresume(L, nargs);
680 api_checknelems(L, (L->status == LUA_OK) ? nargs + 1 : nargs); 691 api_checknelems(L, (L->status == LUA_OK) ? nargs + 1 : nargs);