Ver Fonte

no more 'stackless' implementation; 'luaV_execute' calls itself
recursively to execute function calls. 'unroll' continues all
executions suspended by an yield (through a long jump)

Roberto Ierusalimschy há 7 anos atrás
pai
commit
196c87c9ce
9 ficheiros alterados com 90 adições e 112 exclusões
  1. 2 1
      ldebug.c
  2. 18 48
      ldo.c
  3. 1 2
      ldo.h
  4. 4 3
      llimits.h
  5. 4 8
      lparser.c
  6. 26 2
      lstate.c
  7. 8 9
      lstate.h
  8. 5 1
      ltests.h
  9. 22 38
      lvm.c

+ 2 - 1
ldebug.c

@@ -1,5 +1,5 @@
 /*
 /*
-** $Id: ldebug.c,v 2.143 2017/11/13 12:20:51 roberto Exp roberto $
+** $Id: ldebug.c,v 2.144 2017/11/13 15:36:52 roberto Exp roberto $
 ** Debug Interface
 ** Debug Interface
 ** See Copyright Notice in lua.h
 ** See Copyright Notice in lua.h
 */
 */
@@ -724,6 +724,7 @@ l_noret luaG_errormsg (lua_State *L) {
     setobjs2s(L, L->top, L->top - 1);  /* move argument */
     setobjs2s(L, L->top, L->top - 1);  /* move argument */
     setobjs2s(L, L->top - 1, errfunc);  /* push function */
     setobjs2s(L, L->top - 1, errfunc);  /* push function */
     L->top++;  /* assume EXTRA_STACK */
     L->top++;  /* assume EXTRA_STACK */
+    luaE_incCcalls(L);
     luaD_callnoyield(L, L->top - 2, 1);  /* call it */
     luaD_callnoyield(L, L->top - 2, 1);  /* call it */
   }
   }
   luaD_throw(L, LUA_ERRRUN);
   luaD_throw(L, LUA_ERRRUN);

+ 18 - 48
ldo.c

@@ -1,5 +1,5 @@
 /*
 /*
-** $Id: ldo.c,v 2.172 2017/11/13 15:36:52 roberto Exp roberto $
+** $Id: ldo.c,v 2.173 2017/11/21 14:17:35 roberto Exp roberto $
 ** Stack and Call structure of Lua
 ** Stack and Call structure of Lua
 ** See Copyright Notice in lua.h
 ** See Copyright Notice in lua.h
 */
 */
@@ -135,7 +135,7 @@ l_noret luaD_throw (lua_State *L, int errcode) {
 
 
 
 
 int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud) {
 int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud) {
-  unsigned short oldnCcalls = L->nCcalls;
+  unsigned short oldnCcalls = L->nCcalls - L->nci;
   struct lua_longjmp lj;
   struct lua_longjmp lj;
   lj.status = LUA_OK;
   lj.status = LUA_OK;
   lj.previous = L->errorJmp;  /* chain new error handler */
   lj.previous = L->errorJmp;  /* chain new error handler */
@@ -144,7 +144,7 @@ int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud) {
     (*f)(L, ud);
     (*f)(L, ud);
   );
   );
   L->errorJmp = lj.previous;  /* restore old error handler */
   L->errorJmp = lj.previous;  /* restore old error handler */
-  L->nCcalls = oldnCcalls;
+  L->nCcalls = oldnCcalls + L->nci;
   return lj.status;
   return lj.status;
 }
 }
 
 
