aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2008-08-13 14:02:42 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2008-08-13 14:02:42 -0300
commitfdbb243ff9980870c54676f3b2597b110ab82864 (patch)
tree37c1d31df7addd0638c8b26b28e6f4a0b6024a88
parentc1565c16edc487f32d87d1742a7c8e76d0b10236 (diff)
downloadlua-fdbb243ff9980870c54676f3b2597b110ab82864.tar.gz
lua-fdbb243ff9980870c54676f3b2597b110ab82864.tar.bz2
lua-fdbb243ff9980870c54676f3b2597b110ab82864.zip
first steps towards yielding through longjump
-rw-r--r--ldo.c33
-rw-r--r--ldo.h8
-rw-r--r--lvm.c71
3 files changed, 50 insertions, 62 deletions
diff --git a/ldo.c b/ldo.c
index c156a40e..c984dd09 100644
--- a/ldo.c
+++ b/ldo.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: ldo.c,v 2.45 2007/03/27 14:11:38 roberto Exp roberto $ 2** $Id: ldo.c,v 2.46 2008/01/18 22:36:50 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*/
@@ -193,6 +193,7 @@ void luaD_callhook (lua_State *L, int event, int line) {
193 ar.i_ci = cast_int(L->ci - L->base_ci); 193 ar.i_ci = cast_int(L->ci - L->base_ci);
194 luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */ 194 luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */
195 L->ci->top = L->top + LUA_MINSTACK; 195 L->ci->top = L->top + LUA_MINSTACK;
196 L->ci->status |= 1; /* this level is running a hook */
196 lua_assert(L->ci->top <= L->stack_last); 197 lua_assert(L->ci->top <= L->stack_last);
197 L->allowhook = 0; /* cannot call hooks inside a hook */ 198 L->allowhook = 0; /* cannot call hooks inside a hook */
198 lua_unlock(L); 199 lua_unlock(L);
@@ -202,6 +203,7 @@ void luaD_callhook (lua_State *L, int event, int line) {
202 L->allowhook = 1; 203 L->allowhook = 1;
203 L->ci->top = restorestack(L, ci_top); 204 L->ci->top = restorestack(L, ci_top);
204 L->top = restorestack(L, top); 205 L->top = restorestack(L, top);
206 L->ci->status &= ~1; /* this level is not running a hook anymore */
205 } 207 }
206} 208}
207 209
@@ -264,6 +266,9 @@ static StkId tryfuncTM (lua_State *L, StkId func) {
264 (condhardstacktests(luaD_reallocCI(L, L->size_ci)), ++L->ci)) 266 (condhardstacktests(luaD_reallocCI(L, L->size_ci)), ++L->ci))
265 267
266 268
269/*
270** returns true if function has been executed (C function)
271*/
267int luaD_precall (lua_State *L, StkId func, int nresults) { 272int luaD_precall (lua_State *L, StkId func, int nresults) {
268 LClosure *cl; 273 LClosure *cl;
269 ptrdiff_t funcr; 274 ptrdiff_t funcr;
@@ -292,6 +297,7 @@ int luaD_precall (lua_State *L, StkId func, int nresults) {
292 lua_assert(ci->top <= L->stack_last); 297 lua_assert(ci->top <= L->stack_last);
293 L->savedpc = p->code; /* starting point */ 298 L->savedpc = p->code; /* starting point */
294 ci->tailcalls = 0; 299 ci->tailcalls = 0;
300 ci->status = 0;
295 ci->nresults = nresults; 301 ci->nresults = nresults;
296 for (st = L->top; st < ci->top; st++) 302 for (st = L->top; st < ci->top; st++)
297 setnilvalue(st); 303 setnilvalue(st);
@@ -301,7 +307,7 @@ int luaD_precall (lua_State *L, StkId func, int nresults) {
301 luaD_callhook(L, LUA_HOOKCALL, -1); 307 luaD_callhook(L, LUA_HOOKCALL, -1);
302 L->savedpc--; /* correct 'pc' */ 308 L->savedpc--; /* correct 'pc' */
303 } 309 }
304 return PCRLUA; 310 return 0;
305 } 311 }
306 else { /* if is a C function, call it */ 312 else { /* if is a C function, call it */
307 CallInfo *ci; 313 CallInfo *ci;
@@ -318,12 +324,8 @@ int luaD_precall (lua_State *L, StkId func, int nresults) {
318 lua_unlock(L); 324 lua_unlock(L);
319 n = (*curr_func(L)->c.f)(L); /* do the actual call */ 325 n = (*curr_func(L)->c.f)(L); /* do the actual call */
320 lua_lock(L); 326 lua_lock(L);
321 if (n < 0) /* yielding? */ 327 luaD_poscall(L, L->top - n);
322 return PCRYIELD; 328 return 1;
323 else {
324 luaD_poscall(L, L->top - n);
325 return PCRC;
326 }
327 } 329 }
328} 330}
329 331
@@ -378,7 +380,7 @@ void luaD_call (lua_State *L, StkId func, int nResults) {
378 else if (g->nCcalls >= (LUAI_MAXCCALLS + (LUAI_MAXCCALLS>>3))) 380 else if (g->nCcalls >= (LUAI_MAXCCALLS + (LUAI_MAXCCALLS>>3)))
379 luaD_throw(L, LUA_ERRERR); /* error while handing stack error */ 381 luaD_throw(L, LUA_ERRERR); /* error while handing stack error */
380 } 382 }
381 if (luaD_precall(L, func, nResults) == PCRLUA) /* is a Lua function? */ 383 if (!luaD_precall(L, func, nResults)) /* is a Lua function? */
382 luaV_execute(L, 1); /* call it */ 384 luaV_execute(L, 1); /* call it */
383 g->nCcalls--; 385 g->nCcalls--;
384 luaC_checkGC(L); 386 luaC_checkGC(L);
@@ -390,8 +392,8 @@ static void resume (lua_State *L, void *ud) {
390 CallInfo *ci = L->ci; 392 CallInfo *ci = L->ci;
391 if (L->status == LUA_OK) { /* start coroutine? */ 393 if (L->status == LUA_OK) { /* start coroutine? */
392 lua_assert(ci == L->base_ci && firstArg > L->base); 394 lua_assert(ci == L->base_ci && firstArg > L->base);
393 if (luaD_precall(L, firstArg - 1, LUA_MULTRET) != PCRLUA) 395 if (luaD_precall(L, firstArg - 1, LUA_MULTRET)) /* C function? */
394 return; 396 return; /* done */
395 } 397 }
396 else { /* resuming from previous yield */ 398 else { /* resuming from previous yield */
397 lua_assert(L->status == LUA_YIELD); 399 lua_assert(L->status == LUA_YIELD);
@@ -434,14 +436,14 @@ LUA_API int lua_resume (lua_State *L, int nargs) {
434 return resume_error(L, "C stack overflow"); 436 return resume_error(L, "C stack overflow");
435 L->baseCcalls = ++G(L)->nCcalls; 437 L->baseCcalls = ++G(L)->nCcalls;
436 status = luaD_rawrunprotected(L, resume, L->top - nargs); 438 status = luaD_rawrunprotected(L, resume, L->top - nargs);
437 if (status != LUA_OK) { /* error? */ 439 if (status != LUA_OK && status != LUA_YIELD) { /* error? */
438 L->status = cast_byte(status); /* mark thread as `dead' */ 440 L->status = cast_byte(status); /* mark thread as `dead' */
439 luaD_seterrorobj(L, status, L->top); 441 luaD_seterrorobj(L, status, L->top);
440 L->ci->top = L->top; 442 L->ci->top = L->top;
441 } 443 }
442 else { 444 else {
443 lua_assert(L->baseCcalls == G(L)->nCcalls); 445 lua_assert(L->baseCcalls == G(L)->nCcalls);
444 status = L->status; 446 lua_assert(status == L->status);
445 } 447 }
446 --G(L)->nCcalls; 448 --G(L)->nCcalls;
447 L->baseCcalls = 0; 449 L->baseCcalls = 0;
@@ -457,8 +459,11 @@ LUA_API int lua_yield (lua_State *L, int nresults) {
457 luaG_runerror(L, "attempt to yield across metamethod/C-call boundary"); 459 luaG_runerror(L, "attempt to yield across metamethod/C-call boundary");
458 L->base = L->top - nresults; /* protect stack slots below */ 460 L->base = L->top - nresults; /* protect stack slots below */
459 L->status = LUA_YIELD; 461 L->status = LUA_YIELD;
462 if (!isLua(L->ci)) /* not inside a hook? */
463 luaD_throw(L, LUA_YIELD);
464 lua_assert(L->ci->status & 1); /* must be inside a hook */
460 lua_unlock(L); 465 lua_unlock(L);
461 return -1; 466 return 0; /* otherwise, return to 'luaD_callhook' */
462} 467}
463 468
464 469
diff --git a/ldo.h b/ldo.h
index c8d0f872..ad86a09c 100644
--- a/ldo.h
+++ b/ldo.h
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: ldo.h,v 2.8 2006/07/11 15:53:29 roberto Exp roberto $ 2** $Id: ldo.h,v 2.9 2008/07/03 14:24:36 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*/
@@ -28,12 +28,6 @@
28#define restoreci(L,n) ((CallInfo *)((char *)L->base_ci + (n))) 28#define restoreci(L,n) ((CallInfo *)((char *)L->base_ci + (n)))
29 29
30 30
31/* results from luaD_precall */
32#define PCRLUA 0 /* initiated a call to a Lua function */
33#define PCRC 1 /* did a call to a C function */
34#define PCRYIELD 2 /* C funtion yielded */
35
36
37/* type of protected functions, to be ran by `runprotected' */ 31/* type of protected functions, to be ran by `runprotected' */
38typedef void (*Pfunc) (lua_State *L, void *ud); 32typedef void (*Pfunc) (lua_State *L, void *ud);
39 33
diff --git a/lvm.c b/lvm.c
index b295d5eb..c499913a 100644
--- a/lvm.c
+++ b/lvm.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lvm.c,v 2.73 2007/09/10 17:59:32 roberto Exp roberto $ 2** $Id: lvm.c,v 2.74 2008/04/02 16:16:06 roberto Exp roberto $
3** Lua virtual machine 3** Lua virtual machine
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -415,7 +415,7 @@ void luaV_execute (lua_State *L, int nexeccalls) {
415 traceexec(L); 415 traceexec(L);
416 if (L->status == LUA_YIELD) { /* did hook yield? */ 416 if (L->status == LUA_YIELD) { /* did hook yield? */
417 L->savedpc--; /* undo increment */ 417 L->savedpc--; /* undo increment */
418 return; 418 luaD_throw(L, LUA_YIELD);
419 } 419 }
420 base = L->base; 420 base = L->base;
421 } 421 }
@@ -595,51 +595,40 @@ void luaV_execute (lua_State *L, int nexeccalls) {
595 int b = GETARG_B(i); 595 int b = GETARG_B(i);
596 int nresults = GETARG_C(i) - 1; 596 int nresults = GETARG_C(i) - 1;
597 if (b != 0) L->top = ra+b; /* else previous instruction set top */ 597 if (b != 0) L->top = ra+b; /* else previous instruction set top */
598 switch (luaD_precall(L, ra, nresults)) { 598 if (luaD_precall(L, ra, nresults)) { /* C function? */
599 case PCRLUA: { 599 if (nresults >= 0) L->top = L->ci->top; /* adjust results */
600 nexeccalls++; 600 base = L->base;
601 goto reentry; /* restart luaV_execute over new Lua function */ 601 continue;
602 } 602 }
603 case PCRC: { 603 else { /* Lua function */
604 /* it was a C function (`precall' called it); adjust results */ 604 nexeccalls++;
605 if (nresults >= 0) L->top = L->ci->top; 605 goto reentry; /* restart luaV_execute over new Lua function */
606 base = L->base;
607 continue;
608 }
609 default: {
610 return; /* yield */
611 }
612 } 606 }
613 } 607 }
614 case OP_TAILCALL: { 608 case OP_TAILCALL: {
615 int b = GETARG_B(i); 609 int b = GETARG_B(i);
616 if (b != 0) L->top = ra+b; /* else previous instruction set top */ 610 if (b != 0) L->top = ra+b; /* else previous instruction set top */
617 lua_assert(GETARG_C(i) - 1 == LUA_MULTRET); 611 lua_assert(GETARG_C(i) - 1 == LUA_MULTRET);
618 switch (luaD_precall(L, ra, LUA_MULTRET)) { 612 if (luaD_precall(L, ra, LUA_MULTRET)) { /* C function? */
619 case PCRLUA: { 613 base = L->base;
620 /* tail call: put new frame in place of previous one */ 614 continue;
621 CallInfo *ci = L->ci - 1; /* previous frame */ 615 }
622 int aux; 616 else {
623 StkId func = ci->func; 617 /* tail call: put new frame in place of previous one */
624 StkId pfunc = (ci+1)->func; /* previous function index */ 618 CallInfo *ci = L->ci - 1; /* previous frame */
625 if (L->openupval) luaF_close(L, ci->base); 619 int aux;
626 L->base = ci->base = ci->func + ((ci+1)->base - pfunc); 620 StkId func = ci->func;
627 for (aux = 0; pfunc+aux < L->top; aux++) /* move frame down */ 621 StkId pfunc = (ci+1)->func; /* previous function index */
628 setobjs2s(L, func+aux, pfunc+aux); 622 if (L->openupval) luaF_close(L, ci->base);
629 ci->top = L->top = func+aux; /* correct top */ 623 L->base = ci->base = ci->func + ((ci+1)->base - pfunc);
630 lua_assert(L->top == L->base + clvalue(func)->l.p->maxstacksize); 624 for (aux = 0; pfunc+aux < L->top; aux++) /* move frame down */
631 ci->savedpc = L->savedpc; 625 setobjs2s(L, func+aux, pfunc+aux);
632 ci->tailcalls++; /* one more call lost */ 626 ci->top = L->top = func+aux; /* correct top */
633 L->ci--; /* remove new frame */ 627 lua_assert(L->top == L->base + clvalue(func)->l.p->maxstacksize);
634 goto reentry; 628 ci->savedpc = L->savedpc;
635 } 629 ci->tailcalls++; /* one more call lost */
636 case PCRC: { /* it was a C function (`precall' called it) */ 630 L->ci--; /* remove new frame */
637 base = L->base; 631 goto reentry;
638 continue;
639 }
640 default: {
641 return; /* yield */
642 }
643 } 632 }
644 } 633 }
645 case OP_RETURN: { 634 case OP_RETURN: {