diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2009-03-10 14:14:37 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2009-03-10 14:14:37 -0300 |
commit | ba484b9eb16dd62a7c3a5400a66eb952b654d3f0 (patch) | |
tree | 31692ddf85265e5a46eab0cd55a0b0757a225e68 /lvm.c | |
parent | f9d015523ef48266cea37e13717c223c16941b23 (diff) | |
download | lua-ba484b9eb16dd62a7c3a5400a66eb952b654d3f0.tar.gz lua-ba484b9eb16dd62a7c3a5400a66eb952b654d3f0.tar.bz2 lua-ba484b9eb16dd62a7c3a5400a66eb952b654d3f0.zip |
yielding across lua_call (first version)
Diffstat (limited to 'lvm.c')
-rw-r--r-- | lvm.c | 72 |
1 files changed, 61 insertions, 11 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lvm.c,v 2.82 2009/03/02 16:34:23 roberto Exp roberto $ | 2 | ** $Id: lvm.c,v 2.83 2009/03/04 13:32:29 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 | */ |
@@ -79,17 +79,14 @@ static void traceexec (lua_State *L) { | |||
79 | static void callTM (lua_State *L, const TValue *f, const TValue *p1, | 79 | static void callTM (lua_State *L, const TValue *f, const TValue *p1, |
80 | const TValue *p2, TValue *p3, int hasres) { | 80 | const TValue *p2, TValue *p3, int hasres) { |
81 | ptrdiff_t result = savestack(L, p3); | 81 | ptrdiff_t result = savestack(L, p3); |
82 | int oldbase = L->baseCcalls; | ||
83 | setobj2s(L, L->top++, f); /* push function */ | 82 | setobj2s(L, L->top++, f); /* push function */ |
84 | setobj2s(L, L->top++, p1); /* 1st argument */ | 83 | setobj2s(L, L->top++, p1); /* 1st argument */ |
85 | setobj2s(L, L->top++, p2); /* 2nd argument */ | 84 | setobj2s(L, L->top++, p2); /* 2nd argument */ |
86 | if (!hasres) /* no result? 'p3' is third argument */ | 85 | if (!hasres) /* no result? 'p3' is third argument */ |
87 | setobj2s(L, L->top++, p3); /* 3th argument */ | 86 | setobj2s(L, L->top++, p3); /* 3th argument */ |
88 | luaD_checkstack(L, 0); | 87 | luaD_checkstack(L, 0); |
89 | if (isLua(L->ci)) /* metamethod invoked from a Lua function? */ | 88 | /* metamethod may yield only when called from Lua code */ |
90 | L->baseCcalls++; /* allow it to yield */ | 89 | luaD_call(L, L->top - (4 - hasres), hasres, isLua(L->ci)); |
91 | luaD_call(L, L->top - (4 - hasres), hasres); | ||
92 | L->baseCcalls = oldbase; | ||
93 | if (hasres) { /* if has result, move it to its place */ | 90 | if (hasres) { /* if has result, move it to its place */ |
94 | p3 = restorestack(L, result); | 91 | p3 = restorestack(L, result); |
95 | setobjs2s(L, p3, --L->top); | 92 | setobjs2s(L, p3, --L->top); |
@@ -356,6 +353,61 @@ static void Arith (lua_State *L, StkId ra, const TValue *rb, | |||
356 | } | 353 | } |
357 | 354 | ||
358 | 355 | ||
356 | /* | ||
357 | ** finish execution of an opcode interrupted by an yield | ||
358 | */ | ||
359 | void luaV_finishOp (lua_State *L) { | ||
360 | Instruction inst = *(L->savedpc - 1); /* interrupted instruction */ | ||
361 | switch (GET_OPCODE(inst)) { /* finish its execution */ | ||
362 | case OP_ADD: case OP_SUB: case OP_MUL: case OP_DIV: | ||
363 | case OP_MOD: case OP_POW: case OP_UNM: case OP_LEN: | ||
364 | case OP_GETGLOBAL: case OP_GETTABLE: case OP_SELF: { | ||
365 | setobjs2s(L, L->base + GETARG_A(inst), --L->top); | ||
366 | break; | ||
367 | } | ||
368 | case OP_LE: case OP_LT: case OP_EQ: { | ||
369 | int res = !l_isfalse(L->top - 1); | ||
370 | L->top--; | ||
371 | /* metamethod should not be called when operand is K */ | ||
372 | lua_assert(!ISK(GETARG_B(inst))); | ||
373 | if (GET_OPCODE(inst) == OP_LE && /* "<=" using "<" instead? */ | ||
374 | ttisnil(luaT_gettmbyobj(L, L->base + GETARG_B(inst), TM_LE))) | ||
375 | res = !res; /* invert result */ | ||
376 | lua_assert(GET_OPCODE(*L->savedpc) == OP_JMP); | ||
377 | if (res != GETARG_A(inst)) /* condition failed? */ | ||
378 | L->savedpc++; /* skip jump instruction */ | ||
379 | break; | ||
380 | } | ||
381 | case OP_CONCAT: { | ||
382 | StkId top = L->top - 1; /* top when __concat was called */ | ||
383 | int last = cast_int(top - L->base) - 2; /* last element and ... */ | ||
384 | int b = GETARG_B(inst); /* ... first element to concatenate */ | ||
385 | int total = last - b + 1; /* number of elements to concatenate */ | ||
386 | setobj2s(L, top - 2, top); /* put TM result in proper position */ | ||
387 | L->top = L->ci->top; /* correct top */ | ||
388 | if (total > 1) /* are there elements to concat? */ | ||
389 | luaV_concat(L, total, last); /* concat them (may yield again) */ | ||
390 | /* move final result to final position */ | ||
391 | setobj2s(L, L->base + GETARG_A(inst), L->base + b); | ||
392 | break; | ||
393 | } | ||
394 | case OP_TFORCALL: { | ||
395 | lua_assert(GET_OPCODE(*L->savedpc) == OP_TFORLOOP); | ||
396 | L->top = L->ci->top; /* correct top */ | ||
397 | break; | ||
398 | } | ||
399 | case OP_CALL: { | ||
400 | if (GETARG_C(inst) - 1 >= 0) /* nresults >= 0? */ | ||
401 | L->top = L->ci->top; /* adjust results */ | ||
402 | break; | ||
403 | } | ||
404 | case OP_TAILCALL: case OP_SETGLOBAL: case OP_SETTABLE: | ||
405 | break; | ||
406 | default: lua_assert(0); | ||
407 | } | ||
408 | } | ||
409 | |||
410 | |||
359 | 411 | ||
360 | /* | 412 | /* |
361 | ** some macros for common tasks in `luaV_execute' | 413 | ** some macros for common tasks in `luaV_execute' |
@@ -672,11 +724,9 @@ void luaV_execute (lua_State *L) { | |||
672 | setobjs2s(L, cb+2, ra+2); | 724 | setobjs2s(L, cb+2, ra+2); |
673 | setobjs2s(L, cb+1, ra+1); | 725 | setobjs2s(L, cb+1, ra+1); |
674 | setobjs2s(L, cb, ra); | 726 | setobjs2s(L, cb, ra); |
675 | L->baseCcalls++; /* allow yields */ | ||
676 | L->top = cb + 3; /* func. + 2 args (state and index) */ | 727 | L->top = cb + 3; /* func. + 2 args (state and index) */ |
677 | Protect(luaD_call(L, cb, GETARG_C(i))); | 728 | Protect(luaD_call(L, cb, GETARG_C(i), 1)); |
678 | L->top = L->ci->top; | 729 | L->top = L->ci->top; |
679 | L->baseCcalls--; | ||
680 | i = *(L->savedpc++); /* go to next instruction */ | 730 | i = *(L->savedpc++); /* go to next instruction */ |
681 | ra = RA(i); | 731 | ra = RA(i); |
682 | lua_assert(GET_OPCODE(i) == OP_TFORLOOP); | 732 | lua_assert(GET_OPCODE(i) == OP_TFORLOOP); |
@@ -725,8 +775,8 @@ void luaV_execute (lua_State *L) { | |||
725 | ncl = luaF_newLclosure(L, nup, cl->env); | 775 | ncl = luaF_newLclosure(L, nup, cl->env); |
726 | ncl->l.p = p; | 776 | ncl->l.p = p; |
727 | setclvalue(L, ra, ncl); | 777 | setclvalue(L, ra, ncl); |
728 | for (j=0; j<nup; j++, L->savedpc++) { | 778 | for (j=0; j<nup; j++) { |
729 | Instruction u = *L->savedpc; | 779 | Instruction u = *L->savedpc++; |
730 | if (GET_OPCODE(u) == OP_GETUPVAL) | 780 | if (GET_OPCODE(u) == OP_GETUPVAL) |
731 | ncl->l.upvals[j] = cl->upvals[GETARG_B(u)]; | 781 | ncl->l.upvals[j] = cl->upvals[GETARG_B(u)]; |
732 | else { | 782 | else { |