@@ -299,7 +299,7 @@ static void callhook (lua_State *L, CallInfo *ci, int istail) {
 
 
 /*
 /*
 ** Check whether __call metafield of 'func' is a function. If so, put
 ** Check whether __call metafield of 'func' is a function. If so, put
-** it in stack below original 'func' so that 'luaD_precall' can call
+** it in stack below original 'func' so that 'luaD_call' can call
 ** it. Raise an error if __call metafield is not a function.
 ** it. Raise an error if __call metafield is not a function.
 */
 */
 StkId luaD_tryfuncTM (lua_State *L, StkId func) {
 StkId luaD_tryfuncTM (lua_State *L, StkId func) {
@@ -417,13 +417,12 @@ void luaD_pretailcall (lua_State *L, CallInfo *ci, StkId func, int n) {
 
 
 
 
 /*
 /*
-** Prepares a function call: checks the stack, creates a new CallInfo
-** entry, fills in the relevant information, calls hook if needed.
-** If function is a C function, does the call, too. (Otherwise, leave
-** the execution ('luaV_execute') to the caller, to allow stackless
-** calls.) Returns true iff function has been executed (C function).
+** Call a function (C or Lua). The function to be called is at *func.
+** The arguments are on the stack, right after the function.
+** When returns, all the results are on the stack, starting at the original
+** function position.
 */
 */
-int luaD_precall (lua_State *L, StkId func, int nresults) {
+void luaD_call (lua_State *L, StkId func, int nresults) {
   lua_CFunction f;
   lua_CFunction f;
   TValue *funcv = s2v(func);
   TValue *funcv = s2v(func);
   CallInfo *ci;
   CallInfo *ci;
@@ -449,7 +448,7 @@ int luaD_precall (lua_State *L, StkId func, int nresults) {
       lua_lock(L);
       lua_lock(L);
       api_checknelems(L, n);
       api_checknelems(L, n);
       luaD_poscall(L, ci, L->top - n, n);
       luaD_poscall(L, ci, L->top - n, n);
-      return 1;
+      break;
     }
     }
     case LUA_TLCL: {  /* Lua function: prepare its call */
     case LUA_TLCL: {  /* Lua function: prepare its call */
       Proto *p = clLvalue(funcv)->p;
       Proto *p = clLvalue(funcv)->p;
@@ -469,46 +468,18 @@ int luaD_precall (lua_State *L, StkId func, int nresults) {
       ci->callstatus = CIST_LUA;
       ci->callstatus = CIST_LUA;
       if (L->hookmask)
       if (L->hookmask)
         callhook(L, ci, 0);
         callhook(L, ci, 0);
-      return 0;
+      luaV_execute(L);  /* run the function */
+      break;
     }
     }
     default: {  /* not a function */
     default: {  /* not a function */
       func = luaD_tryfuncTM(L, func);  /* try to get '__call' metamethod */
       func = luaD_tryfuncTM(L, func);  /* try to get '__call' metamethod */
-      return luaD_precall(L, func, nresults);  /* now it must be a function */
+      luaD_call(L, func, nresults);  /* now it must be a function */
+      break;
     }
     }
   }
   }
 }
 }
 
 
 
 
-/*
-** Check appropriate error for stack overflow ("regular" overflow or
-** overflow while handling stack overflow). If 'nCalls' is larger than
-** LUAI_MAXCCALLS (which means it is handling a "regular" overflow) but
-** smaller than 9/8 of LUAI_MAXCCALLS, does not report an error (to
-** allow overflow handling to work)
-*/
-static void stackerror (lua_State *L) {
-  if (L->nCcalls == LUAI_MAXCCALLS)
-    luaG_runerror(L, "C stack overflow");
-  else if (L->nCcalls >= (LUAI_MAXCCALLS + (LUAI_MAXCCALLS>>3)))
-    luaD_throw(L, LUA_ERRERR);  /* error while handing stack error */
-}
-
-
-/*
-** Call a function (C or Lua). The function to be called is at *func.
-** The arguments are on the stack, right after the function.
-** When returns, all the results are on the stack, starting at the original
-** function position.
-*/
-void luaD_call (lua_State *L, StkId func, int nResults) {
-  if (++L->nCcalls >= LUAI_MAXCCALLS)
-    stackerror(L);
-  if (!luaD_precall(L, func, nResults))  /* is a Lua function? */
-    luaV_execute(L);  /* call it */
-  L->nCcalls--;
-}
-
-
 /*
 /*
 ** Similar to 'luaD_call', but does not allow yields during the call
 ** Similar to 'luaD_call', but does not allow yields during the call
 */
 */
@@ -541,7 +512,7 @@ static void finishCcall (lua_State *L, int status) {
   n = (*ci->u.c.k)(L, status, ci->u.c.ctx);  /* call continuation function */
   n = (*ci->u.c.k)(L, status, ci->u.c.ctx);  /* call continuation function */
   lua_lock(L);
   lua_lock(L);
   api_checknelems(L, n);
   api_checknelems(L, n);
-  luaD_poscall(L, ci, L->top - n, n);  /* finish 'luaD_precall' */
+  luaD_poscall(L, ci, L->top - n, n);  /* finish 'luaD_call' */
 }
 }
 
 
 
 
@@ -629,8 +600,7 @@ static void resume (lua_State *L, void *ud) {
   StkId firstArg = L->top - n;  /* first argument */
   StkId firstArg = L->top - n;  /* first argument */
   CallInfo *ci = L->ci;
   CallInfo *ci = L->ci;
   if (L->status == LUA_OK) {  /* starting a coroutine? */
   if (L->status == LUA_OK) {  /* starting a coroutine? */
-    if (!luaD_precall(L, firstArg - 1, LUA_MULTRET))  /* Lua function? */
-      luaV_execute(L);  /* call it */
+    luaD_call(L, firstArg - 1, LUA_MULTRET);
   }
   }
   else {  /* resuming from previous yield */
   else {  /* resuming from previous yield */
     lua_assert(L->status == LUA_YIELD);
     lua_assert(L->status == LUA_YIELD);
@@ -645,7 +615,7 @@ static void resume (lua_State *L, void *ud) {
         api_checknelems(L, n);
         api_checknelems(L, n);
         firstArg = L->top - n;  /* yield results come from continuation */
         firstArg = L->top - n;  /* yield results come from continuation */
       }
       }
-      luaD_poscall(L, ci, firstArg, n);  /* finish 'luaD_precall' */
+      luaD_poscall(L, ci, firstArg, n);  /* finish 'luaD_call' */
     }
     }
     unroll(L, NULL);  /* run continuation */
     unroll(L, NULL);  /* run continuation */
   }
   }
