diff options
Diffstat (limited to '')
| -rw-r--r-- | src/lua/ldo.c (renamed from src/lua-5.3/ldo.c) | 506 |
1 files changed, 263 insertions, 243 deletions
diff --git a/src/lua-5.3/ldo.c b/src/lua/ldo.c index 316e45c..c563b1d 100644 --- a/src/lua-5.3/ldo.c +++ b/src/lua/ldo.c | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: ldo.c,v 2.157.1.1 2017/04/19 17:20:42 roberto Exp $ | 2 | ** $Id: ldo.c $ |
| 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 | */ |
| @@ -88,7 +88,7 @@ struct lua_longjmp { | |||
| 88 | }; | 88 | }; |
| 89 | 89 | ||
| 90 | 90 | ||
| 91 | static void seterrorobj (lua_State *L, int errcode, StkId oldtop) { | 91 | void luaD_seterrorobj (lua_State *L, int errcode, StkId oldtop) { |
| 92 | switch (errcode) { | 92 | switch (errcode) { |
| 93 | case LUA_ERRMEM: { /* memory error? */ | 93 | case LUA_ERRMEM: { /* memory error? */ |
| 94 | setsvalue2s(L, oldtop, G(L)->memerrmsg); /* reuse preregistered msg. */ | 94 | setsvalue2s(L, oldtop, G(L)->memerrmsg); /* reuse preregistered msg. */ |
| @@ -98,6 +98,10 @@ static void seterrorobj (lua_State *L, int errcode, StkId oldtop) { | |||
| 98 | setsvalue2s(L, oldtop, luaS_newliteral(L, "error in error handling")); | 98 | setsvalue2s(L, oldtop, luaS_newliteral(L, "error in error handling")); |
| 99 | break; | 99 | break; |
| 100 | } | 100 | } |
| 101 | case CLOSEPROTECT: { | ||
| 102 | setnilvalue(s2v(oldtop)); /* no error message */ | ||
| 103 | break; | ||
| 104 | } | ||
| 101 | default: { | 105 | default: { |
| 102 | setobjs2s(L, oldtop, L->top - 1); /* error message on current top */ | 106 | setobjs2s(L, oldtop, L->top - 1); /* error message on current top */ |
| 103 | break; | 107 | break; |
| @@ -114,6 +118,7 @@ l_noret luaD_throw (lua_State *L, int errcode) { | |||
| 114 | } | 118 | } |
| 115 | else { /* thread has no error handler */ | 119 | else { /* thread has no error handler */ |
| 116 | global_State *g = G(L); | 120 | global_State *g = G(L); |
| 121 | errcode = luaF_close(L, L->stack, errcode); /* close all upvalues */ | ||
| 117 | L->status = cast_byte(errcode); /* mark it as dead */ | 122 | L->status = cast_byte(errcode); /* mark it as dead */ |
| 118 | if (g->mainthread->errorJmp) { /* main thread has a handler? */ | 123 | if (g->mainthread->errorJmp) { /* main thread has a handler? */ |
| 119 | setobjs2s(L, g->mainthread->top++, L->top - 1); /* copy error obj. */ | 124 | setobjs2s(L, g->mainthread->top++, L->top - 1); /* copy error obj. */ |
| @@ -121,7 +126,7 @@ l_noret luaD_throw (lua_State *L, int errcode) { | |||
| 121 | } | 126 | } |
| 122 | else { /* no handler at all; abort */ | 127 | else { /* no handler at all; abort */ |
| 123 | if (g->panic) { /* panic function? */ | 128 | if (g->panic) { /* panic function? */ |
| 124 | seterrorobj(L, errcode, L->top); /* assume EXTRA_STACK */ | 129 | luaD_seterrorobj(L, errcode, L->top); /* assume EXTRA_STACK */ |
| 125 | if (L->ci->top < L->top) | 130 | if (L->ci->top < L->top) |
| 126 | L->ci->top = L->top; /* pushing msg. can break this invariant */ | 131 | L->ci->top = L->top; /* pushing msg. can break this invariant */ |
| 127 | lua_unlock(L); | 132 | lua_unlock(L); |
| @@ -134,7 +139,8 @@ l_noret luaD_throw (lua_State *L, int errcode) { | |||
| 134 | 139 | ||
| 135 | 140 | ||
| 136 | int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud) { | 141 | int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud) { |
| 137 | unsigned short oldnCcalls = L->nCcalls; | 142 | global_State *g = G(L); |
| 143 | l_uint32 oldnCcalls = g->Cstacklimit - (L->nCcalls + L->nci); | ||
| 138 | struct lua_longjmp lj; | 144 | struct lua_longjmp lj; |
| 139 | lj.status = LUA_OK; | 145 | lj.status = LUA_OK; |
| 140 | lj.previous = L->errorJmp; /* chain new error handler */ | 146 | lj.previous = L->errorJmp; /* chain new error handler */ |
| @@ -143,7 +149,7 @@ int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud) { | |||
| 143 | (*f)(L, ud); | 149 | (*f)(L, ud); |
| 144 | ); | 150 | ); |
| 145 | L->errorJmp = lj.previous; /* restore old error handler */ | 151 | L->errorJmp = lj.previous; /* restore old error handler */ |
| 146 | L->nCcalls = oldnCcalls; | 152 | L->nCcalls = g->Cstacklimit - oldnCcalls - L->nci; |
| 147 | return lj.status; | 153 | return lj.status; |
| 148 | } | 154 | } |
| 149 | 155 | ||
| @@ -155,17 +161,19 @@ int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud) { | |||
| 155 | ** Stack reallocation | 161 | ** Stack reallocation |
| 156 | ** =================================================================== | 162 | ** =================================================================== |
| 157 | */ | 163 | */ |
| 158 | static void correctstack (lua_State *L, TValue *oldstack) { | 164 | static void correctstack (lua_State *L, StkId oldstack, StkId newstack) { |
| 159 | CallInfo *ci; | 165 | CallInfo *ci; |
| 160 | UpVal *up; | 166 | UpVal *up; |
| 161 | L->top = (L->top - oldstack) + L->stack; | 167 | if (oldstack == newstack) |
| 168 | return; /* stack address did not change */ | ||
| 169 | L->top = (L->top - oldstack) + newstack; | ||
| 162 | for (up = L->openupval; up != NULL; up = up->u.open.next) | 170 | for (up = L->openupval; up != NULL; up = up->u.open.next) |
| 163 | up->v = (up->v - oldstack) + L->stack; | 171 | up->v = s2v((uplevel(up) - oldstack) + newstack); |
| 164 | for (ci = L->ci; ci != NULL; ci = ci->previous) { | 172 | for (ci = L->ci; ci != NULL; ci = ci->previous) { |
| 165 | ci->top = (ci->top - oldstack) + L->stack; | 173 | ci->top = (ci->top - oldstack) + newstack; |
| 166 | ci->func = (ci->func - oldstack) + L->stack; | 174 | ci->func = (ci->func - oldstack) + newstack; |
| 167 | if (isLua(ci)) | 175 | if (isLua(ci)) |
| 168 | ci->u.l.base = (ci->u.l.base - oldstack) + L->stack; | 176 | ci->u.l.trap = 1; /* signal to update 'trap' in 'luaV_execute' */ |
| 169 | } | 177 | } |
| 170 | } | 178 | } |
| 171 | 179 | ||
| @@ -174,36 +182,53 @@ static void correctstack (lua_State *L, TValue *oldstack) { | |||
| 174 | #define ERRORSTACKSIZE (LUAI_MAXSTACK + 200) | 182 | #define ERRORSTACKSIZE (LUAI_MAXSTACK + 200) |
| 175 | 183 | ||
| 176 | 184 | ||
| 177 | void luaD_reallocstack (lua_State *L, int newsize) { | 185 | int luaD_reallocstack (lua_State *L, int newsize, int raiseerror) { |
| 178 | TValue *oldstack = L->stack; | ||
| 179 | int lim = L->stacksize; | 186 | int lim = L->stacksize; |
| 187 | StkId newstack = luaM_reallocvector(L, L->stack, lim, newsize, StackValue); | ||
| 180 | lua_assert(newsize <= LUAI_MAXSTACK || newsize == ERRORSTACKSIZE); | 188 | lua_assert(newsize <= LUAI_MAXSTACK || newsize == ERRORSTACKSIZE); |
| 181 | lua_assert(L->stack_last - L->stack == L->stacksize - EXTRA_STACK); | 189 | lua_assert(L->stack_last - L->stack == L->stacksize - EXTRA_STACK); |
| 182 | luaM_reallocvector(L, L->stack, L->stacksize, newsize, TValue); | 190 | if (unlikely(newstack == NULL)) { /* reallocation failed? */ |
| 191 | if (raiseerror) | ||
| 192 | luaM_error(L); | ||
| 193 | else return 0; /* do not raise an error */ | ||
| 194 | } | ||
| 183 | for (; lim < newsize; lim++) | 195 | for (; lim < newsize; lim++) |
| 184 | setnilvalue(L->stack + lim); /* erase new segment */ | 196 | setnilvalue(s2v(newstack + lim)); /* erase new segment */ |
| 197 | correctstack(L, L->stack, newstack); | ||
| 198 | L->stack = newstack; | ||
| 185 | L->stacksize = newsize; | 199 | L->stacksize = newsize; |
| 186 | L->stack_last = L->stack + newsize - EXTRA_STACK; | 200 | L->stack_last = L->stack + newsize - EXTRA_STACK; |
| 187 | correctstack(L, oldstack); | 201 | return 1; |
| 188 | } | 202 | } |
| 189 | 203 | ||
| 190 | 204 | ||
| 191 | void luaD_growstack (lua_State *L, int n) { | 205 | /* |
| 206 | ** Try to grow the stack by at least 'n' elements. when 'raiseerror' | ||
| 207 | ** is true, raises any error; otherwise, return 0 in case of errors. | ||
| 208 | */ | ||
| 209 | int luaD_growstack (lua_State *L, int n, int raiseerror) { | ||
| 192 | int size = L->stacksize; | 210 | int size = L->stacksize; |
| 193 | if (size > LUAI_MAXSTACK) /* error after extra size? */ | 211 | int newsize = 2 * size; /* tentative new size */ |
| 194 | luaD_throw(L, LUA_ERRERR); | 212 | if (unlikely(size > LUAI_MAXSTACK)) { /* need more space after extra size? */ |
| 213 | if (raiseerror) | ||
| 214 | luaD_throw(L, LUA_ERRERR); /* error inside message handler */ | ||
| 215 | else return 0; | ||
| 216 | } | ||
| 195 | else { | 217 | else { |
| 196 | int needed = cast_int(L->top - L->stack) + n + EXTRA_STACK; | 218 | int needed = cast_int(L->top - L->stack) + n + EXTRA_STACK; |
| 197 | int newsize = 2 * size; | 219 | if (newsize > LUAI_MAXSTACK) /* cannot cross the limit */ |
| 198 | if (newsize > LUAI_MAXSTACK) newsize = LUAI_MAXSTACK; | 220 | newsize = LUAI_MAXSTACK; |
| 199 | if (newsize < needed) newsize = needed; | 221 | if (newsize < needed) /* but must respect what was asked for */ |
| 200 | if (newsize > LUAI_MAXSTACK) { /* stack overflow? */ | 222 | newsize = needed; |
| 201 | luaD_reallocstack(L, ERRORSTACKSIZE); | 223 | if (unlikely(newsize > LUAI_MAXSTACK)) { /* stack overflow? */ |
| 202 | luaG_runerror(L, "stack overflow"); | 224 | /* add extra size to be able to handle the error message */ |
| 225 | luaD_reallocstack(L, ERRORSTACKSIZE, raiseerror); | ||
| 226 | if (raiseerror) | ||
| 227 | luaG_runerror(L, "stack overflow"); | ||
| 228 | else return 0; | ||
| 203 | } | 229 | } |
| 204 | else | 230 | } /* else no errors */ |
| 205 | luaD_reallocstack(L, newsize); | 231 | return luaD_reallocstack(L, newsize, raiseerror); |
| 206 | } | ||
| 207 | } | 232 | } |
| 208 | 233 | ||
| 209 | 234 | ||
| @@ -223,17 +248,14 @@ void luaD_shrinkstack (lua_State *L) { | |||
| 223 | int goodsize = inuse + (inuse / 8) + 2*EXTRA_STACK; | 248 | int goodsize = inuse + (inuse / 8) + 2*EXTRA_STACK; |
| 224 | if (goodsize > LUAI_MAXSTACK) | 249 | if (goodsize > LUAI_MAXSTACK) |
| 225 | goodsize = LUAI_MAXSTACK; /* respect stack limit */ | 250 | goodsize = LUAI_MAXSTACK; /* respect stack limit */ |
| 226 | if (L->stacksize > LUAI_MAXSTACK) /* had been handling stack overflow? */ | ||
| 227 | luaE_freeCI(L); /* free all CIs (list grew because of an error) */ | ||
| 228 | else | ||
| 229 | luaE_shrinkCI(L); /* shrink list */ | ||
| 230 | /* if thread is currently not handling a stack overflow and its | 251 | /* if thread is currently not handling a stack overflow and its |
| 231 | good size is smaller than current size, shrink its stack */ | 252 | good size is smaller than current size, shrink its stack */ |
| 232 | if (inuse <= (LUAI_MAXSTACK - EXTRA_STACK) && | 253 | if (inuse <= (LUAI_MAXSTACK - EXTRA_STACK) && |
| 233 | goodsize < L->stacksize) | 254 | goodsize < L->stacksize) |
| 234 | luaD_reallocstack(L, goodsize); | 255 | luaD_reallocstack(L, goodsize, 0); /* ok if that fails */ |
| 235 | else /* don't change stack */ | 256 | else /* don't change stack */ |
| 236 | condmovestack(L,{},{}); /* (change only for debugging) */ | 257 | condmovestack(L,{},{}); /* (change only for debugging) */ |
| 258 | luaE_shrinkCI(L); /* shrink CI list */ | ||
| 237 | } | 259 | } |
| 238 | 260 | ||
| 239 | 261 | ||
| @@ -247,12 +269,14 @@ void luaD_inctop (lua_State *L) { | |||
| 247 | 269 | ||
| 248 | /* | 270 | /* |
| 249 | ** Call a hook for the given event. Make sure there is a hook to be | 271 | ** Call a hook for the given event. Make sure there is a hook to be |
| 250 | ** called. (Both 'L->hook' and 'L->hookmask', which triggers this | 272 | ** called. (Both 'L->hook' and 'L->hookmask', which trigger this |
| 251 | ** function, can be changed asynchronously by signals.) | 273 | ** function, can be changed asynchronously by signals.) |
| 252 | */ | 274 | */ |
| 253 | void luaD_hook (lua_State *L, int event, int line) { | 275 | void luaD_hook (lua_State *L, int event, int line, |
| 276 | int ftransfer, int ntransfer) { | ||
| 254 | lua_Hook hook = L->hook; | 277 | lua_Hook hook = L->hook; |
| 255 | if (hook && L->allowhook) { /* make sure there is a hook */ | 278 | if (hook && L->allowhook) { /* make sure there is a hook */ |
| 279 | int mask = CIST_HOOKED; | ||
| 256 | CallInfo *ci = L->ci; | 280 | CallInfo *ci = L->ci; |
| 257 | ptrdiff_t top = savestack(L, L->top); | 281 | ptrdiff_t top = savestack(L, L->top); |
| 258 | ptrdiff_t ci_top = savestack(L, ci->top); | 282 | ptrdiff_t ci_top = savestack(L, ci->top); |
| @@ -260,11 +284,16 @@ void luaD_hook (lua_State *L, int event, int line) { | |||
| 260 | ar.event = event; | 284 | ar.event = event; |
| 261 | ar.currentline = line; | 285 | ar.currentline = line; |
| 262 | ar.i_ci = ci; | 286 | ar.i_ci = ci; |
| 287 | if (ntransfer != 0) { | ||
| 288 | mask |= CIST_TRAN; /* 'ci' has transfer information */ | ||
| 289 | ci->u2.transferinfo.ftransfer = ftransfer; | ||
| 290 | ci->u2.transferinfo.ntransfer = ntransfer; | ||
| 291 | } | ||
| 263 | luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */ | 292 | luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */ |
| 264 | ci->top = L->top + LUA_MINSTACK; | 293 | if (L->top + LUA_MINSTACK > ci->top) |
| 265 | lua_assert(ci->top <= L->stack_last); | 294 | ci->top = L->top + LUA_MINSTACK; |
| 266 | L->allowhook = 0; /* cannot call hooks inside a hook */ | 295 | L->allowhook = 0; /* cannot call hooks inside a hook */ |
| 267 | ci->callstatus |= CIST_HOOKED; | 296 | ci->callstatus |= mask; |
| 268 | lua_unlock(L); | 297 | lua_unlock(L); |
| 269 | (*hook)(L, &ar); | 298 | (*hook)(L, &ar); |
| 270 | lua_lock(L); | 299 | lua_lock(L); |
| @@ -272,56 +301,66 @@ void luaD_hook (lua_State *L, int event, int line) { | |||
| 272 | L->allowhook = 1; | 301 | L->allowhook = 1; |
| 273 | ci->top = restorestack(L, ci_top); | 302 | ci->top = restorestack(L, ci_top); |
| 274 | L->top = restorestack(L, top); | 303 | L->top = restorestack(L, top); |
| 275 | ci->callstatus &= ~CIST_HOOKED; | 304 | ci->callstatus &= ~mask; |
| 276 | } | 305 | } |
| 277 | } | 306 | } |
| 278 | 307 | ||
| 279 | 308 | ||
| 280 | static void callhook (lua_State *L, CallInfo *ci) { | 309 | /* |
| 281 | int hook = LUA_HOOKCALL; | 310 | ** Executes a call hook for Lua functions. This function is called |
| 311 | ** whenever 'hookmask' is not zero, so it checks whether call hooks are | ||
| 312 | ** active. | ||
| 313 | */ | ||
| 314 | void luaD_hookcall (lua_State *L, CallInfo *ci) { | ||
| 315 | int hook = (ci->callstatus & CIST_TAIL) ? LUA_HOOKTAILCALL : LUA_HOOKCALL; | ||
| 316 | Proto *p; | ||
| 317 | if (!(L->hookmask & LUA_MASKCALL)) /* some other hook? */ | ||
| 318 | return; /* don't call hook */ | ||
| 319 | p = clLvalue(s2v(ci->func))->p; | ||
| 320 | L->top = ci->top; /* prepare top */ | ||
| 282 | ci->u.l.savedpc++; /* hooks assume 'pc' is already incremented */ | 321 | ci->u.l.savedpc++; /* hooks assume 'pc' is already incremented */ |
| 283 | if (isLua(ci->previous) && | 322 | luaD_hook(L, hook, -1, 1, p->numparams); |
| 284 | GET_OPCODE(*(ci->previous->u.l.savedpc - 1)) == OP_TAILCALL) { | ||
| 285 | ci->callstatus |= CIST_TAIL; | ||
| 286 | hook = LUA_HOOKTAILCALL; | ||
| 287 | } | ||
| 288 | luaD_hook(L, hook, -1); | ||
| 289 | ci->u.l.savedpc--; /* correct 'pc' */ | 323 | ci->u.l.savedpc--; /* correct 'pc' */ |
| 290 | } | 324 | } |
| 291 | 325 | ||
| 292 | 326 | ||
| 293 | static StkId adjust_varargs (lua_State *L, Proto *p, int actual) { | 327 | static StkId rethook (lua_State *L, CallInfo *ci, StkId firstres, int nres) { |
| 294 | int i; | 328 | ptrdiff_t oldtop = savestack(L, L->top); /* hook may change top */ |
| 295 | int nfixargs = p->numparams; | 329 | int delta = 0; |
| 296 | StkId base, fixed; | 330 | if (isLuacode(ci)) { |
| 297 | /* move fixed parameters to final position */ | 331 | Proto *p = clLvalue(s2v(ci->func))->p; |
| 298 | fixed = L->top - actual; /* first fixed argument */ | 332 | if (p->is_vararg) |
| 299 | base = L->top; /* final position of first argument */ | 333 | delta = ci->u.l.nextraargs + p->numparams + 1; |
| 300 | for (i = 0; i < nfixargs && i < actual; i++) { | 334 | if (L->top < ci->top) |
| 301 | setobjs2s(L, L->top++, fixed + i); | 335 | L->top = ci->top; /* correct top to run hook */ |
| 302 | setnilvalue(fixed + i); /* erase original copy (for GC) */ | ||
| 303 | } | 336 | } |
| 304 | for (; i < nfixargs; i++) | 337 | if (L->hookmask & LUA_MASKRET) { /* is return hook on? */ |
| 305 | setnilvalue(L->top++); /* complete missing arguments */ | 338 | int ftransfer; |
| 306 | return base; | 339 | ci->func += delta; /* if vararg, back to virtual 'func' */ |
| 340 | ftransfer = cast(unsigned short, firstres - ci->func); | ||
| 341 | luaD_hook(L, LUA_HOOKRET, -1, ftransfer, nres); /* call it */ | ||
| 342 | ci->func -= delta; | ||
| 343 | } | ||
| 344 | if (isLua(ci->previous)) | ||
| 345 | L->oldpc = ci->previous->u.l.savedpc; /* update 'oldpc' */ | ||
| 346 | return restorestack(L, oldtop); | ||
| 307 | } | 347 | } |
| 308 | 348 | ||
| 309 | 349 | ||
| 310 | /* | 350 | /* |
| 311 | ** Check whether __call metafield of 'func' is a function. If so, put | 351 | ** Check whether 'func' has a '__call' metafield. If so, put it in the |
| 312 | ** it in stack below original 'func' so that 'luaD_precall' can call | 352 | ** stack, below original 'func', so that 'luaD_call' can call it. Raise |
| 313 | ** it. Raise an error if __call metafield is not a function. | 353 | ** an error if there is no '__call' metafield. |
| 314 | */ | 354 | */ |
| 315 | static void tryfuncTM (lua_State *L, StkId func) { | 355 | void luaD_tryfuncTM (lua_State *L, StkId func) { |
| 316 | const TValue *tm = luaT_gettmbyobj(L, func, TM_CALL); | 356 | const TValue *tm = luaT_gettmbyobj(L, s2v(func), TM_CALL); |
| 317 | StkId p; | 357 | StkId p; |
| 318 | if (!ttisfunction(tm)) | 358 | if (unlikely(ttisnil(tm))) |
| 319 | luaG_typeerror(L, func, "call"); | 359 | luaG_typeerror(L, s2v(func), "call"); /* nothing to call */ |
| 320 | /* Open a hole inside the stack at 'func' */ | 360 | for (p = L->top; p > func; p--) /* open space for metamethod */ |
| 321 | for (p = L->top; p > func; p--) | ||
| 322 | setobjs2s(L, p, p-1); | 361 | setobjs2s(L, p, p-1); |
| 323 | L->top++; /* slot ensured by caller */ | 362 | L->top++; /* stack space pre-allocated by the caller */ |
| 324 | setobj2s(L, func, tm); /* tag method is the new function to be called */ | 363 | setobj2s(L, func, tm); /* metamethod is the new function to be called */ |
| 325 | } | 364 | } |
| 326 | 365 | ||
| 327 | 366 | ||
| @@ -331,183 +370,161 @@ static void tryfuncTM (lua_State *L, StkId func) { | |||
| 331 | ** expressions, multiple results for tail calls/single parameters) | 370 | ** expressions, multiple results for tail calls/single parameters) |
| 332 | ** separated. | 371 | ** separated. |
| 333 | */ | 372 | */ |
| 334 | static int moveresults (lua_State *L, const TValue *firstResult, StkId res, | 373 | static void moveresults (lua_State *L, StkId res, int nres, int wanted) { |
| 335 | int nres, int wanted) { | 374 | StkId firstresult; |
| 375 | int i; | ||
| 336 | switch (wanted) { /* handle typical cases separately */ | 376 | switch (wanted) { /* handle typical cases separately */ |
| 337 | case 0: break; /* nothing to move */ | 377 | case 0: /* no values needed */ |
| 338 | case 1: { /* one result needed */ | 378 | L->top = res; |
| 379 | return; | ||
| 380 | case 1: /* one value needed */ | ||
| 339 | if (nres == 0) /* no results? */ | 381 | if (nres == 0) /* no results? */ |
| 340 | firstResult = luaO_nilobject; /* adjust with nil */ | 382 | setnilvalue(s2v(res)); /* adjust with nil */ |
| 341 | setobjs2s(L, res, firstResult); /* move it to proper place */ | 383 | else |
| 384 | setobjs2s(L, res, L->top - nres); /* move it to proper place */ | ||
| 385 | L->top = res + 1; | ||
| 386 | return; | ||
| 387 | case LUA_MULTRET: | ||
| 388 | wanted = nres; /* we want all results */ | ||
| 342 | break; | 389 | break; |
| 343 | } | 390 | default: /* multiple results (or to-be-closed variables) */ |
| 344 | case LUA_MULTRET: { | 391 | if (hastocloseCfunc(wanted)) { /* to-be-closed variables? */ |
| 345 | int i; | 392 | ptrdiff_t savedres = savestack(L, res); |
| 346 | for (i = 0; i < nres; i++) /* move all results to correct place */ | 393 | luaF_close(L, res, LUA_OK); /* may change the stack */ |
| 347 | setobjs2s(L, res + i, firstResult + i); | 394 | res = restorestack(L, savedres); |
| 348 | L->top = res + nres; | 395 | wanted = codeNresults(wanted); /* correct value */ |
| 349 | return 0; /* wanted == LUA_MULTRET */ | 396 | if (wanted == LUA_MULTRET) |
| 350 | } | 397 | wanted = nres; |
| 351 | default: { | ||
| 352 | int i; | ||
| 353 | if (wanted <= nres) { /* enough results? */ | ||
| 354 | for (i = 0; i < wanted; i++) /* move wanted results to correct place */ | ||
| 355 | setobjs2s(L, res + i, firstResult + i); | ||
| 356 | } | ||
| 357 | else { /* not enough results; use all of them plus nils */ | ||
| 358 | for (i = 0; i < nres; i++) /* move all results to correct place */ | ||
| 359 | setobjs2s(L, res + i, firstResult + i); | ||
| 360 | for (; i < wanted; i++) /* complete wanted number of results */ | ||
| 361 | setnilvalue(res + i); | ||
| 362 | } | 398 | } |
| 363 | break; | 399 | break; |
| 364 | } | ||
| 365 | } | 400 | } |
| 401 | firstresult = L->top - nres; /* index of first result */ | ||
| 402 | /* move all results to correct place */ | ||
| 403 | for (i = 0; i < nres && i < wanted; i++) | ||
| 404 | setobjs2s(L, res + i, firstresult + i); | ||
| 405 | for (; i < wanted; i++) /* complete wanted number of results */ | ||
| 406 | setnilvalue(s2v(res + i)); | ||
| 366 | L->top = res + wanted; /* top points after the last result */ | 407 | L->top = res + wanted; /* top points after the last result */ |
| 367 | return 1; | ||
| 368 | } | 408 | } |
| 369 | 409 | ||
| 370 | 410 | ||
| 371 | /* | 411 | /* |
| 372 | ** Finishes a function call: calls hook if necessary, removes CallInfo, | 412 | ** Finishes a function call: calls hook if necessary, removes CallInfo, |
| 373 | ** moves current number of results to proper place; returns 0 iff call | 413 | ** moves current number of results to proper place. |
| 374 | ** wanted multiple (variable number of) results. | ||
| 375 | */ | 414 | */ |
| 376 | int luaD_poscall (lua_State *L, CallInfo *ci, StkId firstResult, int nres) { | 415 | void luaD_poscall (lua_State *L, CallInfo *ci, int nres) { |
| 377 | StkId res; | 416 | if (L->hookmask) |
| 378 | int wanted = ci->nresults; | 417 | L->top = rethook(L, ci, L->top - nres, nres); |
| 379 | if (L->hookmask & (LUA_MASKRET | LUA_MASKLINE)) { | ||
| 380 | if (L->hookmask & LUA_MASKRET) { | ||
| 381 | ptrdiff_t fr = savestack(L, firstResult); /* hook may change stack */ | ||
| 382 | luaD_hook(L, LUA_HOOKRET, -1); | ||
| 383 | firstResult = restorestack(L, fr); | ||
| 384 | } | ||
| 385 | L->oldpc = ci->previous->u.l.savedpc; /* 'oldpc' for caller function */ | ||
| 386 | } | ||
| 387 | res = ci->func; /* res == final position of 1st result */ | ||
| 388 | L->ci = ci->previous; /* back to caller */ | 418 | L->ci = ci->previous; /* back to caller */ |
| 389 | /* move results to proper place */ | 419 | /* move results to proper place */ |
| 390 | return moveresults(L, firstResult, res, nres, wanted); | 420 | moveresults(L, ci->func, nres, ci->nresults); |
| 391 | } | 421 | } |
| 392 | 422 | ||
| 393 | 423 | ||
| 394 | 424 | ||
| 395 | #define next_ci(L) (L->ci = (L->ci->next ? L->ci->next : luaE_extendCI(L))) | 425 | #define next_ci(L) (L->ci->next ? L->ci->next : luaE_extendCI(L)) |
| 396 | 426 | ||
| 397 | 427 | ||
| 398 | /* macro to check stack size, preserving 'p' */ | 428 | /* |
| 399 | #define checkstackp(L,n,p) \ | 429 | ** Prepare a function for a tail call, building its call info on top |
| 400 | luaD_checkstackaux(L, n, \ | 430 | ** of the current call info. 'narg1' is the number of arguments plus 1 |
| 401 | ptrdiff_t t__ = savestack(L, p); /* save 'p' */ \ | 431 | ** (so that it includes the function itself). |
| 402 | luaC_checkGC(L), /* stack grow uses memory */ \ | 432 | */ |
| 403 | p = restorestack(L, t__)) /* 'pos' part: restore 'p' */ | 433 | void luaD_pretailcall (lua_State *L, CallInfo *ci, StkId func, int narg1) { |
| 434 | Proto *p = clLvalue(s2v(func))->p; | ||
| 435 | int fsize = p->maxstacksize; /* frame size */ | ||
| 436 | int nfixparams = p->numparams; | ||
| 437 | int i; | ||
| 438 | for (i = 0; i < narg1; i++) /* move down function and arguments */ | ||
| 439 | setobjs2s(L, ci->func + i, func + i); | ||
| 440 | checkstackGC(L, fsize); | ||
| 441 | func = ci->func; /* moved-down function */ | ||
| 442 | for (; narg1 <= nfixparams; narg1++) | ||
| 443 | setnilvalue(s2v(func + narg1)); /* complete missing arguments */ | ||
| 444 | ci->top = func + 1 + fsize; /* top for new function */ | ||
| 445 | lua_assert(ci->top <= L->stack_last); | ||
| 446 | ci->u.l.savedpc = p->code; /* starting point */ | ||
| 447 | ci->callstatus |= CIST_TAIL; | ||
| 448 | L->top = func + narg1; /* set top */ | ||
| 449 | } | ||
| 404 | 450 | ||
| 405 | 451 | ||
| 406 | /* | 452 | /* |
| 407 | ** Prepares a function call: checks the stack, creates a new CallInfo | 453 | ** Call a function (C or Lua). The function to be called is at *func. |
| 408 | ** entry, fills in the relevant information, calls hook if needed. | 454 | ** The arguments are on the stack, right after the function. |
| 409 | ** If function is a C function, does the call, too. (Otherwise, leave | 455 | ** When returns, all the results are on the stack, starting at the original |
| 410 | ** the execution ('luaV_execute') to the caller, to allow stackless | 456 | ** function position. |
| 411 | ** calls.) Returns true iff function has been executed (C function). | ||
| 412 | */ | 457 | */ |
| 413 | int luaD_precall (lua_State *L, StkId func, int nresults) { | 458 | void luaD_call (lua_State *L, StkId func, int nresults) { |
| 414 | lua_CFunction f; | 459 | lua_CFunction f; |
| 415 | CallInfo *ci; | 460 | retry: |
| 416 | switch (ttype(func)) { | 461 | switch (ttypetag(s2v(func))) { |
| 417 | case LUA_TCCL: /* C closure */ | 462 | case LUA_VCCL: /* C closure */ |
| 418 | f = clCvalue(func)->f; | 463 | f = clCvalue(s2v(func))->f; |
| 419 | goto Cfunc; | 464 | goto Cfunc; |
| 420 | case LUA_TLCF: /* light C function */ | 465 | case LUA_VLCF: /* light C function */ |
| 421 | f = fvalue(func); | 466 | f = fvalue(s2v(func)); |
| 422 | Cfunc: { | 467 | Cfunc: { |
| 423 | int n; /* number of returns */ | 468 | int n; /* number of returns */ |
| 469 | CallInfo *ci = next_ci(L); | ||
| 424 | checkstackp(L, LUA_MINSTACK, func); /* ensure minimum stack size */ | 470 | checkstackp(L, LUA_MINSTACK, func); /* ensure minimum stack size */ |
| 425 | ci = next_ci(L); /* now 'enter' new function */ | ||
| 426 | ci->nresults = nresults; | 471 | ci->nresults = nresults; |
| 427 | ci->func = func; | 472 | ci->callstatus = CIST_C; |
| 428 | ci->top = L->top + LUA_MINSTACK; | 473 | ci->top = L->top + LUA_MINSTACK; |
| 474 | ci->func = func; | ||
| 475 | L->ci = ci; | ||
| 429 | lua_assert(ci->top <= L->stack_last); | 476 | lua_assert(ci->top <= L->stack_last); |
| 430 | ci->callstatus = 0; | 477 | if (L->hookmask & LUA_MASKCALL) { |
| 431 | if (L->hookmask & LUA_MASKCALL) | 478 | int narg = cast_int(L->top - func) - 1; |
| 432 | luaD_hook(L, LUA_HOOKCALL, -1); | 479 | luaD_hook(L, LUA_HOOKCALL, -1, 1, narg); |
| 480 | } | ||
| 433 | lua_unlock(L); | 481 | lua_unlock(L); |
| 434 | n = (*f)(L); /* do the actual call */ | 482 | n = (*f)(L); /* do the actual call */ |
| 435 | lua_lock(L); | 483 | lua_lock(L); |
| 436 | api_checknelems(L, n); | 484 | api_checknelems(L, n); |
| 437 | luaD_poscall(L, ci, L->top - n, n); | 485 | luaD_poscall(L, ci, n); |
| 438 | return 1; | 486 | break; |
| 439 | } | 487 | } |
| 440 | case LUA_TLCL: { /* Lua function: prepare its call */ | 488 | case LUA_VLCL: { /* Lua function */ |
| 441 | StkId base; | 489 | CallInfo *ci = next_ci(L); |
| 442 | Proto *p = clLvalue(func)->p; | 490 | Proto *p = clLvalue(s2v(func))->p; |
| 443 | int n = cast_int(L->top - func) - 1; /* number of real arguments */ | 491 | int narg = cast_int(L->top - func) - 1; /* number of real arguments */ |
| 492 | int nfixparams = p->numparams; | ||
| 444 | int fsize = p->maxstacksize; /* frame size */ | 493 | int fsize = p->maxstacksize; /* frame size */ |
| 445 | checkstackp(L, fsize, func); | 494 | checkstackp(L, fsize, func); |
| 446 | if (p->is_vararg) | ||
| 447 | base = adjust_varargs(L, p, n); | ||
| 448 | else { /* non vararg function */ | ||
| 449 | for (; n < p->numparams; n++) | ||
| 450 | setnilvalue(L->top++); /* complete missing arguments */ | ||
| 451 | base = func + 1; | ||
| 452 | } | ||
| 453 | ci = next_ci(L); /* now 'enter' new function */ | ||
| 454 | ci->nresults = nresults; | 495 | ci->nresults = nresults; |
| 496 | ci->u.l.savedpc = p->code; /* starting point */ | ||
| 497 | ci->callstatus = 0; | ||
| 498 | ci->top = func + 1 + fsize; | ||
| 455 | ci->func = func; | 499 | ci->func = func; |
| 456 | ci->u.l.base = base; | 500 | L->ci = ci; |
| 457 | L->top = ci->top = base + fsize; | 501 | for (; narg < nfixparams; narg++) |
| 502 | setnilvalue(s2v(L->top++)); /* complete missing arguments */ | ||
| 458 | lua_assert(ci->top <= L->stack_last); | 503 | lua_assert(ci->top <= L->stack_last); |
| 459 | ci->u.l.savedpc = p->code; /* starting point */ | 504 | luaV_execute(L, ci); /* run the function */ |
| 460 | ci->callstatus = CIST_LUA; | 505 | break; |
| 461 | if (L->hookmask & LUA_MASKCALL) | ||
| 462 | callhook(L, ci); | ||
| 463 | return 0; | ||
| 464 | } | 506 | } |
| 465 | default: { /* not a function */ | 507 | default: { /* not a function */ |
| 466 | checkstackp(L, 1, func); /* ensure space for metamethod */ | 508 | checkstackp(L, 1, func); /* space for metamethod */ |
| 467 | tryfuncTM(L, func); /* try to get '__call' metamethod */ | 509 | luaD_tryfuncTM(L, func); /* try to get '__call' metamethod */ |
| 468 | return luaD_precall(L, func, nresults); /* now it must be a function */ | 510 | goto retry; /* try again with metamethod */ |
| 469 | } | 511 | } |
| 470 | } | 512 | } |
| 471 | } | 513 | } |
| 472 | 514 | ||
| 473 | 515 | ||
| 474 | /* | 516 | /* |
| 475 | ** Check appropriate error for stack overflow ("regular" overflow or | 517 | ** Similar to 'luaD_call', but does not allow yields during the call. |
| 476 | ** overflow while handling stack overflow). If 'nCalls' is larger than | 518 | ** If there is a stack overflow, freeing all CI structures will |
| 477 | ** LUAI_MAXCCALLS (which means it is handling a "regular" overflow) but | 519 | ** force the subsequent call to invoke 'luaE_extendCI', which then |
| 478 | ** smaller than 9/8 of LUAI_MAXCCALLS, does not report an error (to | 520 | ** will raise any errors. |
| 479 | ** allow overflow handling to work) | ||
| 480 | */ | ||
| 481 | static void stackerror (lua_State *L) { | ||
| 482 | if (L->nCcalls == LUAI_MAXCCALLS) | ||
| 483 | luaG_runerror(L, "C stack overflow"); | ||
| 484 | else if (L->nCcalls >= (LUAI_MAXCCALLS + (LUAI_MAXCCALLS>>3))) | ||
| 485 | luaD_throw(L, LUA_ERRERR); /* error while handing stack error */ | ||
| 486 | } | ||
| 487 | |||
| 488 | |||
| 489 | /* | ||
| 490 | ** Call a function (C or Lua). The function to be called is at *func. | ||
| 491 | ** The arguments are on the stack, right after the function. | ||
| 492 | ** When returns, all the results are on the stack, starting at the original | ||
| 493 | ** function position. | ||
| 494 | */ | ||
| 495 | void luaD_call (lua_State *L, StkId func, int nResults) { | ||
| 496 | if (++L->nCcalls >= LUAI_MAXCCALLS) | ||
| 497 | stackerror(L); | ||
| 498 | if (!luaD_precall(L, func, nResults)) /* is a Lua function? */ | ||
| 499 | luaV_execute(L); /* call it */ | ||
| 500 | L->nCcalls--; | ||
| 501 | } | ||
| 502 | |||
| 503 | |||
| 504 | /* | ||
| 505 | ** Similar to 'luaD_call', but does not allow yields during the call | ||
| 506 | */ | 521 | */ |
| 507 | void luaD_callnoyield (lua_State *L, StkId func, int nResults) { | 522 | void luaD_callnoyield (lua_State *L, StkId func, int nResults) { |
| 508 | L->nny++; | 523 | incXCcalls(L); |
| 524 | if (getCcalls(L) <= CSTACKERR) /* possible stack overflow? */ | ||
| 525 | luaE_freeCI(L); | ||
| 509 | luaD_call(L, func, nResults); | 526 | luaD_call(L, func, nResults); |
| 510 | L->nny--; | 527 | decXCcalls(L); |
| 511 | } | 528 | } |
| 512 | 529 | ||
| 513 | 530 | ||
| @@ -519,7 +536,7 @@ static void finishCcall (lua_State *L, int status) { | |||
| 519 | CallInfo *ci = L->ci; | 536 | CallInfo *ci = L->ci; |
| 520 | int n; | 537 | int n; |
| 521 | /* must have a continuation and must be able to call it */ | 538 | /* must have a continuation and must be able to call it */ |
| 522 | lua_assert(ci->u.c.k != NULL && L->nny == 0); | 539 | lua_assert(ci->u.c.k != NULL && yieldable(L)); |
| 523 | /* error status can only happen in a protected call */ | 540 | /* error status can only happen in a protected call */ |
| 524 | lua_assert((ci->callstatus & CIST_YPCALL) || status == LUA_YIELD); | 541 | lua_assert((ci->callstatus & CIST_YPCALL) || status == LUA_YIELD); |
| 525 | if (ci->callstatus & CIST_YPCALL) { /* was inside a pcall? */ | 542 | if (ci->callstatus & CIST_YPCALL) { /* was inside a pcall? */ |
| @@ -533,7 +550,7 @@ static void finishCcall (lua_State *L, int status) { | |||
| 533 | n = (*ci->u.c.k)(L, status, ci->u.c.ctx); /* call continuation function */ | 550 | n = (*ci->u.c.k)(L, status, ci->u.c.ctx); /* call continuation function */ |
| 534 | lua_lock(L); | 551 | lua_lock(L); |
| 535 | api_checknelems(L, n); | 552 | api_checknelems(L, n); |
| 536 | luaD_poscall(L, ci, L->top - n, n); /* finish 'luaD_precall' */ | 553 | luaD_poscall(L, ci, n); /* finish 'luaD_call' */ |
| 537 | } | 554 | } |
| 538 | 555 | ||
| 539 | 556 | ||
| @@ -546,14 +563,15 @@ static void finishCcall (lua_State *L, int status) { | |||
| 546 | ** status is LUA_YIELD). | 563 | ** status is LUA_YIELD). |
| 547 | */ | 564 | */ |
| 548 | static void unroll (lua_State *L, void *ud) { | 565 | static void unroll (lua_State *L, void *ud) { |
| 566 | CallInfo *ci; | ||
| 549 | if (ud != NULL) /* error status? */ | 567 | if (ud != NULL) /* error status? */ |
| 550 | finishCcall(L, *(int *)ud); /* finish 'lua_pcallk' callee */ | 568 | finishCcall(L, *(int *)ud); /* finish 'lua_pcallk' callee */ |
| 551 | while (L->ci != &L->base_ci) { /* something in the stack */ | 569 | while ((ci = L->ci) != &L->base_ci) { /* something in the stack */ |
| 552 | if (!isLua(L->ci)) /* C function? */ | 570 | if (!isLua(ci)) /* C function? */ |
| 553 | finishCcall(L, LUA_YIELD); /* complete its execution */ | 571 | finishCcall(L, LUA_YIELD); /* complete its execution */ |
| 554 | else { /* Lua function */ | 572 | else { /* Lua function */ |
| 555 | luaV_finishOp(L); /* finish interrupted instruction */ | 573 | luaV_finishOp(L); /* finish interrupted instruction */ |
| 556 | luaV_execute(L); /* execute down to higher C 'boundary' */ | 574 | luaV_execute(L, ci); /* execute down to higher C 'boundary' */ |
| 557 | } | 575 | } |
| 558 | } | 576 | } |
| 559 | } | 577 | } |
| @@ -583,12 +601,12 @@ static int recover (lua_State *L, int status) { | |||
| 583 | CallInfo *ci = findpcall(L); | 601 | CallInfo *ci = findpcall(L); |
| 584 | if (ci == NULL) return 0; /* no recovery point */ | 602 | if (ci == NULL) return 0; /* no recovery point */ |
| 585 | /* "finish" luaD_pcall */ | 603 | /* "finish" luaD_pcall */ |
| 586 | oldtop = restorestack(L, ci->extra); | 604 | oldtop = restorestack(L, ci->u2.funcidx); |
| 587 | luaF_close(L, oldtop); | 605 | luaF_close(L, oldtop, status); /* may change the stack */ |
| 588 | seterrorobj(L, status, oldtop); | 606 | oldtop = restorestack(L, ci->u2.funcidx); |
| 607 | luaD_seterrorobj(L, status, oldtop); | ||
| 589 | L->ci = ci; | 608 | L->ci = ci; |
| 590 | L->allowhook = getoah(ci->callstatus); /* restore original 'allowhook' */ | 609 | L->allowhook = getoah(ci->callstatus); /* restore original 'allowhook' */ |
| 591 | L->nny = 0; /* should be zero to be yieldable */ | ||
| 592 | luaD_shrinkstack(L); | 610 | luaD_shrinkstack(L); |
| 593 | L->errfunc = ci->u.c.old_errfunc; | 611 | L->errfunc = ci->u.c.old_errfunc; |
| 594 | return 1; /* continue running the coroutine */ | 612 | return 1; /* continue running the coroutine */ |
| @@ -621,71 +639,68 @@ static void resume (lua_State *L, void *ud) { | |||
| 621 | StkId firstArg = L->top - n; /* first argument */ | 639 | StkId firstArg = L->top - n; /* first argument */ |
| 622 | CallInfo *ci = L->ci; | 640 | CallInfo *ci = L->ci; |
| 623 | if (L->status == LUA_OK) { /* starting a coroutine? */ | 641 | if (L->status == LUA_OK) { /* starting a coroutine? */ |
| 624 | if (!luaD_precall(L, firstArg - 1, LUA_MULTRET)) /* Lua function? */ | 642 | luaD_call(L, firstArg - 1, LUA_MULTRET); |
| 625 | luaV_execute(L); /* call it */ | ||
| 626 | } | 643 | } |
| 627 | else { /* resuming from previous yield */ | 644 | else { /* resuming from previous yield */ |
| 628 | lua_assert(L->status == LUA_YIELD); | 645 | lua_assert(L->status == LUA_YIELD); |
| 629 | L->status = LUA_OK; /* mark that it is running (again) */ | 646 | L->status = LUA_OK; /* mark that it is running (again) */ |
| 630 | ci->func = restorestack(L, ci->extra); | ||
| 631 | if (isLua(ci)) /* yielded inside a hook? */ | 647 | if (isLua(ci)) /* yielded inside a hook? */ |
| 632 | luaV_execute(L); /* just continue running Lua code */ | 648 | luaV_execute(L, ci); /* just continue running Lua code */ |
| 633 | else { /* 'common' yield */ | 649 | else { /* 'common' yield */ |
| 634 | if (ci->u.c.k != NULL) { /* does it have a continuation function? */ | 650 | if (ci->u.c.k != NULL) { /* does it have a continuation function? */ |
| 635 | lua_unlock(L); | 651 | lua_unlock(L); |
| 636 | n = (*ci->u.c.k)(L, LUA_YIELD, ci->u.c.ctx); /* call continuation */ | 652 | n = (*ci->u.c.k)(L, LUA_YIELD, ci->u.c.ctx); /* call continuation */ |
| 637 | lua_lock(L); | 653 | lua_lock(L); |
| 638 | api_checknelems(L, n); | 654 | api_checknelems(L, n); |
| 639 | firstArg = L->top - n; /* yield results come from continuation */ | ||
| 640 | } | 655 | } |
| 641 | luaD_poscall(L, ci, firstArg, n); /* finish 'luaD_precall' */ | 656 | luaD_poscall(L, ci, n); /* finish 'luaD_call' */ |
| 642 | } | 657 | } |
| 643 | unroll(L, NULL); /* run continuation */ | 658 | unroll(L, NULL); /* run continuation */ |
| 644 | } | 659 | } |
| 645 | } | 660 | } |
| 646 | 661 | ||
| 647 | 662 | LUA_API int lua_resume (lua_State *L, lua_State *from, int nargs, | |
| 648 | LUA_API int lua_resume (lua_State *L, lua_State *from, int nargs) { | 663 | int *nresults) { |
| 649 | int status; | 664 | int status; |
| 650 | unsigned short oldnny = L->nny; /* save "number of non-yieldable" calls */ | ||
| 651 | lua_lock(L); | 665 | lua_lock(L); |
| 652 | if (L->status == LUA_OK) { /* may be starting a coroutine */ | 666 | if (L->status == LUA_OK) { /* may be starting a coroutine */ |
| 653 | if (L->ci != &L->base_ci) /* not in base level? */ | 667 | if (L->ci != &L->base_ci) /* not in base level? */ |
| 654 | return resume_error(L, "cannot resume non-suspended coroutine", nargs); | 668 | return resume_error(L, "cannot resume non-suspended coroutine", nargs); |
| 669 | else if (L->top - (L->ci->func + 1) == nargs) /* no function? */ | ||
| 670 | return resume_error(L, "cannot resume dead coroutine", nargs); | ||
| 655 | } | 671 | } |
| 656 | else if (L->status != LUA_YIELD) | 672 | else if (L->status != LUA_YIELD) /* ended with errors? */ |
| 657 | return resume_error(L, "cannot resume dead coroutine", nargs); | 673 | return resume_error(L, "cannot resume dead coroutine", nargs); |
| 658 | L->nCcalls = (from) ? from->nCcalls + 1 : 1; | 674 | if (from == NULL) |
| 659 | if (L->nCcalls >= LUAI_MAXCCALLS) | 675 | L->nCcalls = CSTACKTHREAD; |
| 676 | else /* correct 'nCcalls' for this thread */ | ||
| 677 | L->nCcalls = getCcalls(from) + from->nci - L->nci - CSTACKCF; | ||
| 678 | if (L->nCcalls <= CSTACKERR) | ||
| 660 | return resume_error(L, "C stack overflow", nargs); | 679 | return resume_error(L, "C stack overflow", nargs); |
| 661 | luai_userstateresume(L, nargs); | 680 | luai_userstateresume(L, nargs); |
| 662 | L->nny = 0; /* allow yields */ | ||
| 663 | api_checknelems(L, (L->status == LUA_OK) ? nargs + 1 : nargs); | 681 | api_checknelems(L, (L->status == LUA_OK) ? nargs + 1 : nargs); |
| 664 | status = luaD_rawrunprotected(L, resume, &nargs); | 682 | status = luaD_rawrunprotected(L, resume, &nargs); |
| 665 | if (status == -1) /* error calling 'lua_resume'? */ | 683 | /* continue running after recoverable errors */ |
| 666 | status = LUA_ERRRUN; | 684 | while (errorstatus(status) && recover(L, status)) { |
| 667 | else { /* continue running after recoverable errors */ | 685 | /* unroll continuation */ |
| 668 | while (errorstatus(status) && recover(L, status)) { | 686 | status = luaD_rawrunprotected(L, unroll, &status); |
| 669 | /* unroll continuation */ | 687 | } |
| 670 | status = luaD_rawrunprotected(L, unroll, &status); | 688 | if (likely(!errorstatus(status))) |
| 671 | } | 689 | lua_assert(status == L->status); /* normal end or yield */ |
| 672 | if (errorstatus(status)) { /* unrecoverable error? */ | 690 | else { /* unrecoverable error */ |
| 673 | L->status = cast_byte(status); /* mark thread as 'dead' */ | 691 | L->status = cast_byte(status); /* mark thread as 'dead' */ |
| 674 | seterrorobj(L, status, L->top); /* push error message */ | 692 | luaD_seterrorobj(L, status, L->top); /* push error message */ |
| 675 | L->ci->top = L->top; | 693 | L->ci->top = L->top; |
| 676 | } | ||
| 677 | else lua_assert(status == L->status); /* normal end or yield */ | ||
| 678 | } | 694 | } |
| 679 | L->nny = oldnny; /* restore 'nny' */ | 695 | *nresults = (status == LUA_YIELD) ? L->ci->u2.nyield |
| 680 | L->nCcalls--; | 696 | : cast_int(L->top - (L->ci->func + 1)); |
| 681 | lua_assert(L->nCcalls == ((from) ? from->nCcalls : 0)); | ||
| 682 | lua_unlock(L); | 697 | lua_unlock(L); |
| 683 | return status; | 698 | return status; |
| 684 | } | 699 | } |
| 685 | 700 | ||
| 686 | 701 | ||
| 687 | LUA_API int lua_isyieldable (lua_State *L) { | 702 | LUA_API int lua_isyieldable (lua_State *L) { |
| 688 | return (L->nny == 0); | 703 | return yieldable(L); |
| 689 | } | 704 | } |
| 690 | 705 | ||
| 691 | 706 | ||
| @@ -695,21 +710,22 @@ LUA_API int lua_yieldk (lua_State *L, int nresults, lua_KContext ctx, | |||
| 695 | luai_userstateyield(L, nresults); | 710 | luai_userstateyield(L, nresults); |
| 696 | lua_lock(L); | 711 | lua_lock(L); |
| 697 | api_checknelems(L, nresults); | 712 | api_checknelems(L, nresults); |
| 698 | if (L->nny > 0) { | 713 | if (unlikely(!yieldable(L))) { |
| 699 | if (L != G(L)->mainthread) | 714 | if (L != G(L)->mainthread) |
| 700 | luaG_runerror(L, "attempt to yield across a C-call boundary"); | 715 | luaG_runerror(L, "attempt to yield across a C-call boundary"); |
| 701 | else | 716 | else |
| 702 | luaG_runerror(L, "attempt to yield from outside a coroutine"); | 717 | luaG_runerror(L, "attempt to yield from outside a coroutine"); |
| 703 | } | 718 | } |
| 704 | L->status = LUA_YIELD; | 719 | L->status = LUA_YIELD; |
| 705 | ci->extra = savestack(L, ci->func); /* save current 'func' */ | ||
| 706 | if (isLua(ci)) { /* inside a hook? */ | 720 | if (isLua(ci)) { /* inside a hook? */ |
| 721 | lua_assert(!isLuacode(ci)); | ||
| 707 | api_check(L, k == NULL, "hooks cannot continue after yielding"); | 722 | api_check(L, k == NULL, "hooks cannot continue after yielding"); |
| 723 | ci->u2.nyield = 0; /* no results */ | ||
| 708 | } | 724 | } |
| 709 | else { | 725 | else { |
| 710 | if ((ci->u.c.k = k) != NULL) /* is there a continuation? */ | 726 | if ((ci->u.c.k = k) != NULL) /* is there a continuation? */ |
| 711 | ci->u.c.ctx = ctx; /* save context */ | 727 | ci->u.c.ctx = ctx; /* save context */ |
| 712 | ci->func = L->top - nresults - 1; /* protect stack below results */ | 728 | ci->u2.nyield = nresults; /* save number of results */ |
| 713 | luaD_throw(L, LUA_YIELD); | 729 | luaD_throw(L, LUA_YIELD); |
| 714 | } | 730 | } |
| 715 | lua_assert(ci->callstatus & CIST_HOOKED); /* must be inside a hook */ | 731 | lua_assert(ci->callstatus & CIST_HOOKED); /* must be inside a hook */ |
| @@ -718,22 +734,26 @@ LUA_API int lua_yieldk (lua_State *L, int nresults, lua_KContext ctx, | |||
| 718 | } | 734 | } |
| 719 | 735 | ||
| 720 | 736 | ||
| 737 | /* | ||
| 738 | ** Call the C function 'func' in protected mode, restoring basic | ||
| 739 | ** thread information ('allowhook', etc.) and in particular | ||
| 740 | ** its stack level in case of errors. | ||
| 741 | */ | ||
| 721 | int luaD_pcall (lua_State *L, Pfunc func, void *u, | 742 | int luaD_pcall (lua_State *L, Pfunc func, void *u, |
| 722 | ptrdiff_t old_top, ptrdiff_t ef) { | 743 | ptrdiff_t old_top, ptrdiff_t ef) { |
| 723 | int status; | 744 | int status; |
| 724 | CallInfo *old_ci = L->ci; | 745 | CallInfo *old_ci = L->ci; |
| 725 | lu_byte old_allowhooks = L->allowhook; | 746 | lu_byte old_allowhooks = L->allowhook; |
| 726 | unsigned short old_nny = L->nny; | ||
| 727 | ptrdiff_t old_errfunc = L->errfunc; | 747 | ptrdiff_t old_errfunc = L->errfunc; |
| 728 | L->errfunc = ef; | 748 | L->errfunc = ef; |
| 729 | status = luaD_rawrunprotected(L, func, u); | 749 | status = luaD_rawrunprotected(L, func, u); |
| 730 | if (status != LUA_OK) { /* an error occurred? */ | 750 | if (unlikely(status != LUA_OK)) { /* an error occurred? */ |
| 731 | StkId oldtop = restorestack(L, old_top); | 751 | StkId oldtop = restorestack(L, old_top); |
| 732 | luaF_close(L, oldtop); /* close possible pending closures */ | ||
| 733 | seterrorobj(L, status, oldtop); | ||
| 734 | L->ci = old_ci; | 752 | L->ci = old_ci; |
| 735 | L->allowhook = old_allowhooks; | 753 | L->allowhook = old_allowhooks; |
| 736 | L->nny = old_nny; | 754 | status = luaF_close(L, oldtop, status); |
| 755 | oldtop = restorestack(L, old_top); /* previous call may change stack */ | ||
| 756 | luaD_seterrorobj(L, status, oldtop); | ||
| 737 | luaD_shrinkstack(L); | 757 | luaD_shrinkstack(L); |
| 738 | } | 758 | } |
| 739 | L->errfunc = old_errfunc; | 759 | L->errfunc = old_errfunc; |
| @@ -784,7 +804,7 @@ int luaD_protectedparser (lua_State *L, ZIO *z, const char *name, | |||
| 784 | const char *mode) { | 804 | const char *mode) { |
| 785 | struct SParser p; | 805 | struct SParser p; |
| 786 | int status; | 806 | int status; |
| 787 | L->nny++; /* cannot yield during parsing */ | 807 | incnny(L); /* cannot yield during parsing */ |
| 788 | p.z = z; p.name = name; p.mode = mode; | 808 | p.z = z; p.name = name; p.mode = mode; |
| 789 | p.dyd.actvar.arr = NULL; p.dyd.actvar.size = 0; | 809 | p.dyd.actvar.arr = NULL; p.dyd.actvar.size = 0; |
| 790 | p.dyd.gt.arr = NULL; p.dyd.gt.size = 0; | 810 | p.dyd.gt.arr = NULL; p.dyd.gt.size = 0; |
| @@ -795,7 +815,7 @@ int luaD_protectedparser (lua_State *L, ZIO *z, const char *name, | |||
| 795 | luaM_freearray(L, p.dyd.actvar.arr, p.dyd.actvar.size); | 815 | luaM_freearray(L, p.dyd.actvar.arr, p.dyd.actvar.size); |
| 796 | luaM_freearray(L, p.dyd.gt.arr, p.dyd.gt.size); | 816 | luaM_freearray(L, p.dyd.gt.arr, p.dyd.gt.size); |
| 797 | luaM_freearray(L, p.dyd.label.arr, p.dyd.label.size); | 817 | luaM_freearray(L, p.dyd.label.arr, p.dyd.label.size); |
| 798 | L->nny--; | 818 | decnny(L); |
| 799 | return status; | 819 | return status; |
| 800 | } | 820 | } |
| 801 | 821 | ||
