summaryrefslogtreecommitdiff
path: root/lvm.c
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2004-05-14 16:25:09 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2004-05-14 16:25:09 -0300
commit0bda88e6cd960d3b1ad1d46826bfdef179098d2a (patch)
treed3b237faef502dba76747a5563be9ccc4c404754 /lvm.c
parent7966a4acaea50230e30acc8fd6997bce22307f24 (diff)
downloadlua-0bda88e6cd960d3b1ad1d46826bfdef179098d2a.tar.gz
lua-0bda88e6cd960d3b1ad1d46826bfdef179098d2a.tar.bz2
lua-0bda88e6cd960d3b1ad1d46826bfdef179098d2a.zip
small steps towards yields in iterators and tag methods
Diffstat (limited to 'lvm.c')
-rw-r--r--lvm.c127
1 files changed, 72 insertions, 55 deletions
diff --git a/lvm.c b/lvm.c
index a7a4b3b3..4c5a7ec7 100644
--- a/lvm.c
+++ b/lvm.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lvm.c,v 2.4 2004/04/30 20:13:38 roberto Exp roberto $ 2** $Id: lvm.c,v 2.5 2004/05/10 17:50:51 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*/
@@ -106,7 +106,8 @@ static void callTM (lua_State *L) {
106} 106}
107 107
108 108
109void luaV_gettable (lua_State *L, const TValue *t, TValue *key, StkId val) { 109StkId luaV_gettable (lua_State *L, const TValue *t, TValue *key, StkId val,
110 const Instruction *pc) {
110 int loop; 111 int loop;
111 for (loop = 0; loop < MAXTAGLOOP; loop++) { 112 for (loop = 0; loop < MAXTAGLOOP; loop++) {
112 const TValue *tm; 113 const TValue *tm;
@@ -116,24 +117,30 @@ void luaV_gettable (lua_State *L, const TValue *t, TValue *key, StkId val) {
116 if (!ttisnil(res) || /* result is no nil? */ 117 if (!ttisnil(res) || /* result is no nil? */
117 (tm = fasttm(L, h->metatable, TM_INDEX)) == NULL) { /* or no TM? */ 118 (tm = fasttm(L, h->metatable, TM_INDEX)) == NULL) { /* or no TM? */
118 setobj2s(L, val, res); 119 setobj2s(L, val, res);
119 return; 120 return L->base;
120 } 121 }
121 /* else will try the tag method */ 122 /* else will try the tag method */
122 } 123 }
123 else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_INDEX))) 124 else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_INDEX))) {
125 if (pc) L->ci->u.l.savedpc = pc;
124 luaG_typeerror(L, t, "index"); 126 luaG_typeerror(L, t, "index");
127 }
125 if (ttisfunction(tm)) { 128 if (ttisfunction(tm)) {
129 if (pc) L->ci->u.l.savedpc = pc;
126 prepTMcall(L, tm, t, key); 130 prepTMcall(L, tm, t, key);
127 callTMres(L, val); 131 callTMres(L, val);
128 return; 132 return L->base;
129 } 133 }
130 t = tm; /* else repeat with `tm' */ 134 t = tm; /* else repeat with `tm' */
131 } 135 }
136 if (pc) L->ci->u.l.savedpc = pc;
132 luaG_runerror(L, "loop in gettable"); 137 luaG_runerror(L, "loop in gettable");
138 return NULL; /* to avoid warnings */
133} 139}
134 140
135 141
136void luaV_settable (lua_State *L, const TValue *t, TValue *key, StkId val) { 142StkId luaV_settable (lua_State *L, const TValue *t, TValue *key, StkId val,
143 const Instruction *pc) {
137 int loop; 144 int loop;
138 for (loop = 0; loop < MAXTAGLOOP; loop++) { 145 for (loop = 0; loop < MAXTAGLOOP; loop++) {
139 const TValue *tm; 146 const TValue *tm;
@@ -144,21 +151,26 @@ void luaV_settable (lua_State *L, const TValue *t, TValue *key, StkId val) {
144 (tm = fasttm(L, h->metatable, TM_NEWINDEX)) == NULL) { /* or no TM? */ 151 (tm = fasttm(L, h->metatable, TM_NEWINDEX)) == NULL) { /* or no TM? */
145 setobj2t(L, oldval, val); 152 setobj2t(L, oldval, val);
146 luaC_barrier(L, h, val); 153 luaC_barrier(L, h, val);
147 return; 154 return L->base;
148 } 155 }
149 /* else will try the tag method */ 156 /* else will try the tag method */
150 } 157 }
151 else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_NEWINDEX))) 158 else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_NEWINDEX))) {
159 if (pc) L->ci->u.l.savedpc = pc;
152 luaG_typeerror(L, t, "index"); 160 luaG_typeerror(L, t, "index");
161 }
153 if (ttisfunction(tm)) { 162 if (ttisfunction(tm)) {
163 if (pc) L->ci->u.l.savedpc = pc;
154 prepTMcall(L, tm, t, key); 164 prepTMcall(L, tm, t, key);
155 setobj2s(L, L->top+3, val); /* 3th argument */ 165 setobj2s(L, L->top+3, val); /* 3th argument */
156 callTM(L); 166 callTM(L);
157 return; 167 return L->base;
158 } 168 }
159 t = tm; /* else repeat with `tm' */ 169 t = tm; /* else repeat with `tm' */
160 } 170 }
171 if (pc) L->ci->u.l.savedpc = pc;
161 luaG_runerror(L, "loop in settable"); 172 luaG_runerror(L, "loop in settable");
173 return NULL; /* to avoid warnings */
162} 174}
163 175
164 176
@@ -427,22 +439,16 @@ StkId luaV_execute (lua_State *L, int nexeccalls) {
427 case OP_GETGLOBAL: { 439 case OP_GETGLOBAL: {
428 TValue *rb = KBx(i); 440 TValue *rb = KBx(i);
429 lua_assert(ttisstring(rb) && ttistable(&cl->g)); 441 lua_assert(ttisstring(rb) && ttistable(&cl->g));
430 L->ci->u.l.savedpc = pc; 442 base = luaV_gettable(L, &cl->g, rb, ra, pc); /***/
431 luaV_gettable(L, &cl->g, rb, ra); /***/
432 base = L->base;
433 break; 443 break;
434 } 444 }
435 case OP_GETTABLE: { 445 case OP_GETTABLE: {
436 L->ci->u.l.savedpc = pc; 446 base = luaV_gettable(L, RB(i), RKC(i), ra, pc); /***/
437 luaV_gettable(L, RB(i), RKC(i), ra); /***/
438 base = L->base;
439 break; 447 break;
440 } 448 }
441 case OP_SETGLOBAL: { 449 case OP_SETGLOBAL: {
442 lua_assert(ttisstring(KBx(i)) && ttistable(&cl->g)); 450 lua_assert(ttisstring(KBx(i)) && ttistable(&cl->g));
443 L->ci->u.l.savedpc = pc; 451 base = luaV_settable(L, &cl->g, KBx(i), ra, pc); /***/
444 luaV_settable(L, &cl->g, KBx(i), ra); /***/
445 base = L->base;
446 break; 452 break;
447 } 453 }
448 case OP_SETUPVAL: { 454 case OP_SETUPVAL: {
@@ -452,9 +458,7 @@ StkId luaV_execute (lua_State *L, int nexeccalls) {
452 break; 458 break;
453 } 459 }
454 case OP_SETTABLE: { 460 case OP_SETTABLE: {
455 L->ci->u.l.savedpc = pc; 461 base = luaV_settable(L, ra, RKB(i), RKC(i), pc); /***/
456 luaV_settable(L, ra, RKB(i), RKC(i)); /***/
457 base = L->base;
458 break; 462 break;
459 } 463 }
460 case OP_NEWTABLE: { 464 case OP_NEWTABLE: {
@@ -469,9 +473,7 @@ StkId luaV_execute (lua_State *L, int nexeccalls) {
469 case OP_SELF: { 473 case OP_SELF: {
470 StkId rb = RB(i); 474 StkId rb = RB(i);
471 setobjs2s(L, ra+1, rb); 475 setobjs2s(L, ra+1, rb);
472 L->ci->u.l.savedpc = pc; 476 base = luaV_gettable(L, rb, RKC(i), ra, pc); /***/
473 luaV_gettable(L, rb, RKC(i), ra); /***/
474 base = L->base;
475 break; 477 break;
476 } 478 }
477 case OP_ADD: { 479 case OP_ADD: {
@@ -582,43 +584,59 @@ StkId luaV_execute (lua_State *L, int nexeccalls) {
582 } 584 }
583 break; 585 break;
584 } 586 }
585 case OP_CALL: 587 case OP_CALL: { /***/
586 case OP_TAILCALL: { /***/ 588 int pcr;
587 StkId firstResult;
588 int b = GETARG_B(i); 589 int b = GETARG_B(i);
590 int nresults = GETARG_C(i) - 1;
589 if (b != 0) L->top = ra+b; /* else previous instruction set top */ 591 if (b != 0) L->top = ra+b; /* else previous instruction set top */
590 L->ci->u.l.savedpc = pc; 592 L->ci->u.l.savedpc = pc;
591 firstResult = luaD_precall(L, ra); 593 pcr = luaD_precall(L, ra, nresults);
592 if (firstResult) { 594 if (pcr == PCRLUA) {
593 int nresults = GETARG_C(i) - 1; 595 nexeccalls++;
594 if (firstResult > L->top) { /* yield? */ 596 goto callentry; /* restart luaV_execute over new Lua function */
595 (L->ci - 1)->u.l.savedpc = pc; 597 }
596 return NULL; 598 else if (pcr == PCRC) {
597 }
598 /* it was a C function (`precall' called it); adjust results */ 599 /* it was a C function (`precall' called it); adjust results */
599 luaD_poscall(L, nresults, firstResult);
600 if (nresults >= 0) L->top = L->ci->top; 600 if (nresults >= 0) L->top = L->ci->top;
601 base = L->base;
602 break;
601 } 603 }
602 else { /* it is a Lua function */ 604 else {
603 if (GET_OPCODE(i) == OP_CALL) /* regular call? */ 605 lua_assert(pcr == PCRYIELD);
604 nexeccalls++; 606 return NULL;
605 else { /* tail call: put new frame in place of previous one */ 607 }
606 int aux; 608 }
607 base = (L->ci - 1)->base; /* `luaD_precall' may change the stack */ 609 case OP_TAILCALL: { /***/
608 ra = RA(i); 610 int pcr;
609 if (L->openupval) luaF_close(L, base); 611 int b = GETARG_B(i);
610 for (aux = 0; ra+aux < L->top; aux++) /* move frame down */ 612 if (b != 0) L->top = ra+b; /* else previous instruction set top */
611 setobjs2s(L, base+aux-1, ra+aux); 613 L->ci->u.l.savedpc = pc;
612 (L->ci - 1)->top = L->top = base+aux; /* correct top */ 614 lua_assert(GETARG_C(i) - 1 == LUA_MULTRET);
613 (L->ci - 1)->u.l.savedpc = L->ci->u.l.savedpc; 615 pcr = luaD_precall(L, ra, LUA_MULTRET);
614 (L->ci - 1)->u.l.tailcalls++; /* one more call lost */ 616 if (pcr == PCRLUA) {
615 L->ci--; /* remove new frame */ 617 /* tail call: put new frame in place of previous one */
616 L->base = L->ci->base; 618 int aux;
617 } 619 base = (L->ci - 1)->base; /* `luaD_precall' may change the stack */
620 ra = RA(i);
621 if (L->openupval) luaF_close(L, base);
622 for (aux = 0; ra+aux < L->top; aux++) /* move frame down */
623 setobjs2s(L, base+aux-1, ra+aux);
624 (L->ci - 1)->top = L->top = base+aux; /* correct top */
625 (L->ci - 1)->u.l.savedpc = L->ci->u.l.savedpc;
626 (L->ci - 1)->u.l.tailcalls++; /* one more call lost */
627 L->ci--; /* remove new frame */
628 L->base = L->ci->base;
618 goto callentry; 629 goto callentry;
619 } 630 }
620 base = L->base; 631 else if (pcr == PCRC) {
621 break; 632 /* it was a C function (`precall' called it) */
633 base = L->base;
634 break;
635 }
636 else {
637 lua_assert(pcr == PCRYIELD);
638 return NULL;
639 }
622 } 640 }
623 case OP_RETURN: { 641 case OP_RETURN: {
624 CallInfo *ci = L->ci - 1; /* previous function frame */ 642 CallInfo *ci = L->ci - 1; /* previous function frame */
@@ -629,10 +647,9 @@ StkId luaV_execute (lua_State *L, int nexeccalls) {
629 if (--nexeccalls == 0) /* was previous function running `here'? */ 647 if (--nexeccalls == 0) /* was previous function running `here'? */
630 return ra; /* no: return */ 648 return ra; /* no: return */
631 else { /* yes: continue its execution */ 649 else { /* yes: continue its execution */
632 int nresults; 650 int nresults = (ci+1)->nresults;
633 lua_assert(isLua(ci)); 651 lua_assert(isLua(ci));
634 lua_assert(GET_OPCODE(*(ci->u.l.savedpc - 1)) == OP_CALL); 652 lua_assert(GET_OPCODE(*(ci->u.l.savedpc - 1)) == OP_CALL);
635 nresults = GETARG_C(*(ci->u.l.savedpc - 1)) - 1;
636 luaD_poscall(L, nresults, ra); 653 luaD_poscall(L, nresults, ra);
637 if (nresults >= 0) L->top = L->ci->top; 654 if (nresults >= 0) L->top = L->ci->top;
638 goto retentry; 655 goto retentry;