@@ -688,7 +658,7 @@ LUA_API int lua_resume (lua_State *L, lua_State *from, int nargs,
                                     : L->top - (L->ci->func + 1);
                                     : L->top - (L->ci->func + 1);
   L->nny = oldnny;  /* restore 'nny' */
   L->nny = oldnny;  /* restore 'nny' */
   L->nCcalls--;
   L->nCcalls--;
-  lua_assert(L->nCcalls == ((from) ? from->nCcalls : 0));
+  // lua_assert(L->nCcalls == ((from) ? from->nCcalls : 0));
   lua_unlock(L);
   lua_unlock(L);
   return status;
   return status;
 }
 }

+ 1 - 2
ldo.h

@@ -1,5 +1,5 @@
 /*
 /*
-** $Id: ldo.h,v 2.33 2017/11/07 13:25:26 roberto Exp roberto $
+** $Id: ldo.h,v 2.34 2017/11/21 14:18:03 roberto Exp roberto $
 ** Stack and Call structure of Lua
 ** Stack and Call structure of Lua
 ** See Copyright Notice in lua.h
 ** See Copyright Notice in lua.h
 */
 */
@@ -47,7 +47,6 @@ typedef void (*Pfunc) (lua_State *L, void *ud);
 LUAI_FUNC int luaD_protectedparser (lua_State *L, ZIO *z, const char *name,
 LUAI_FUNC int luaD_protectedparser (lua_State *L, ZIO *z, const char *name,
                                                   const char *mode);
                                                   const char *mode);
 LUAI_FUNC void luaD_hook (lua_State *L, int event, int line);
 LUAI_FUNC void luaD_hook (lua_State *L, int event, int line);
-LUAI_FUNC int luaD_precall (lua_State *L, StkId func, int nresults);
 LUAI_FUNC void luaD_pretailcall (lua_State *L, CallInfo *ci, StkId func, int n);
 LUAI_FUNC void luaD_pretailcall (lua_State *L, CallInfo *ci, StkId func, int n);
 LUAI_FUNC void luaD_call (lua_State *L, StkId func, int nResults);
 LUAI_FUNC void luaD_call (lua_State *L, StkId func, int nResults);
 LUAI_FUNC void luaD_callnoyield (lua_State *L, StkId func, int nResults);
 LUAI_FUNC void luaD_callnoyield (lua_State *L, StkId func, int nResults);

+ 4 - 3
llimits.h

