diff options
| -rw-r--r-- | ldo.c | 64 |
1 files changed, 38 insertions, 26 deletions
| @@ -36,7 +36,6 @@ struct lua_longjmp { | |||
| 36 | struct lua_longjmp *previous; | 36 | struct lua_longjmp *previous; |
| 37 | CallInfo *ci; /* index of call info of active function that set protection */ | 37 | CallInfo *ci; /* index of call info of active function that set protection */ |
| 38 | StkId top; /* top stack when protection was set */ | 38 | StkId top; /* top stack when protection was set */ |
| 39 | TObject *stack; /* active stack for this entry */ | ||
| 40 | int allowhooks; /* `allowhook' state when protection was set */ | 39 | int allowhooks; /* `allowhook' state when protection was set */ |
| 41 | volatile int status; /* error code */ | 40 | volatile int status; /* error code */ |
| 42 | }; | 41 | }; |
| @@ -47,10 +46,8 @@ static void correctstack (lua_State *L, TObject *oldstack) { | |||
| 47 | CallInfo *ci; | 46 | CallInfo *ci; |
| 48 | UpVal *up; | 47 | UpVal *up; |
| 49 | L->top = (L->top - oldstack) + L->stack; | 48 | L->top = (L->top - oldstack) + L->stack; |
| 50 | for (lj = L->errorJmp; lj && lj->stack == oldstack; lj = lj->previous) { | 49 | for (lj = L->errorJmp; lj != NULL; lj = lj->previous) |
| 51 | lj->top = (lj->top - oldstack) + L->stack; | 50 | lj->top = (lj->top - oldstack) + L->stack; |
| 52 | lj->stack = L->stack; | ||
| 53 | } | ||
| 54 | for (up = L->openupval; up != NULL; up = up->next) | 51 | for (up = L->openupval; up != NULL; up = up->next) |
| 55 | up->v = (up->v - oldstack) + L->stack; | 52 | up->v = (up->v - oldstack) + L->stack; |
| 56 | for (ci = L->base_ci; ci <= L->ci; ci++) { | 53 | for (ci = L->base_ci; ci <= L->ci; ci++) { |
| @@ -147,7 +144,7 @@ static void luaD_callHook (lua_State *L, lua_Hook callhook, const char *event) { | |||
| 147 | 144 | ||
| 148 | static void correctCI (lua_State *L, CallInfo *oldci) { | 145 | static void correctCI (lua_State *L, CallInfo *oldci) { |
| 149 | struct lua_longjmp *lj; | 146 | struct lua_longjmp *lj; |
| 150 | for (lj = L->errorJmp; lj && lj->stack == L->stack; lj = lj->previous) { | 147 | for (lj = L->errorJmp; lj != NULL; lj = lj->previous) { |
| 151 | lj->ci = (lj->ci - oldci) + L->base_ci; | 148 | lj->ci = (lj->ci - oldci) + L->base_ci; |
| 152 | } | 149 | } |
| 153 | } | 150 | } |
| @@ -287,35 +284,51 @@ LUA_API void lua_cobegin (lua_State *L, int nargs) { | |||
| 287 | } | 284 | } |
| 288 | 285 | ||
| 289 | 286 | ||
| 290 | static void resume_results (lua_State *L, lua_State *from, int numresults) { | 287 | static void move_results (lua_State *L, TObject *from, TObject *to) { |
| 291 | while (numresults) { | 288 | while (from < to) { |
| 292 | setobj(L->top, from->top - numresults); | 289 | setobj(L->top, from); |
| 293 | numresults--; | 290 | from++; |
| 294 | incr_top(L); | 291 | incr_top(L); |
| 295 | } | 292 | } |
| 296 | } | 293 | } |
| 297 | 294 | ||
| 298 | 295 | ||
| 299 | LUA_API void lua_resume (lua_State *L, lua_State *co) { | 296 | static void resume (lua_State *L, void *numres) { |
| 300 | StkId firstResult; | 297 | StkId firstResult; |
| 301 | lua_lock(L); | 298 | CallInfo *ci = L->ci; |
| 302 | if (co->ci == co->base_ci) /* no activation record? ?? */ | 299 | if (ci->savedpc != ci_func(ci)->l.p->code) { /* not first time? */ |
| 303 | luaD_error(L, "thread is dead - cannot be resumed"); | 300 | /* finish interupted execution of `OP_CALL' */ |
| 304 | lua_assert(co->errorJmp == NULL); | 301 | int nresults; |
| 305 | co->errorJmp = L->errorJmp; | 302 | lua_assert(GET_OPCODE(*((ci-1)->savedpc - 1)) == OP_CALL); |
| 306 | firstResult = luaV_execute(co); | 303 | nresults = GETARG_C(*((ci-1)->savedpc - 1)) - 1; |
| 307 | if (firstResult != NULL) { /* `return'? */ | 304 | luaD_poscall(L, nresults, L->top); /* complete it */ |
| 308 | resume_results(L, co, co->top - firstResult); | 305 | if (nresults >= 0) L->top = L->ci->top; |
| 309 | luaD_poscall(co, 0, firstResult); /* ends this coroutine */ | ||
| 310 | } | 306 | } |
| 311 | else { /* `yield' */ | 307 | firstResult = luaV_execute(L); |
| 312 | int nresults = GETARG_C(*((co->ci-1)->savedpc - 1)) - 1; | 308 | if (firstResult == NULL) /* yield? */ |
| 313 | resume_results(L, co, co->ci->yield_results); | 309 | *(int *)numres = L->ci->yield_results; |
| 314 | luaD_poscall(co, nresults, co->top); /* complete it */ | 310 | else { /* return */ |
| 315 | if (nresults >= 0) co->top = co->ci->top; | 311 | *(int *)numres = L->top - firstResult; |
| 312 | luaD_poscall(L, LUA_MULTRET, firstResult); /* finalize this coroutine */ | ||
| 316 | } | 313 | } |
| 317 | co->errorJmp = NULL; | 314 | } |
| 315 | |||
| 316 | |||
| 317 | LUA_API int lua_resume (lua_State *L, lua_State *co) { | ||
| 318 | CallInfo *ci; | ||
| 319 | int numres; | ||
| 320 | int status; | ||
| 321 | lua_lock(L); | ||
| 322 | ci = co->ci; | ||
| 323 | if (ci == co->base_ci) /* no activation record? ?? */ | ||
| 324 | luaD_error(L, "thread is dead - cannot be resumed"); | ||
| 325 | if (co->errorJmp != NULL) /* ?? */ | ||
| 326 | luaD_error(L, "thread is active - cannot be resumed"); | ||
| 327 | status = luaD_runprotected(co, resume, &numres); | ||
| 328 | if (status == 0) | ||
| 329 | move_results(L, co->top - numres, co->top); | ||
| 318 | lua_unlock(L); | 330 | lua_unlock(L); |
| 331 | return status; | ||
| 319 | } | 332 | } |
| 320 | 333 | ||
| 321 | 334 | ||
| @@ -486,7 +499,6 @@ int luaD_runprotected (lua_State *L, void (*f)(lua_State *, void *), void *ud) { | |||
| 486 | struct lua_longjmp lj; | 499 | struct lua_longjmp lj; |
| 487 | lj.ci = L->ci; | 500 | lj.ci = L->ci; |
| 488 | lj.top = L->top; | 501 | lj.top = L->top; |
| 489 | lj.stack = L->stack; | ||
| 490 | lj.allowhooks = L->allowhooks; | 502 | lj.allowhooks = L->allowhooks; |
| 491 | lj.status = 0; | 503 | lj.status = 0; |
| 492 | lj.previous = L->errorJmp; /* chain new error handler */ | 504 | lj.previous = L->errorJmp; /* chain new error handler */ |
