aboutsummaryrefslogtreecommitdiff
path: root/lvm.c
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2009-03-10 14:14:37 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2009-03-10 14:14:37 -0300
commitba484b9eb16dd62a7c3a5400a66eb952b654d3f0 (patch)
tree31692ddf85265e5a46eab0cd55a0b0757a225e68 /lvm.c
parentf9d015523ef48266cea37e13717c223c16941b23 (diff)
downloadlua-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.c72
1 files changed, 61 insertions, 11 deletions
diff --git a/lvm.c b/lvm.c
index 2b54266f..494b40cd 100644
--- a/lvm.c
+++ b/lvm.c
@@ -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) {
79static void callTM (lua_State *L, const TValue *f, const TValue *p1, 79static 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*/
359void 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 {