@@ -1,5 +1,5 @@
 /*
 /*
-** $Id: llimits.h,v 1.143 2017/06/01 19:16:34 roberto Exp roberto $
+** $Id: llimits.h,v 1.144 2017/06/27 11:35:01 roberto Exp roberto $
 ** Limits, basic types, and some other 'installation-dependent' definitions
 ** Limits, basic types, and some other 'installation-dependent' definitions
 ** See Copyright Notice in lua.h
 ** See Copyright Notice in lua.h
 */
 */
@@ -140,10 +140,11 @@ typedef LUAI_UACINT l_uacInt;
 
 
 /*
 /*
 ** maximum depth for nested C calls and syntactical nested non-terminals
 ** maximum depth for nested C calls and syntactical nested non-terminals
-** in a program. (Value must fit in an unsigned short int.)
+** in a program. (Value must fit in an unsigned short int. It must also
+** be compatible with the size of the C stack.)
 */
 */
 #if !defined(LUAI_MAXCCALLS)
 #if !defined(LUAI_MAXCCALLS)
-#define LUAI_MAXCCALLS		200
+#define LUAI_MAXCCALLS		1000
 #endif
 #endif
 
 
 
 

+ 4 - 8
lparser.c

@@ -1,5 +1,5 @@
 /*
 /*
-** $Id: lparser.c,v 2.166 2017/09/28 16:53:29 roberto Exp roberto $
+** $Id: lparser.c,v 2.167 2017/10/04 21:53:03 roberto Exp roberto $
 ** Lua Parser
 ** Lua Parser
 ** See Copyright Notice in lua.h
 ** See Copyright Notice in lua.h
 */
 */
@@ -330,11 +330,7 @@ static void adjust_assign (LexState *ls, int nvars, int nexps, expdesc *e) {
 }
 }
 
 
 
 
-static void enterlevel (LexState *ls) {
-  lua_State *L = ls->L;
-  ++L->nCcalls;
-  checklimit(ls->fs, L->nCcalls, LUAI_MAXCCALLS, "C levels");
-}
+#define enterlevel(ls)	luaE_incCcalls((ls)->L)
 
 
 
 
 #define leavelevel(ls)	((ls)->L->nCcalls--)
 #define leavelevel(ls)	((ls)->L->nCcalls--)
