aboutsummaryrefslogtreecommitdiff
path: root/lvm.c
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2002-02-05 20:39:12 -0200
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2002-02-05 20:39:12 -0200
commit38b0e6128da7796300e2e8621e87835e16539f5b (patch)
tree5b0a7ad2b0fb850d47f0566fd06b8cda013bbc8b /lvm.c
parentaddbe8c8b0587fd316f33fb013034e035f9217ed (diff)
downloadlua-38b0e6128da7796300e2e8621e87835e16539f5b.tar.gz
lua-38b0e6128da7796300e2e8621e87835e16539f5b.tar.bz2
lua-38b0e6128da7796300e2e8621e87835e16539f5b.zip
simpler implementation for `for' loops
Diffstat (limited to 'lvm.c')
-rw-r--r--lvm.c67
1 files changed, 32 insertions, 35 deletions
diff --git a/lvm.c b/lvm.c
index a3ced1bc..94165d97 100644
--- a/lvm.c
+++ b/lvm.c
@@ -26,6 +26,9 @@
26#include "lvm.h" 26#include "lvm.h"
27 27
28 28
29/* limit for table tag-method chains (to avoid loops) */
30#define MAXTAGLOOP 10000
31
29 32
30static void luaV_checkGC (lua_State *L, StkId top) { 33static void luaV_checkGC (lua_State *L, StkId top) {
31 if (G(L)->nblocks >= G(L)->GCthreshold) { 34 if (G(L)->nblocks >= G(L)->GCthreshold) {
@@ -65,6 +68,8 @@ static void traceexec (lua_State *L, lua_Hook linehook) {
65 int *lineinfo = ci_func(ci)->l.p->lineinfo; 68 int *lineinfo = ci_func(ci)->l.p->lineinfo;
66 int pc = cast(int, *ci->pc - ci_func(ci)->l.p->code) - 1; 69 int pc = cast(int, *ci->pc - ci_func(ci)->l.p->code) - 1;
67 int newline; 70 int newline;
71 if (testOpMode(GET_OPCODE(*(*ci->pc - 1)), OpModeNoTrace))
72 return;
68 if (ci->line == -1) return; /* no linehooks for this function */ 73 if (ci->line == -1) return; /* no linehooks for this function */
69 else if (ci->line == 0) { /* first linehook? */ 74 else if (ci->line == 0) { /* first linehook? */
70 if (pc == 0) { /* function is starting now? */ 75 if (pc == 0) { /* function is starting now? */
@@ -123,6 +128,7 @@ static void callTM (lua_State *L, const TObject *f,
123*/ 128*/
124void luaV_gettable (lua_State *L, StkId t, TObject *key, StkId res) { 129void luaV_gettable (lua_State *L, StkId t, TObject *key, StkId res) {
125 const TObject *tm; 130 const TObject *tm;
131 int loop = 0;
126 init: 132 init:
127 if (ttype(t) == LUA_TTABLE) { /* `t' is a table? */ 133 if (ttype(t) == LUA_TTABLE) { /* `t' is a table? */
128 Table *et = hvalue(t)->metatable; 134 Table *et = hvalue(t)->metatable;
@@ -145,6 +151,7 @@ void luaV_gettable (lua_State *L, StkId t, TObject *key, StkId res) {
145 if (ttype(tm) == LUA_TFUNCTION) 151 if (ttype(tm) == LUA_TFUNCTION)
146 callTMres(L, tm, t, key, res); 152 callTMres(L, tm, t, key, res);
147 else { 153 else {
154 if (++loop == MAXTAGLOOP) luaD_error(L, "loop in gettable");
148 t = (StkId)tm; /* ?? */ 155 t = (StkId)tm; /* ?? */
149 goto init; /* return luaV_gettable(L, tm, key, res); */ 156 goto init; /* return luaV_gettable(L, tm, key, res); */
150 } 157 }
@@ -156,6 +163,7 @@ void luaV_gettable (lua_State *L, StkId t, TObject *key, StkId res) {
156*/ 163*/
157void luaV_settable (lua_State *L, StkId t, TObject *key, StkId val) { 164void luaV_settable (lua_State *L, StkId t, TObject *key, StkId val) {
158 const TObject *tm; 165 const TObject *tm;
166 int loop = 0;
159 init: 167 init:
160 if (ttype(t) == LUA_TTABLE) { /* `t' is a table? */ 168 if (ttype(t) == LUA_TTABLE) { /* `t' is a table? */
161 Table *et = hvalue(t)->metatable; 169 Table *et = hvalue(t)->metatable;
@@ -173,6 +181,7 @@ void luaV_settable (lua_State *L, StkId t, TObject *key, StkId val) {
173 if (ttype(tm) == LUA_TFUNCTION) 181 if (ttype(tm) == LUA_TFUNCTION)
174 callTM(L, tm, t, key, val); 182 callTM(L, tm, t, key, val);
175 else { 183 else {
184 if (++loop == MAXTAGLOOP) luaD_error(L, "loop in settable");
176 t = (StkId)tm; /* ?? */ 185 t = (StkId)tm; /* ?? */
177 goto init; /* luaV_settable(L, tm, key, val); */ 186 goto init; /* luaV_settable(L, tm, key, val); */
178 } 187 }
@@ -301,8 +310,8 @@ static void powOp (lua_State *L, StkId ra, StkId rb, StkId rc) {
301#define Arith(op, optm) { \ 310#define Arith(op, optm) { \
302 const TObject *b = RB(i); const TObject *c = RKC(i); \ 311 const TObject *b = RB(i); const TObject *c = RKC(i); \
303 TObject tempb, tempc; \ 312 TObject tempb, tempc; \
304 if ((ttype(b) == LUA_TNUMBER || (b = luaV_tonumber(b, &tempb)) != NULL) && \ 313 if ((b = luaV_tonumber(b, &tempb)) != NULL && \
305 (ttype(c) == LUA_TNUMBER || (c = luaV_tonumber(c, &tempc)) != NULL)) { \ 314 (c = luaV_tonumber(c, &tempc)) != NULL) { \
306 setnvalue(ra, nvalue(b) op nvalue(c)); \ 315 setnvalue(ra, nvalue(b) op nvalue(c)); \
307 } else \ 316 } else \
308 call_arith(L, RB(i), RKC(i), ra, optm); \ 317 call_arith(L, RB(i), RKC(i), ra, optm); \
@@ -423,7 +432,7 @@ StkId luaV_execute (lua_State *L) {
423 } 432 }
424 case OP_UNM: { 433 case OP_UNM: {
425 const TObject *rb = RB(i); 434 const TObject *rb = RB(i);
426 if (ttype(rb) == LUA_TNUMBER || (rb=luaV_tonumber(rb, ra)) != NULL) { 435 if ((rb=luaV_tonumber(rb, ra)) != NULL) {
427 setnvalue(ra, -nvalue(rb)); 436 setnvalue(ra, -nvalue(rb));
428 } 437 }
429 else { 438 else {
@@ -441,7 +450,7 @@ StkId luaV_execute (lua_State *L) {
441 case OP_CONCAT: { 450 case OP_CONCAT: {
442 int b = GETARG_B(i); 451 int b = GETARG_B(i);
443 int c = GETARG_C(i); 452 int c = GETARG_C(i);
444 luaV_strconc(L, c-b+1, c); /* this call may change `base' (and `ra') */ 453 luaV_strconc(L, c-b+1, c); /* may change `base' (and `ra') */
445 setobj(base+GETARG_A(i), base+b); 454 setobj(base+GETARG_A(i), base+b);
446 luaV_checkGC(L, base+c+1); 455 luaV_checkGC(L, base+c+1);
447 break; 456 break;
@@ -532,53 +541,41 @@ StkId luaV_execute (lua_State *L) {
532 } 541 }
533 break; 542 break;
534 } 543 }
535 case OP_FORPREP: { 544 case OP_FORLOOP: {
536 if (luaV_tonumber(ra, ra) == NULL) 545 lua_Number step, index, limit;
546 int j = GETARG_sBc(i);
547 pc += j; /* jump back before tests (for error messages) */
548 if (ttype(ra) != LUA_TNUMBER)
537 luaD_error(L, "`for' initial value must be a number"); 549 luaD_error(L, "`for' initial value must be a number");
538 if (luaV_tonumber(ra+1, ra+1) == NULL) 550 if (luaV_tonumber(ra+1, ra+1) == NULL)
539 luaD_error(L, "`for' limit must be a number"); 551 luaD_error(L, "`for' limit must be a number");
540 if (luaV_tonumber(ra+2, ra+2) == NULL) 552 if (luaV_tonumber(ra+2, ra+2) == NULL)
541 luaD_error(L, "`for' step must be a number"); 553 luaD_error(L, "`for' step must be a number");
542 /* decrement index (to be incremented) */ 554 step = nvalue(ra+2);
543 chgnvalue(ra, nvalue(ra) - nvalue(ra+2)); 555 index = nvalue(ra) + step; /* increment index */
544 pc += -GETARG_sBc(i); /* `jump' to loop end (delta is negated here) */ 556 limit = nvalue(ra+1);
545 /* store in `ra+1' total number of repetitions */ 557 if (step > 0 ? index <= limit : index >= limit)
546 chgnvalue(ra+1, (nvalue(ra+1)-nvalue(ra))/nvalue(ra+2)); 558 chgnvalue(ra, index); /* update index */
547 /* go through */ 559 else
548 } 560 pc -= j; /* undo jump */
549 case OP_FORLOOP: {
550 runtime_check(L, ttype(ra+1) == LUA_TNUMBER &&
551 ttype(ra+2) == LUA_TNUMBER);
552 if (ttype(ra) != LUA_TNUMBER)
553 luaD_error(L, "`for' index must be a number");
554 chgnvalue(ra+1, nvalue(ra+1) - 1); /* decrement counter */
555 if (nvalue(ra+1) >= 0) {
556 chgnvalue(ra, nvalue(ra) + nvalue(ra+2)); /* increment index */
557 dojump(pc, i); /* repeat loop */
558 }
559 break; 561 break;
560 } 562 }
561 case OP_TFORPREP: {
562 if (ttype(ra) != LUA_TTABLE)
563 luaD_error(L, "`for' table must be a table");
564 setnvalue(ra+1, -1); /* initial index */
565 setnilvalue(ra+2);
566 setnilvalue(ra+3);
567 pc += -GETARG_sBc(i); /* `jump' to loop end (delta is negated here) */
568 /* go through */
569 }
570 case OP_TFORLOOP: { 563 case OP_TFORLOOP: {
571 Table *t; 564 Table *t;
572 int n; 565 int n;
573 runtime_check(L, ttype(ra) == LUA_TTABLE && 566 int j = GETARG_sBc(i);
574 ttype(ra+1) == LUA_TNUMBER); 567 pc += j; /* jump back before tests (for error messages) */
568 if (ttype(ra) != LUA_TTABLE)
569 luaD_error(L, "`for' table must be a table");
570 runtime_check(L, ttype(ra+1) == LUA_TNUMBER);
575 t = hvalue(ra); 571 t = hvalue(ra);
576 n = cast(int, nvalue(ra+1)); 572 n = cast(int, nvalue(ra+1));
577 n = luaH_nexti(t, n, ra+2); 573 n = luaH_nexti(t, n, ra+2);
578 if (n != -1) { /* repeat loop? */ 574 if (n != -1) { /* repeat loop? */
579 setnvalue(ra+1, n); /* index */ 575 setnvalue(ra+1, n); /* index */
580 dojump(pc, i); /* repeat loop */
581 } 576 }
577 else
578 pc -= j; /* undo jump */
582 break; 579 break;
583 } 580 }
584 case OP_SETLIST: 581 case OP_SETLIST: