aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2002-03-22 13:54:31 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2002-03-22 13:54:31 -0300
commit00af2faae71e6388ee61ef18b2c5902a42e9bc27 (patch)
tree9aa58a3fb85e9ba665578bbb6c669ef3149ef56e
parente9ef7ed2d3015ff6083ae51995b153b88837b64d (diff)
downloadlua-00af2faae71e6388ee61ef18b2c5902a42e9bc27.tar.gz
lua-00af2faae71e6388ee61ef18b2c5902a42e9bc27.tar.bz2
lua-00af2faae71e6388ee61ef18b2c5902a42e9bc27.zip
first implementation of proper tail call
-rw-r--r--ldebug.c4
-rw-r--r--lvm.c42
2 files changed, 32 insertions, 14 deletions
diff --git a/ldebug.c b/ldebug.c
index 26b24df1..34b3eec5 100644
--- a/ldebug.c
+++ b/ldebug.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: ldebug.c,v 1.102 2002/03/11 12:45:00 roberto Exp roberto $ 2** $Id: ldebug.c,v 1.103 2002/03/19 12:45:25 roberto Exp roberto $
3** Debug Interface 3** Debug Interface
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -296,6 +296,7 @@ static int checkopenop (const Proto *pt, int pc) {
296 Instruction i = pt->code[pc+1]; 296 Instruction i = pt->code[pc+1];
297 switch (GET_OPCODE(i)) { 297 switch (GET_OPCODE(i)) {
298 case OP_CALL: 298 case OP_CALL:
299 case OP_TAILCALL:
299 case OP_RETURN: { 300 case OP_RETURN: {
300 check(GETARG_B(i) == 0); 301 check(GETARG_B(i) == 0);
301 return 1; 302 return 1;
@@ -405,6 +406,7 @@ static Instruction luaG_symbexec (const Proto *pt, int lastpc, int reg) {
405 if (reg >= a) last = pc; /* affect all registers above base */ 406 if (reg >= a) last = pc; /* affect all registers above base */
406 break; 407 break;
407 } 408 }
409 case OP_TAILCALL:
408 case OP_RETURN: { 410 case OP_RETURN: {
409 b--; /* b = num. returns */ 411 b--; /* b = num. returns */
410 if (b > 0) checkreg(pt, a+b-1); 412 if (b > 0) checkreg(pt, a+b-1);
diff --git a/lvm.c b/lvm.c
index 5bc7783a..84a70fd5 100644
--- a/lvm.c
+++ b/lvm.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lvm.c,v 1.220 2002/03/19 12:45:25 roberto Exp roberto $ 2** $Id: lvm.c,v 1.221 2002/03/20 12:52:32 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*/
@@ -314,7 +314,7 @@ static void powOp (lua_State *L, StkId ra, StkId rb, StkId rc) {
314} 314}
315 315
316 316
317#define dojump(pc, i) ((pc) += GETARG_sBc(i)) 317#define dojump(pc, i) ((pc) += (i))
318 318
319/* 319/*
320** Executes current Lua function. Parameters are between [base,top). 320** Executes current Lua function. Parameters are between [base,top).
@@ -327,13 +327,13 @@ StkId luaV_execute (lua_State *L) {
327 const Instruction *pc; 327 const Instruction *pc;
328 lua_Hook linehook; 328 lua_Hook linehook;
329 reinit: 329 reinit:
330 base = L->ci->base;
331 cl = &clvalue(base - 1)->l;
332 k = cl->p->k;
333 linehook = L->linehook; 330 linehook = L->linehook;
334 L->ci->pc = &pc; 331 L->ci->pc = &pc;
335 L->ci->pb = &base;
336 pc = L->ci->savedpc; 332 pc = L->ci->savedpc;
333 L->ci->pb = &base;
334 base = L->ci->base;
335 cl = &clvalue(base - 1)->l;
336 k = cl->p->k;
337 /* main loop of interpreter */ 337 /* main loop of interpreter */
338 for (;;) { 338 for (;;) {
339 const Instruction i = *pc++; 339 const Instruction i = *pc++;
@@ -343,7 +343,8 @@ StkId luaV_execute (lua_State *L) {
343 ra = RA(i); 343 ra = RA(i);
344 lua_assert(L->top <= L->stack + L->stacksize && L->top >= L->ci->base); 344 lua_assert(L->top <= L->stack + L->stacksize && L->top >= L->ci->base);
345 lua_assert(L->top == L->ci->top || GET_OPCODE(i) == OP_CALL || 345 lua_assert(L->top == L->ci->top || GET_OPCODE(i) == OP_CALL ||
346 GET_OPCODE(i) == OP_RETURN || GET_OPCODE(i) == OP_SETLISTO); 346 GET_OPCODE(i) == OP_TAILCALL || GET_OPCODE(i) == OP_RETURN ||
347 GET_OPCODE(i) == OP_SETLISTO);
347 switch (GET_OPCODE(i)) { 348 switch (GET_OPCODE(i)) {
348 case OP_MOVE: { 349 case OP_MOVE: {
349 setobj(ra, RB(i)); 350 setobj(ra, RB(i));
@@ -452,7 +453,8 @@ StkId luaV_execute (lua_State *L) {
452 break; 453 break;
453 } 454 }
454 case OP_JMP: { 455 case OP_JMP: {
455 dojump(pc, i); 456 linehook = L->linehook;
457 dojump(pc, GETARG_sBc(i));
456 break; 458 break;
457 } 459 }
458 case OP_TESTEQ: { /* skip next instruction if test fails */ 460 case OP_TESTEQ: { /* skip next instruction if test fails */
@@ -513,14 +515,26 @@ StkId luaV_execute (lua_State *L) {
513 } 515 }
514 break; 516 break;
515 } 517 }
518 case OP_TAILCALL: {
519 int b = GETARG_B(i);
520 if (L->openupval) luaF_close(L, base);
521 if (b != 0) L->top = ra+b; /* else previous instruction set top */
522 luaD_poscall(L, LUA_MULTRET, ra); /* move down function and args. */
523 ra = luaD_precall(L, base-1);
524 if (ra == NULL) goto reinit; /* it is a Lua function */
525 else if (ra > L->top) return NULL; /* yield??? */
526 else goto ret;
527 }
516 case OP_RETURN: { 528 case OP_RETURN: {
517 CallInfo *ci;
518 int b; 529 int b;
519 if (L->openupval) luaF_close(L, base); 530 if (L->openupval) luaF_close(L, base);
520 b = GETARG_B(i); 531 b = GETARG_B(i);
521 if (b != 0) L->top = ra+b-1; 532 if (b != 0) L->top = ra+b-1;
533 lua_assert(L->ci->pc == &pc);
534 }
535 ret: {
536 CallInfo *ci;
522 ci = L->ci - 1; 537 ci = L->ci - 1;
523 lua_assert((ci+1)->pc == &pc);
524 if (ci->pc != &pc) /* previous function was running `here'? */ 538 if (ci->pc != &pc) /* previous function was running `here'? */
525 return ra; /* no: return */ 539 return ra; /* no: return */
526 else { /* yes: continue its execution */ 540 else { /* yes: continue its execution */
@@ -542,7 +556,7 @@ StkId luaV_execute (lua_State *L) {
542 int j = GETARG_sBc(i); 556 int j = GETARG_sBc(i);
543 const TObject *plimit = ra+1; 557 const TObject *plimit = ra+1;
544 const TObject *pstep = ra+2; 558 const TObject *pstep = ra+2;
545 pc += j; /* jump back before tests (for error messages) */ 559 dojump(pc, j); /* jump back before tests (for error messages) */
546 if (ttype(ra) != LUA_TNUMBER) 560 if (ttype(ra) != LUA_TNUMBER)
547 luaD_error(L, "`for' initial value must be a number"); 561 luaD_error(L, "`for' initial value must be a number");
548 if (!tonumber(plimit, ra+1)) 562 if (!tonumber(plimit, ra+1))
@@ -552,10 +566,12 @@ StkId luaV_execute (lua_State *L) {
552 step = nvalue(pstep); 566 step = nvalue(pstep);
553 index = nvalue(ra) + step; /* increment index */ 567 index = nvalue(ra) + step; /* increment index */
554 limit = nvalue(plimit); 568 limit = nvalue(plimit);
555 if (step > 0 ? index <= limit : index >= limit) 569 if (step > 0 ? index <= limit : index >= limit) {
556 chgnvalue(ra, index); /* update index */ 570 chgnvalue(ra, index); /* update index */
571 linehook = L->linehook;
572 }
557 else 573 else
558 pc -= j; /* undo jump */ 574 dojump(pc, -j); /* undo jump */
559 break; 575 break;
560 } 576 }
561 case OP_TFORLOOP: { 577 case OP_TFORLOOP: {