diff options
| author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2008-11-06 10:43:51 -0200 |
|---|---|---|
| committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2008-11-06 10:43:51 -0200 |
| commit | b47209849321b17e2037bfa46abf530e69bcc869 (patch) | |
| tree | 1915a213b71e70c7cdbc405b260ccdef48bedf21 | |
| parent | 84b3daebbd09b334db0fa125700ffdb1d326c4f6 (diff) | |
| download | lua-b47209849321b17e2037bfa46abf530e69bcc869.tar.gz lua-b47209849321b17e2037bfa46abf530e69bcc869.tar.bz2 lua-b47209849321b17e2037bfa46abf530e69bcc869.zip | |
concat TM can yield
| -rw-r--r-- | ldo.c | 32 | ||||
| -rw-r--r-- | lvm.c | 4 |
2 files changed, 24 insertions, 12 deletions
| @@ -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) { | |||
| 390 | static void unroll (lua_State *L) { | 390 | static 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) { | |||
| 500 | LUA_API int lua_yield (lua_State *L, int nresults) { | 511 | LUA_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 */ |
| @@ -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 */ ; |
