2
0
Эх сурвалжийг харах

generic for coded as two dedicated instructions to simplify resumption

Roberto Ierusalimschy 16 жил өмнө
parent
commit
84b3daebbd
6 өөрчлөгдсөн 43 нэмэгдсэн , 39 устгасан
  1. 4 2
      ldebug.c
  2. 7 11
      ldo.c
  3. 5 3
      lopcodes.c
  4. 5 4
      lopcodes.h
  5. 7 8
      lparser.c
  6. 15 11
      lvm.c

+ 4 - 2
ldebug.c

@@ -1,5 +1,5 @@
 /*
-** $Id: ldebug.c,v 2.40 2008/07/03 14:24:11 roberto Exp roberto $
+** $Id: ldebug.c,v 2.41 2008/08/26 13:27:42 roberto Exp roberto $
 ** Debug Interface
 ** See Copyright Notice in lua.h
 */
@@ -388,12 +388,14 @@ static Instruction symbexec (const Proto *pt, int lastpc, int reg) {
         check(b < c);  /* at least two operands */
         break;
       }
-      case OP_TFORLOOP: {
+      case OP_TFORCALL: {
         check(c >= 1);  /* at least one result (control variable) */
         checkreg(pt, a+2+c);  /* space for results */
+        check(GET_OPCODE(pt->code[pc+1]) == OP_TFORLOOP);
         if (reg >= a+2) last = pc;  /* affect all regs above its base */
         break;
       }
+      case OP_TFORLOOP:
       case OP_FORLOOP:
       case OP_FORPREP:
         checkreg(pt, a+3);

+ 7 - 11
ldo.c

@@ -1,5 +1,5 @@
 /*
-** $Id: ldo.c,v 2.48 2008/08/26 13:27:42 roberto Exp roberto $
+** $Id: ldo.c,v 2.49 2008/10/28 16:53:16 roberto Exp roberto $
 ** Stack and Call structure of Lua
 ** See Copyright Notice in lua.h
 */
@@ -391,8 +391,10 @@ static void unroll (lua_State *L) {
   for (;;) {
     Instruction inst;
     luaV_execute(L);  /* execute up to higher C 'boundary' */
-    if (L->ci == L->base_ci)  /* stack is empty? */
+    if (L->ci == L->base_ci) {  /* stack is empty? */
+      lua_assert(L->baseCcalls == G(L)->nCcalls);
       return;  /* coroutine finished normally */
+    }
     L->baseCcalls--;  /* undo increment that allows yields */
     inst = *(L->savedpc - 1);  /* interrupted instruction */
     switch (GET_OPCODE(inst)) {  /* finish its execution */
@@ -419,15 +421,9 @@ static void unroll (lua_State *L) {
       }
       case OP_SETGLOBAL: case OP_SETTABLE:
         break;  /* nothing to be done */
-      case OP_TFORLOOP: {
-        StkId cb = L->base + GETARG_A(inst) + 3;
-        L->top = L->ci->top;
-        lua_assert(GET_OPCODE(*L->savedpc) == OP_JMP);
-        if (!ttisnil(cb)) {  /* continue loop? */
-          setobjs2s(L, cb - 1, cb);  /* save control variable */
-          L->savedpc += GETARG_sBx(*L->savedpc);  /* jump back */
-        }
-        L->savedpc++;
+      case OP_TFORCALL: {
+        lua_assert(GET_OPCODE(*L->savedpc) == OP_TFORLOOP);
+        L->top = L->ci->top;  /* correct top */
         break;
       }
       default: lua_assert(0);

+ 5 - 3
lopcodes.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lopcodes.c,v 1.38 2006/09/11 14:07:24 roberto Exp roberto $
+** $Id: lopcodes.c,v 1.39 2008/04/02 16:16:06 roberto Exp roberto $
 ** See Copyright Notice in lua.h
 */
 
@@ -47,11 +47,12 @@ const char *const luaP_opnames[NUM_OPCODES+1] = {
   "RETURN",
   "FORLOOP",
   "FORPREP",
-  "TFORLOOP",
+  "TFORCALL",
   "SETLIST",
   "CLOSE",
   "CLOSURE",
   "VARARG",
+  "TFORLOOP",
   "EXTRAARG",
   NULL
 };
@@ -94,11 +95,12 @@ const lu_byte luaP_opmodes[NUM_OPCODES] = {
  ,opmode(0, 0, OpArgU, OpArgN, iABC)		/* OP_RETURN */
  ,opmode(0, 1, OpArgR, OpArgN, iAsBx)		/* OP_FORLOOP */
  ,opmode(0, 1, OpArgR, OpArgN, iAsBx)		/* OP_FORPREP */
- ,opmode(1, 0, OpArgN, OpArgU, iABC)		/* OP_TFORLOOP */
+ ,opmode(0, 0, OpArgN, OpArgU, iABC)		/* OP_TFORCALL */
  ,opmode(0, 0, OpArgU, OpArgU, iABC)		/* OP_SETLIST */
  ,opmode(0, 0, OpArgN, OpArgN, iABC)		/* OP_CLOSE */
  ,opmode(0, 1, OpArgU, OpArgN, iABx)		/* OP_CLOSURE */
  ,opmode(0, 1, OpArgU, OpArgN, iABC)		/* OP_VARARG */
+ ,opmode(0, 1, OpArgR, OpArgN, iAsBx)		/* OP_TFORLOOP */
  ,opmode(0, 0, OpArgU, OpArgU, iAx)		/* OP_EXTRAARG */
 };
 

+ 5 - 4
lopcodes.h

@@ -1,5 +1,5 @@
 /*
-** $Id: lopcodes.h,v 1.126 2006/09/11 14:07:24 roberto Exp roberto $
+** $Id: lopcodes.h,v 1.127 2008/04/02 16:16:06 roberto Exp roberto $
 ** Opcodes for Lua virtual machine
 ** See Copyright Notice in lua.h
 */
@@ -211,8 +211,7 @@ OP_FORLOOP,/*	A sBx	R(A)+=R(A+2);
 			if R(A) <?= R(A+1) then { pc+=sBx; R(A+3)=R(A) }*/
 OP_FORPREP,/*	A sBx	R(A)-=R(A+2); pc+=sBx				*/
 
-OP_TFORLOOP,/*	A C	R(A+3), ... ,R(A+2+C) := R(A)(R(A+1), R(A+2));
-                        if R(A+3) ~= nil then R(A+2)=R(A+3) else pc++	*/
+OP_TFORCALL,/*	A C	R(A+3), ... ,R(A+2+C) := R(A)(R(A+1), R(A+2));	*/
 OP_SETLIST,/*	A B C	R(A)[(C-1)*FPF+i] := R(A+i), 1 <= i <= B	*/
 
 OP_CLOSE,/*	A	close all variables in the stack up to (>=) R(A)*/
@@ -220,6 +219,8 @@ OP_CLOSURE,/*	A Bx	R(A) := closure(KPROTO[Bx], R(A), ... ,R(A+n))	*/
 
 OP_VARARG,/*	A B	R(A), R(A+1), ..., R(A+B-1) = vararg		*/
 
+OP_TFORLOOP,/*	A sBx	if R(A+1) ~= nil then { R(A)=R(A+1); pc += sBx }*/
+
 OP_EXTRAARG/*	Ax	extra argument for previous opcode		*/
 } OpCode;
 
@@ -255,7 +256,7 @@ OP_EXTRAARG/*	Ax	extra argument for previous opcode		*/
 ** bits 2-3: C arg mode
 ** bits 4-5: B arg mode
 ** bit 6: instruction set register A
-** bit 7: operator is a test
+** bit 7: operator is a test (next instruction must be a jump)
 */
 
 enum OpArgMask {

+ 7 - 8
lparser.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lparser.c,v 2.58 2008/05/08 15:44:51 roberto Exp roberto $
+** $Id: lparser.c,v 2.59 2008/10/28 12:55:00 roberto Exp roberto $
 ** Lua Parser
 ** See Copyright Notice in lua.h
 */
@@ -1055,7 +1055,7 @@ static void forbody (LexState *ls, int base, int line, int nvars, int isnum) {
   /* forbody -> DO block */
   BlockCnt bl;
   FuncState *fs = ls->fs;
-  int prep;
+  int prep, endfor;
   adjustlocalvars(ls, 3);  /* control variables */
   checknext(ls, TK_DO);
   prep = isnum ? luaK_codeAsBx(fs, OP_FORPREP, base, NO_JUMP) : luaK_jump(fs);
@@ -1065,15 +1065,14 @@ static void forbody (LexState *ls, int base, int line, int nvars, int isnum) {
   block(ls);
   leaveblock(fs);  /* end of scope for declared variables */
   luaK_patchtohere(fs, prep);
-  if (isnum) {  /* numeric for? */
-    int endfor = luaK_codeAsBx(fs, OP_FORLOOP, base, NO_JUMP);
-    luaK_patchlist(fs, endfor, prep + 1);
-  }
+  if (isnum)  /* numeric for? */
+    endfor = luaK_codeAsBx(fs, OP_FORLOOP, base, NO_JUMP);
   else {  /* generic for */
-    luaK_codeABC(fs, OP_TFORLOOP, base, 0, nvars);
+    luaK_codeABC(fs, OP_TFORCALL, base, 0, nvars);
     luaK_fixline(fs, line);
-    luaK_jumpto(fs, prep + 1);
+    endfor = luaK_codeAsBx(fs, OP_TFORLOOP, base + 2, NO_JUMP);
   }
+  luaK_patchlist(fs, endfor, prep + 1);
   luaK_fixline(fs, line);
 }
 

+ 15 - 11
lvm.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lvm.c,v 2.77 2008/09/09 13:53:02 roberto Exp roberto $
+** $Id: lvm.c,v 2.78 2008/10/28 16:53:16 roberto Exp roberto $
 ** Lua virtual machine
 ** See Copyright Notice in lua.h
 */
@@ -404,7 +404,7 @@ void luaV_execute (lua_State *L) {
   k = cl->p->k;
   /* main loop of interpreter */
   for (;;) {
-    const Instruction i = *(L->savedpc++);
+    Instruction i = *(L->savedpc++);
     StkId ra;
     if ((L->hookmask & (LUA_MASKLINE | LUA_MASKCOUNT)) &&
         (--L->hookcount == 0 || L->hookmask & LUA_MASKLINE)) {
@@ -667,22 +667,26 @@ void luaV_execute (lua_State *L) {
         dojump(L, GETARG_sBx(i));
         continue;
       }
-      case OP_TFORLOOP: {
+      case OP_TFORCALL: {
         StkId cb = ra + 3;  /* call base */
         setobjs2s(L, cb+2, ra+2);
         setobjs2s(L, cb+1, ra+1);
         setobjs2s(L, cb, ra);
-        L->top = cb+3;  /* func. + 2 args (state and index) */
-        L->baseCcalls++;
+        L->baseCcalls++;  /* allow yields */
+        L->top = cb + 3;  /* func. + 2 args (state and index) */
         Protect(luaD_call(L, cb, GETARG_C(i)));
-        L->baseCcalls--;
         L->top = L->ci->top;
-        cb = RA(i) + 3;  /* previous call may change the stack */
-        if (!ttisnil(cb)) {  /* continue loop? */
-          setobjs2s(L, cb-1, cb);  /* save control variable */
-          dojump(L, GETARG_sBx(*L->savedpc));  /* jump back */
+        L->baseCcalls--;
+        i = *(L->savedpc++);  /* go to next instruction */
+        ra = RA(i);
+        lua_assert(GET_OPCODE(i) == OP_TFORLOOP);
+        /* go through */
+      }
+      case OP_TFORLOOP: {
+        if (!ttisnil(ra + 1)) {  /* continue loop? */
+          setobjs2s(L, ra, ra + 1);  /* save control variable */
+          dojump(L, GETARG_sBx(i));  /* jump back */
         }
-        L->savedpc++;
         continue;
       }
       case OP_SETLIST: {