aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2008-11-06 10:43:51 -0200
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2008-11-06 10:43:51 -0200
commitb47209849321b17e2037bfa46abf530e69bcc869 (patch)
tree1915a213b71e70c7cdbc405b260ccdef48bedf21
parent84b3daebbd09b334db0fa125700ffdb1d326c4f6 (diff)
downloadlua-b47209849321b17e2037bfa46abf530e69bcc869.tar.gz
lua-b47209849321b17e2037bfa46abf530e69bcc869.tar.bz2
lua-b47209849321b17e2037bfa46abf530e69bcc869.zip
concat TM can yield
-rw-r--r--ldo.c32
-rw-r--r--lvm.c4
2 files changed, 24 insertions, 12 deletions
diff --git a/ldo.c b/ldo.c
index 52c08ce7..f2f3f207 100644
--- a/ldo.c
+++ b/ldo.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: ldo.c,v 2.49 2008/10/28 16:53:16 roberto Exp roberto $ 2** $Id: ldo.c,v 2.50 2008/10/30 15:39:30 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*/
@@ -390,7 +390,7 @@ void luaD_call (lua_State *L, StkId func, int nResults) {
390static void unroll (lua_State *L) { 390static void unroll (lua_State *L) {
391 for (;;) { 391 for (;;) {
392 Instruction inst; 392 Instruction inst;
393 luaV_execute(L); /* execute up to higher C 'boundary' */ 393 luaV_execute(L); /* execute down to higher C 'boundary' */
394 if (L->ci == L->base_ci) { /* stack is empty? */ 394 if (L->ci == L->base_ci) { /* stack is empty? */
395 lua_assert(L->baseCcalls == G(L)->nCcalls); 395 lua_assert(L->baseCcalls == G(L)->nCcalls);
396 return; /* coroutine finished normally */ 396 return; /* coroutine finished normally */
@@ -405,27 +405,38 @@ static void unroll (lua_State *L) {
405 break; 405 break;
406 } 406 }
407 case OP_LE: case OP_LT: case OP_EQ: { 407 case OP_LE: case OP_LT: case OP_EQ: {
408 int res; 408 int res = !l_isfalse(L->top - 1);
409 L->top--; 409 L->top--;
410 res = !l_isfalse(L->top); 410 /* metamethod should not be called when operand is K */
411 /* cannot call metamethod with K operand */
412 lua_assert(!ISK(GETARG_B(inst))); 411 lua_assert(!ISK(GETARG_B(inst)));
413 if (GET_OPCODE(inst) == OP_LE && /* "<=" using "<" instead? */ 412 if (GET_OPCODE(inst) == OP_LE && /* "<=" using "<" instead? */
414 ttisnil(luaT_gettmbyobj(L, L->base + GETARG_B(inst), TM_LE))) 413 ttisnil(luaT_gettmbyobj(L, L->base + GETARG_B(inst), TM_LE)))
415 res = !res; /* invert result */ 414 res = !res; /* invert result */
416 lua_assert(GET_OPCODE(*L->savedpc) == OP_JMP); 415 lua_assert(GET_OPCODE(*L->savedpc) == OP_JMP);
417 if (res == GETARG_A(inst)) 416 if (res != GETARG_A(inst)) /* condition failed? */
418 L->savedpc += GETARG_sBx(*L->savedpc); /* jump */ 417 L->savedpc++; /* skip jump instruction */
419 L->savedpc++; /* skip jump instruction */
420 break; 418 break;
421 } 419 }
422 case OP_SETGLOBAL: case OP_SETTABLE: 420 case OP_CONCAT: {
423 break; /* nothing to be done */ 421 StkId top = L->top - 1; /* top when __concat was called */
422 int last = cast_int(top - L->base) - 2; /* last element and ... */
423 int b = GETARG_B(inst); /* ... first element to concatenate */
424 int total = last - b + 1; /* number of elements to concatenate */
425 setobj2s(L, top - 2, top); /* put TM result in proper position */
426 L->top = L->ci->top; /* correct top */
427 if (total > 1) /* are there elements to concat? */
428 luaV_concat(L, total, last); /* concat them (may yield again) */
429 /* move final result to final position */
430 setobj2s(L, L->base + GETARG_A(inst), L->base + b);
431 continue;
432 }
424 case OP_TFORCALL: { 433 case OP_TFORCALL: {
425 lua_assert(GET_OPCODE(*L->savedpc) == OP_TFORLOOP); 434 lua_assert(GET_OPCODE(*L->savedpc) == OP_TFORLOOP);
426 L->top = L->ci->top; /* correct top */ 435 L->top = L->ci->top; /* correct top */
427 break; 436 break;
428 } 437 }
438 case OP_SETGLOBAL: case OP_SETTABLE:
439 break; /* nothing to be done */
429 default: lua_assert(0); 440 default: lua_assert(0);
430 } 441 }
431 } 442 }
@@ -500,7 +511,6 @@ LUA_API int lua_resume (lua_State *L, int nargs) {
500LUA_API int lua_yield (lua_State *L, int nresults) { 511LUA_API int lua_yield (lua_State *L, int nresults) {
501 luai_userstateyield(L, nresults); 512 luai_userstateyield(L, nresults);
502 lua_lock(L); 513 lua_lock(L);
503/*printf("yield: %d - %d\n", G(L)->nCcalls, L->baseCcalls);*/
504 if (G(L)->nCcalls > L->baseCcalls) 514 if (G(L)->nCcalls > L->baseCcalls)
505 luaG_runerror(L, "attempt to yield across metamethod/C-call boundary"); 515 luaG_runerror(L, "attempt to yield across metamethod/C-call boundary");
506 L->base = L->top - nresults; /* protect stack slots below */ 516 L->base = L->top - nresults; /* protect stack slots below */
diff --git a/lvm.c b/lvm.c
index f7ad8f12..fb36ae18 100644
--- a/lvm.c
+++ b/lvm.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lvm.c,v 2.78 2008/10/28 16:53:16 roberto Exp roberto $ 2** $Id: lvm.c,v 2.79 2008/10/30 15:39:30 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*/
@@ -271,8 +271,10 @@ void luaV_concat (lua_State *L, int total, int last) {
271 StkId top = L->base + last + 1; 271 StkId top = L->base + last + 1;
272 int n = 2; /* number of elements handled in this pass (at least 2) */ 272 int n = 2; /* number of elements handled in this pass (at least 2) */
273 if (!(ttisstring(top-2) || ttisnumber(top-2)) || !tostring(L, top-1)) { 273 if (!(ttisstring(top-2) || ttisnumber(top-2)) || !tostring(L, top-1)) {
274 L->top = top; /* set top to current position (in case of yield) */
274 if (!call_binTM(L, top-2, top-1, top-2, TM_CONCAT)) 275 if (!call_binTM(L, top-2, top-1, top-2, TM_CONCAT))
275 luaG_concaterror(L, top-2, top-1); 276 luaG_concaterror(L, top-2, top-1);
277 L->top = L->ci->top; /* restore top */
276 } 278 }
277 else if (tsvalue(top-1)->len == 0) { /* second operand is empty? */ 279 else if (tsvalue(top-1)->len == 0) { /* second operand is empty? */
278 (void)tostring(L, top - 2); /* result is first operand */ ; 280 (void)tostring(L, top - 2); /* result is first operand */ ;