aboutsummaryrefslogtreecommitdiff
path: root/ldo.c
diff options
context:
space:
mode:
Diffstat (limited to 'ldo.c')
-rw-r--r--ldo.c64
1 files changed, 38 insertions, 26 deletions
diff --git a/ldo.c b/ldo.c
index 3c38fd25..6f850cbd 100644
--- a/ldo.c
+++ b/ldo.c
@@ -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
148static void correctCI (lua_State *L, CallInfo *oldci) { 145static 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
290static void resume_results (lua_State *L, lua_State *from, int numresults) { 287static 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
299LUA_API void lua_resume (lua_State *L, lua_State *co) { 296static 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
317LUA_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 */