@@ -1188,9 +1184,9 @@ static void assignment (LexState *ls, struct LHS_assign *lh, int nvars) {
     suffixedexp(ls, &nv.v);
     suffixedexp(ls, &nv.v);
     if (!vkisindexed(nv.v.k))
     if (!vkisindexed(nv.v.k))
       check_conflict(ls, lh, &nv.v);
       check_conflict(ls, lh, &nv.v);
-    checklimit(ls->fs, nvars + ls->L->nCcalls, LUAI_MAXCCALLS,
-                    "C levels");
+    luaE_incCcalls(ls->L);  /* control recursion depth */
     assignment(ls, &nv, nvars+1);
     assignment(ls, &nv, nvars+1);
+    ls->L->nCcalls--;
   }
   }
   else {  /* assignment -> '=' explist */
   else {  /* assignment -> '=' explist */
     int nexps;
     int nexps;

+ 26 - 2
lstate.c

@@ -1,5 +1,5 @@
 /*
 /*
-** $Id: lstate.c,v 2.146 2017/11/07 13:25:26 roberto Exp roberto $
+** $Id: lstate.c,v 2.147 2017/11/13 15:36:52 roberto Exp roberto $
 ** Global State
 ** Global State
 ** See Copyright Notice in lua.h
 ** See Copyright Notice in lua.h
 */
 */
@@ -97,8 +97,28 @@ void luaE_setdebt (global_State *g, l_mem debt) {
 }
 }
 
 
 
 
+/*
+** Increment count of "C calls" and check for overflows. In case of
+** a stack overflow, check appropriate error ("regular" overflow or
+** overflow while handling stack overflow). If 'nCalls' is larger than
+** LUAI_MAXCCALLS (which means it is handling a "regular" overflow) but
+** smaller than 9/8 of LUAI_MAXCCALLS, does not report an error (to
+** allow overflow handling to work)
+*/
+void luaE_incCcalls (lua_State *L) {
+  if (++L->nCcalls >= LUAI_MAXCCALLS) {
+    if (L->nCcalls == LUAI_MAXCCALLS)
+      luaG_runerror(L, "C stack overflow");
+    else if (L->nCcalls >= (LUAI_MAXCCALLS + (LUAI_MAXCCALLS>>3)))
+      luaD_throw(L, LUA_ERRERR);  /* error while handing stack error */
+  }
+}
+
+
 CallInfo *luaE_extendCI (lua_State *L) {
 CallInfo *luaE_extendCI (lua_State *L) {
-  CallInfo *ci = luaM_new(L, CallInfo);
+  CallInfo *ci;
+  luaE_incCcalls(L);
+  ci = luaM_new(L, CallInfo);
   lua_assert(L->ci->next == NULL);
   lua_assert(L->ci->next == NULL);
   L->ci->next = ci;
   L->ci->next = ci;
   ci->previous = L->ci;
   ci->previous = L->ci;
@@ -116,11 +136,13 @@ void luaE_freeCI (lua_State *L) {
   CallInfo *ci = L->ci;
   CallInfo *ci = L->ci;
   CallInfo *next = ci->next;
   CallInfo *next = ci->next;
   ci->next = NULL;
   ci->next = NULL;
+  L->nCcalls -= L->nci;  /* to subtract removed elements from 'nCcalls' */
   while ((ci = next) != NULL) {
   while ((ci = next) != NULL) {
     next = ci->next;
     next = ci->next;
     luaM_free(L, ci);
     luaM_free(L, ci);
     L->nci--;
     L->nci--;
   }
   }
+  L->nCcalls += L->nci;  /* to subtract removed elements from 'nCcalls' */
 }
 }
 
 
 
 
@@ -130,6 +152,7 @@ void luaE_freeCI (lua_State *L) {
 void luaE_shrinkCI (lua_State *L) {
 void luaE_shrinkCI (lua_State *L) {
   CallInfo *ci = L->ci;
   CallInfo *ci = L->ci;
   CallInfo *next2;  /* next's next */
   CallInfo *next2;  /* next's next */
+  L->nCcalls -= L->nci;  /* to subtract removed elements from 'nCcalls' */
   /* while there are two nexts */
   /* while there are two nexts */
   while (ci->next != NULL && (next2 = ci->next->next) != NULL) {
   while (ci->next != NULL && (next2 = ci->next->next) != NULL) {
     luaM_free(L, ci->next);  /* free next */
     luaM_free(L, ci->next);  /* free next */
@@ -138,6 +161,7 @@ void luaE_shrinkCI (lua_State *L) {
     next2->previous = ci;
     next2->previous = ci;
     ci = next2;  /* keep next's next */
     ci = next2;  /* keep next's next */
   }
   }
+  L->nCcalls += L->nci;  /* to subtract removed elements from 'nCcalls' */
 }
 }
 
 
 
 

+ 8 - 9
lstate.h

@@ -1,5 +1,5 @@
 /*
 /*
-** $Id: lstate.h,v 2.150 2017/11/07 13:25:26 roberto Exp roberto $
+** $Id: lstate.h,v 2.151 2017/11/13 15:36:52 roberto Exp roberto $
 ** Global State
 ** Global State
 ** See Copyright Notice in lua.h
 ** See Copyright Notice in lua.h
 */
 */
@@ -104,7 +104,7 @@ typedef struct CallInfo {
     int nyield;  /* number of values yielded */
     int nyield;  /* number of values yielded */
   } u2;
   } u2;
   short nresults;  /* expected number of results from this function */
   short nresults;  /* expected number of results from this function */
-  unsigned short callstatus;
+  lu_byte callstatus;
 } CallInfo;
 } CallInfo;
 
 
 
 
@@ -114,13 +114,11 @@ typedef struct CallInfo {
 #define CIST_OAH	(1<<0)	/* original value of 'allowhook' */
 #define CIST_OAH	(1<<0)	/* original value of 'allowhook' */
 #define CIST_LUA	(1<<1)	/* call is running a Lua function */
 #define CIST_LUA	(1<<1)	/* call is running a Lua function */
 #define CIST_HOOKED	(1<<2)	/* call is running a debug hook */
 #define CIST_HOOKED	(1<<2)	/* call is running a debug hook */
-#define CIST_FRESH	(1<<3)	/* call is running on a fresh invocation
-                                   of luaV_execute */
-#define CIST_YPCALL	(1<<4)	/* call is a yieldable protected call */
-#define CIST_TAIL	(1<<5)	/* call was tail called */
-#define CIST_HOOKYIELD	(1<<6)	/* last hook called yielded */
-#define CIST_LEQ	(1<<7)  /* using __lt for __le */
-#define CIST_FIN	(1<<8)  /* call is running a finalizer */
+#define CIST_YPCALL	(1<<3)	/* call is a yieldable protected call */
+#define CIST_TAIL	(1<<4)	/* call was tail called */
+#define CIST_HOOKYIELD	(1<<5)	/* last hook called yielded */
+#define CIST_LEQ	(1<<6)  /* using __lt for __le */
+#define CIST_FIN	(1<<7)  /* call is running a finalizer */
 
 
 #define isLua(ci)	((ci)->callstatus & CIST_LUA)
 #define isLua(ci)	((ci)->callstatus & CIST_LUA)
 
 
@@ -256,6 +254,7 @@ LUAI_FUNC void luaE_freethread (lua_State *L, lua_State *L1);
 LUAI_FUNC CallInfo *luaE_extendCI (lua_State *L);
 LUAI_FUNC CallInfo *luaE_extendCI (lua_State *L);
 LUAI_FUNC void luaE_freeCI (lua_State *L);
 LUAI_FUNC void luaE_freeCI (lua_State *L);
 LUAI_FUNC void luaE_shrinkCI (lua_State *L);
 LUAI_FUNC void luaE_shrinkCI (lua_State *L);
+LUAI_FUNC void luaE_incCcalls (lua_State *L);
 
 
 
 
 #endif
 #endif

+ 5 - 1
ltests.h

@@ -1,5 +1,5 @@
 /*
 /*
-** $Id: ltests.h,v 2.51 2017/06/27 11:35:31 roberto Exp roberto $
+** $Id: ltests.h,v 2.52 2017/11/13 12:19:35 roberto Exp roberto $
 ** Internal Header for Debugging of the Lua Implementation
 ** Internal Header for Debugging of the Lua Implementation
 ** See Copyright Notice in lua.h
 ** See Copyright Notice in lua.h
 */
 */
@@ -34,6 +34,10 @@
 #define lua_assert(c)           assert(c)
 #define lua_assert(c)           assert(c)
 
 
 
 
+/* compiled with -O0, Lua uses a lot of C stack space... */
+#undef LUAI_MAXCCALLS
+#define LUAI_MAXCCALLS	300
+
 /* to avoid warnings, and to make sure value is really unused */
 /* to avoid warnings, and to make sure value is really unused */
 #define UNUSED(x)       (x=0, (void)(x))
 #define UNUSED(x)       (x=0, (void)(x))
 
 

+ 22 - 38
lvm.c

@@ -1,5 +1,9 @@
 /*
 /*
-** $Id: lvm.c,v 2.314 2017/11/22 18:41:20 roberto Exp roberto $
+<<<<<<< lvm.c
+** $Id: lvm.c,v 2.313 2017/11/21 14:17:35 roberto Exp roberto $
+=======
+** $Id: lvm.c,v 2.315 2017/11/22 19:15:44 roberto Exp $
+>>>>>>> 2.315
 ** Lua virtual machine
 ** Lua virtual machine
 ** See Copyright Notice in lua.h
 ** See Copyright Notice in lua.h
 */
 */
@@ -829,20 +833,12 @@ void luaV_finishOp (lua_State *L) {
 
 
 
 
 void luaV_execute (lua_State *L) {
 void luaV_execute (lua_State *L) {
-  CallInfo *ci = L->ci;  /* local copy of 'L->ci' */
-  LClosure *cl;
-  TValue *k;
-  StkId base;  /* local copy of 'ci->func + 1' */
-  int trap;
-  const Instruction *pc;  /* local copy of 'ci->u.l.savedpc' */
-  ci->callstatus |= CIST_FRESH;  /* fresh invocation of 'luaV_execute" */
- newframe:  /* reentry point when frame changes (call/return) */
-  lua_assert(ci == L->ci);
-  cl = clLvalue(s2v(ci->func));  /* local reference to function's closure */
-  k = cl->p->k;  /* local reference to function's constant table */
-  updatetrap(ci);
-  updatebase(ci);
-  pc = ci->u.l.savedpc;
+  CallInfo *ci = L->ci;
+  LClosure *cl = clLvalue(s2v(ci->func));
+  TValue *k = cl->p->k;
+  StkId base = ci->func + 1;
+  int trap = ci->u.l.trap;
+  const Instruction *pc = ci->u.l.savedpc;
   /* main loop of interpreter */
   /* main loop of interpreter */
   for (;;) {
   for (;;) {
     Instruction i;
     Instruction i;
@@ -1418,20 +1414,13 @@ void luaV_execute (lua_State *L) {
       vmcase(OP_CALL) {
       vmcase(OP_CALL) {
         int b = GETARG_B(i);
         int b = GETARG_B(i);
         int nresults = GETARG_C(i) - 1;
         int nresults = GETARG_C(i) - 1;
-        int isC;
         if (b != 0)  /* fixed number of arguments? */
         if (b != 0)  /* fixed number of arguments? */
           L->top = ra + b;  /* top signals number of arguments */
           L->top = ra + b;  /* top signals number of arguments */
         /* else previous instruction set top */
         /* else previous instruction set top */
-        Protect(isC = luaD_precall(L, ra, nresults));
-        if (isC) {  /* C function? */
-          if (nresults >= 0)  /* fixed number of results? */
-            L->top = ci->top;  /* correct top */
-          /* else leave top for next instruction */
-        }
-        else {  /* Lua function */
-          ci = L->ci;
-          goto newframe;  /* restart luaV_execute over new Lua function */
-        }
+        Protect(luaD_call(L, ra, nresults));
+        if (nresults >= 0)  /* fixed number of results? */
+          L->top = ci->top;  /* correct top */
+        /* else leave top for next instruction */
         vmbreak;
         vmbreak;
       }
       }
       vmcase(OP_TAILCALL) {
       vmcase(OP_TAILCALL) {
@@ -1447,12 +1436,15 @@ void luaV_execute (lua_State *L) {
           b++;  /* there is now one extra argument */
           b++;  /* there is now one extra argument */
         }
         }
         if (!ttisLclosure(s2v(ra)))  /* C function? */
         if (!ttisLclosure(s2v(ra)))  /* C function? */
-          Protect(luaD_precall(L, ra, LUA_MULTRET));  /* call it */
+          Protect(luaD_call(L, ra, LUA_MULTRET));  /* call it */
         else {  /* tail call */
         else {  /* tail call */
           if (cl->p->sizep > 0) /* close upvalues from previous call */
           if (cl->p->sizep > 0) /* close upvalues from previous call */
             luaF_close(L, ci->func + 1);
             luaF_close(L, ci->func + 1);
           luaD_pretailcall(L, ci, ra, b);  /* prepare call frame */
           luaD_pretailcall(L, ci, ra, b);  /* prepare call frame */
-          goto newframe;  /* restart luaV_execute over new Lua function */
+          cl = clLvalue(s2v(ci->func));
+          k = cl->p->k;
+          updatebase(ci);
+          pc = ci->u.l.savedpc;
         }
         }
         vmbreak;
         vmbreak;
       }
       }
@@ -1461,16 +1453,8 @@ void luaV_execute (lua_State *L) {
         if (cl->p->sizep > 0)
         if (cl->p->sizep > 0)
           luaF_close(L, base);
           luaF_close(L, base);
         savepc(L);
         savepc(L);
-        b = luaD_poscall(L, ci, ra, (b != 0 ? b - 1 : cast_int(L->top - ra)));
-        if (ci->callstatus & CIST_FRESH)  /* local 'ci' still from callee */
-          return;  /* external invocation: return */
-        else {  /* invocation via reentry: continue execution */
-          ci = L->ci;
-          if (b) L->top = ci->top;
-          lua_assert(isLua(ci));
-          lua_assert(GET_OPCODE(*((ci)->u.l.savedpc - 1)) == OP_CALL);
-          goto newframe;  /* restart luaV_execute over new Lua function */
-        }
+        luaD_poscall(L, ci, ra, (b != 0 ? b - 1 : cast_int(L->top - ra)));
+        return;  /* external invocation: return */
       }
       }
       vmcase(OP_FORLOOP) {
       vmcase(OP_FORLOOP) {
         if (ttisinteger(s2v(ra))) {  /* integer loop? */
         if (ttisinteger(s2v(ra))) {  /* integer loop? */