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

new implementation for error handling

Roberto Ierusalimschy 23 жил өмнө
parent
commit
4e23699aa6
9 өөрчлөгдсөн 279 нэмэгдсэн , 259 устгасан
  1. 7 8
      lauxlib.c
  2. 8 13
      ldblib.c
  3. 135 140
      ldo.c
  4. 7 4
      ldo.h
  5. 15 8
      lstate.c
  6. 21 10
      lstate.h
  7. 1 2
      luadebug.h
  8. 77 73
      lvm.c
  9. 8 1
      lvm.h

+ 7 - 8
lauxlib.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lauxlib.c,v 1.77 2002/06/26 19:28:44 roberto Exp roberto $
+** $Id: lauxlib.c,v 1.78 2002/07/01 19:23:58 roberto Exp $
 ** Auxiliary functions for building Lua libraries
 ** See Copyright Notice in lua.h
 */
@@ -394,21 +394,20 @@ LUALIB_API int luaL_loadbuffer (lua_State *L, const char *buff, size_t size,
 
 static void callalert (lua_State *L, int status) {
   if (status != 0) {
-    int top;
-    if (status == LUA_ERRRUN)
-      lua_concat(L, 2);  /* concat error message and traceback */
-    top = lua_gettop(L);
     lua_getglobal(L, "_ALERT");
     lua_insert(L, -2);
-    lua_pcall(L, 1, 0);
-    lua_settop(L, top-1);
+    lua_call(L, 1, 0);
+    lua_pop(L, 1);
   }
 }
 
 
 static int aux_do (lua_State *L, int status) {
-  if (status == 0)  /* parse OK? */
+  if (status == 0) {  /* parse OK? */
     status = lua_pcall(L, 0, LUA_MULTRET);  /* call main */
+    if (status != 0)
+      lua_pcallreset(L);
+  }
   callalert(L, status);
   return status;
 }

+ 8 - 13
ldblib.c

@@ -1,5 +1,5 @@
 /*
-** $Id: ldblib.c,v 1.63 2002/07/08 20:22:08 roberto Exp roberto $
+** $Id: ldblib.c,v 1.64 2002/07/17 16:25:13 roberto Exp roberto $
 ** Interface from Lua to its debug API
 ** See Copyright Notice in lua.h
 */
@@ -194,15 +194,11 @@ static int debug (lua_State *L) {
 static int errorfb (lua_State *L) {
   int level = 1;  /* skip level 0 (it's this function) */
   int firstpart = 1;  /* still before eventual `...' */
-  int alllevels = 1;
-  const char *msg = lua_tostring(L, 1);
   lua_Debug ar;
-  lua_settop(L, 0);
-  if (msg) {
-    alllevels = 0;
-    if (!strstr(msg, "stack traceback:\n"))
-      lua_pushliteral(L, "stack traceback:\n");
-  }
+  if (lua_gettop(L) == 0)
+    lua_pushliteral(L, "");
+  else if (!lua_isstring(L, 1)) return 1;  /* no string message */
+  lua_pushliteral(L, "stack traceback:\n");
   while (lua_getstack(L, level++, &ar)) {
     if (level > LEVELS1 && firstpart) {
       /* no more than `LEVELS2' more levels? */
@@ -217,7 +213,7 @@ static int errorfb (lua_State *L) {
       continue;
     }
     lua_pushliteral(L, "\t");
-    lua_getinfo(L, "Snlc", &ar);
+    lua_getinfo(L, "Snl", &ar);
     lua_pushfstring(L, "%s:", ar.short_src);
     if (ar.currentline > 0)
       lua_pushfstring(L, "%d:", ar.currentline);
@@ -240,7 +236,6 @@ static int errorfb (lua_State *L) {
     }
     lua_pushliteral(L, "\n");
     lua_concat(L, lua_gettop(L));
-    if (!alllevels && ar.isprotected) break;
   }
   lua_concat(L, lua_gettop(L));
   return 1;
@@ -261,9 +256,9 @@ static const luaL_reg dblib[] = {
 
 LUALIB_API int lua_dblibopen (lua_State *L) {
   luaL_opennamedlib(L, LUA_DBLIBNAME, dblib, 0);
-  lua_pushliteral(L, LUA_TRACEBACK);
+  lua_pushliteral(L, "_TRACEBACK");
   lua_pushcfunction(L, errorfb);
-  lua_settable(L, LUA_REGISTRYINDEX);
+  lua_settable(L, LUA_GLOBALSINDEX);
   return 0;
 }
 

+ 135 - 140
ldo.c

@@ -1,5 +1,5 @@
 /*
-** $Id: ldo.c,v 1.187 2002/07/09 18:19:19 roberto Exp roberto $
+** $Id: ldo.c,v 1.188 2002/07/16 14:26:56 roberto Exp roberto $
 ** Stack and Call structure of Lua
 ** See Copyright Notice in lua.h
 */
@@ -29,40 +29,113 @@
 
 
 
+/*
+** {======================================================
+** Error-recovery functions (based on long jumps)
+** =======================================================
+*/
+
+
 /* chain list of long jump buffers */
 struct lua_longjmp {
   struct lua_longjmp *previous;
-  CallInfo *ci;  /* index of call info of active function that set protection */
-  StkId top;  /* top stack when protection was set */
   jmp_buf b;
-  int allowhooks;  /* `allowhook' state when protection was set */
   volatile int status;  /* error code */
-  TObject *err;  /* error messages (start of `ud') */
 };
 
 
-static void pusherrormsg (lua_State *L, int status, TObject *err) {
-  setobj(L->top++, &err[0]);
-  if (status == LUA_ERRRUN)
-    setobj(L->top++, &err[1]);
+static void seterrorobj (lua_State *L, int errcode) {
+  switch (errcode) {
+    case LUA_ERRMEM: {
+      setsvalue(L->top, luaS_new(L, MEMERRMSG));
+      break;
+    }
+    case LUA_ERRERR: {
+      setsvalue(L->top, luaS_new(L, "error in error handling"));
+      break;
+    }
+    case LUA_ERRSYNTAX:
+    case LUA_ERRRUN: {
+      return;  /* error message already on top */
+    }
+  }
+  L->top++;
+}
+
+
+void luaD_throw (lua_State *L, int errcode) {
+  if (errcode == LUA_ERRRUN)
+    luaD_checkstack(L, LUA_MINSTACK);  /* ensure stack space to handle error */
+  luaG_saveallpcs(L);  /* C stack will disapear */
+  if (L->errorJmp) {
+    L->errorJmp->status = errcode;
+    longjmp(L->errorJmp->b, 1);
+  }
+  else {
+    G(L)->panic(L);
+    exit(EXIT_FAILURE);
+  }
+}
+
+
+int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud) {
+  struct lua_longjmp lj;
+  lj.status = 0;
+  lj.previous = L->errorJmp;  /* chain new error handler */
+  L->errorJmp = &lj;
+  if (setjmp(lj.b) == 0)
+    (*f)(L, ud);
+  L->errorJmp = lj.previous;  /* restore old error handler */
+  return lj.status;
+}
+
+
+static void restore_stack_limit (lua_State *L) {
+  L->stack_last = L->stack+L->stacksize-1;
+  if (L->size_ci > LUA_MAXCALLS) {  /* there was an overflow? */
+    int inuse = (L->ci - L->base_ci);
+    if (inuse + 1 < LUA_MAXCALLS)  /* can `undo' overflow? */
+      luaD_reallocCI(L, LUA_MAXCALLS);
+  }
 }
 
 
+void luaD_resetprotection (lua_State *L) {
+  Protection *p;
+  StkId err = L->top - 1;  /* error msg. position (if there is one) */
+  lua_assert(L->number_toreset > 0);
+  p = &L->toreset[--L->number_toreset];
+  L->ci = restoreci(L, p->ci);
+  L->top = restorestack(L, p->top);
+  L->ci->top = L->top + LUA_MINSTACK;
+  setallowhook(L, p->allowhooks);
+  restore_stack_limit(L);
+  setobj(L->top++, err);  /* copy error message to corrected top */
+}
+
+
+/*
+** invalidate all pc pointers from stack part that becomes inactive
+*/
+static void deactivateinfo (lua_State *L, CallInfo *p_ci) {
+  CallInfo *ci;
+  for (ci = L->ci; ci > p_ci; ci--)
+    ci->pc = NULL;
+}
+
+/* }====================================================== */
+
+
 static void correctstack (lua_State *L, TObject *oldstack) {
-  struct lua_longjmp *lj;
   CallInfo *ci;
   UpVal *up;
   L->top = (L->top - oldstack) + L->stack;
-  for (lj = L->errorJmp; lj != NULL; lj = lj->previous)
-    lj->top = (lj->top - oldstack) + L->stack;
   for (up = L->openupval; up != NULL; up = up->next)
     up->v = (up->v - oldstack) + L->stack;
   for (ci = L->base_ci; ci <= L->ci; ci++) {
     ci->base = (ci->base - oldstack) + L->stack;
     ci->top = (ci->top - oldstack) + L->stack;
-    if (isLua(ci) &&  /* is a Lua function... */
-        !(isLua(ci-1) &&  /* and next is not a Lua function... */
-         ci->u.l.pc == (ci-1)->u.l.pc))  /* sharing the same C frame? */
+    if (ci->pc && ci->pc != &luaV_callingmark)  /* function has a frame? */
       *ci->u.l.pb = (*ci->u.l.pb - oldstack) + L->stack;  /* correct frame */
   }
 }
@@ -72,35 +145,17 @@ void luaD_reallocstack (lua_State *L, int newsize) {
   TObject *oldstack = L->stack;
   luaM_reallocvector(L, L->stack, L->stacksize, newsize, TObject);
   L->stacksize = newsize;
-  L->stack_last = L->stack+(newsize-EXTRA_STACK)-1;
+  L->stack_last = L->stack+newsize-1-EXTRA_STACK;
   correctstack(L, oldstack);
 }
 
 
-static void correctCI (lua_State *L, CallInfo *oldci) {
-  struct lua_longjmp *lj;
-  for (lj = L->errorJmp; lj != NULL; lj = lj->previous) {
-    lj->ci = (lj->ci - oldci) + L->base_ci;
-  }
-}
-
-
 void luaD_reallocCI (lua_State *L, int newsize) {
   CallInfo *oldci = L->base_ci;
   luaM_reallocvector(L, L->base_ci, L->size_ci, newsize, CallInfo);
   L->size_ci = newsize;
   L->ci = (L->ci - oldci) + L->base_ci;
   L->end_ci = L->base_ci + L->size_ci;
-  correctCI(L, oldci);
-}
-
-
-static void restore_stack_limit (lua_State *L) {
-  if (L->size_ci > LUA_MAXCALLS) {  /* there was an overflow? */
-    int inuse = (L->ci - L->base_ci);
-    if (inuse + 1 < LUA_MAXCALLS)  /* can `undo' overflow? */
-      luaD_reallocCI(L, LUA_MAXCALLS);
-  }
 }
 
 
@@ -175,7 +230,7 @@ static StkId tryfuncTM (lua_State *L, StkId func) {
   const TObject *tm = luaT_gettmbyobj(L, func, TM_CALL);
   StkId p;
   ptrdiff_t funcr = savestack(L, func);
-  if (ttype(tm) != LUA_TFUNCTION)
+  if (!ttisfunction(tm))
     luaG_typeerror(L, func, "call");
   /* Open a hole inside the stack at `func' */
   for (p = L->top; p > func; p--) setobj(p, p-1);
@@ -189,7 +244,7 @@ static StkId tryfuncTM (lua_State *L, StkId func) {
 StkId luaD_precall (lua_State *L, StkId func) {
   LClosure *cl;
   ptrdiff_t funcr = savestack(L, func);
-  if (ttype(func) != LUA_TFUNCTION) /* `func' is not a function? */
+  if (!ttisfunction(func)) /* `func' is not a function? */
     func = tryfuncTM(L, func);  /* check the `function' tag method */
   if (L->ci + 1 == L->end_ci) luaD_growCI(L);
   cl = &clvalue(func)->l;
@@ -202,7 +257,7 @@ StkId luaD_precall (lua_State *L, StkId func) {
     ci = ++L->ci;  /* now `enter' new function */
     ci->base = restorestack(L, funcr) + 1;
     ci->top = ci->base + p->maxstacksize;
-    ci->savedpc = p->code;  /* starting point */
+    ci->u.l.savedpc = p->code;  /* starting point */
     while (L->top < ci->top)
       setnilvalue(L->top++);
     L->top = ci->top;
@@ -215,7 +270,7 @@ StkId luaD_precall (lua_State *L, StkId func) {
     ci = ++L->ci;  /* now `enter' new function */
     ci->base = restorestack(L, funcr) + 1;
     ci->top = L->top + LUA_MINSTACK;
-    ci->savedpc = NULL;  /* not a Lua function */
+    ci->pc = NULL;  /* not a Lua function */
     if (L->hookmask & LUA_MASKCALL) {
       luaD_callhook(L, LUA_HOOKCALL, -1);
       ci = L->ci;  /* previous call may realocate `ci' */
@@ -274,6 +329,7 @@ void luaD_call (lua_State *L, StkId func, int nResults) {
 LUA_API void lua_cobegin (lua_State *L, int nargs) {
   lua_lock(L);
   luaD_precall(L, L->top - (nargs+1));
+  L->ci->pc = &luaV_callingmark;  /* function is not active (yet) */
   lua_unlock(L);
 }
 
@@ -287,28 +343,24 @@ static void move_results (lua_State *L, TObject *from, TObject *to) {
 }
 
 
-struct ResS {
-  TObject err[2];
-  int numres;
-};
-
 static void resume (lua_State *L, void *ud) {
   StkId firstResult;
   CallInfo *ci = L->ci;
-  if (!isLua(ci)) {  /* not first time? */
+  if (ci->pc == NULL) {  /* not first time? */
     /* finish interrupted execution of `OP_CALL' */
     int nresults;
-    lua_assert(isLua(ci - 1));
-    lua_assert(GET_OPCODE(*((ci-1)->savedpc - 1)) == OP_CALL);
-    nresults = GETARG_C(*((ci-1)->savedpc - 1)) - 1;
+    lua_assert((ci - 1)->pc == &luaV_callingmark);
+    lua_assert(GET_OPCODE(*((ci-1)->u.l.savedpc - 1)) == OP_CALL ||
+               GET_OPCODE(*((ci-1)->u.l.savedpc - 1)) == OP_TAILCALL);
+    nresults = GETARG_C(*((ci-1)->u.l.savedpc - 1)) - 1;
     luaD_poscall(L, nresults, L->top);  /* complete it */
     if (nresults >= 0) L->top = L->ci->top;
   }
   firstResult = luaV_execute(L);
   if (firstResult == NULL)   /* yield? */
-    cast(struct ResS *, ud)->numres = L->ci->u.c.yield_results;
+    *cast(int *, ud) = L->ci->u.c.yield_results;
   else {  /* return */
-    cast(struct ResS *, ud)->numres = L->top - firstResult;
+    *cast(int *, ud) = L->top - firstResult;
     luaD_poscall(L, LUA_MULTRET, firstResult);  /* finalize this coroutine */
   }
 }
@@ -316,7 +368,7 @@ static void resume (lua_State *L, void *ud) {
 
 LUA_API int lua_resume (lua_State *L, lua_State *co) {
   CallInfo *ci;
-  struct ResS ud;
+  int numres;
   int status;
   lua_lock(L);
   ci = co->ci;
@@ -324,11 +376,13 @@ LUA_API int lua_resume (lua_State *L, lua_State *co) {
     luaG_runerror(L, "cannot resume dead thread");
   if (co->errorJmp != NULL)  /* ?? */
     luaG_runerror(L, "cannot resume active thread");
-  status = luaD_runprotected(co, resume, ud.err);
+  status = luaD_rawrunprotected(co, resume, &numres);
   if (status == 0)  
-    move_results(L, co->top - ud.numres, co->top);
-  else
-    pusherrormsg(L, status, ud.err);
+    move_results(L, co->top - numres, co->top);
+  else {
+    setobj(L->top++, co->top - 1);  /* move error message to other stack */
+    co->ci = co->base_ci;  /* `kill' thread */
+  }
   lua_unlock(L);
   return status;
 }
@@ -338,9 +392,9 @@ LUA_API int lua_yield (lua_State *L, int nresults) {
   CallInfo *ci;
   lua_lock(L);
   ci = L->ci;
-  if (!isLua(ci-1))
+  if ((ci-1)->pc == NULL)
     luaG_runerror(L, "cannot yield a C function");
-  lua_assert(!isLua(ci));
+  lua_assert(ci->pc == NULL);  /* current function is not Lua */
   ci->u.c.yield_results = nresults;
   lua_unlock(L);
   return -1;
@@ -351,7 +405,6 @@ LUA_API int lua_yield (lua_State *L, int nresults) {
 ** Execute a protected call.
 */
 struct CallS {  /* data to `f_call' */
-  TObject err[2];
   StkId func;
   int nresults;
 };
@@ -359,6 +412,8 @@ struct CallS {  /* data to `f_call' */
 
 static void f_call (lua_State *L, void *ud) {
   struct CallS *c = cast(struct CallS *, ud);
+  luaM_growvector(L, L->toreset, L->number_toreset, L->size_toreset,
+                     Protection, MAX_INT, "");
   luaD_call(L, c->func, c->nresults);
 }
 
@@ -366,13 +421,24 @@ static void f_call (lua_State *L, void *ud) {
 int luaD_pcall (lua_State *L, int nargs, int nresults) {
   struct CallS c;
   int status;
+  int protectionlevel = L->number_toreset;
+  Protection protection;
+  protection.top = savestack(L, L->top);
+  protection.ci = saveci(L, L->ci);
+  protection.allowhooks = allowhook(L);
   c.func = L->top - (nargs+1);  /* function to be called */
   c.nresults = nresults;
-  status = luaD_runprotected(L, &f_call, c.err);
+  status = luaD_rawrunprotected(L, &f_call, &c);
   if (status != 0) {  /* an error occurred? */
-    L->top -= nargs+1;  /* remove parameters and func from the stack */
-    luaF_close(L, L->top);  /* close eventual pending closures */
-    pusherrormsg(L, status, c.err);
+    /* remove parameters and func from the stack */
+    protection.top = savestack(L, restorestack(L, protection.top) - (nargs+1));
+    /* close eventual pending closures */
+    luaF_close(L, restorestack(L, protection.top));
+    L->ci->top = L->top + LUA_MINSTACK;  /* extra space to handle error */
+    seterrorobj(L, status);
+    deactivateinfo(L, restoreci(L, protection.ci));
+    L->number_toreset = protectionlevel + 1;
+    L->toreset[L->number_toreset - 1] = protection;
   }
   return status;
 }
@@ -382,7 +448,6 @@ int luaD_pcall (lua_State *L, int nargs, int nresults) {
 ** Execute a protected parser.
 */
 struct SParser {  /* data to `f_parser' */
-  TObject err[2];
   ZIO *z;
   int bin;
 };
@@ -401,95 +466,25 @@ int luaD_protectedparser (lua_State *L, ZIO *z, int bin) {
   struct SParser p;
   lu_mem old_blocks;
   int status;
+  ptrdiff_t oldtopr = savestack(L, L->top);  /* save current top */
   p.z = z; p.bin = bin;
   /* before parsing, give a (good) chance to GC */
   if (G(L)->nblocks + G(L)->nblocks/4 >= G(L)->GCthreshold)
     luaC_collectgarbage(L);
   old_blocks = G(L)->nblocks;
-  status = luaD_runprotected(L, f_parser, p.err);
+  status = luaD_rawrunprotected(L, f_parser, &p);
   if (status == 0) {
     /* add new memory to threshold (as it probably will stay) */
     lua_assert(G(L)->nblocks >= old_blocks);
     G(L)->GCthreshold += (G(L)->nblocks - old_blocks);
   }
-  else
-    pusherrormsg(L, status, p.err);
-  return status;
-}
-
-
-
-/*
-** {======================================================
-** Error-recovery functions (based on long jumps)
-** =======================================================
-*/
-
-static void seterrorobj (lua_State *L, int errcode, TObject *m) {
-  switch (errcode) {
-    case LUA_ERRMEM: {
-      if (G(L) != NULL && G(L)->GCthreshold > 0)  /* state is OK? */
-        setsvalue(&m[0], luaS_new(L, MEMERRMSG));
-      break;
-    }
-    case LUA_ERRERR: {
-      setsvalue(&m[0], luaS_new(L, "error in error handling"));
-      break;
-    }
-    case LUA_ERRSYNTAX: {  /* message is on stack top */
-      setobj(&m[0], L->top - 1);
-      break;
-    }
-    case LUA_ERRRUN: {  /* traceback is on stack top */
-      setobj(&m[0], L->top - 2);
-      setobj(&m[1], L->top - 1);
-      break;
-    }
-  }
-}
-
-
-void luaD_throw (lua_State *L, int errcode) {
-  if (L->errorJmp) {
-    seterrorobj(L, errcode, L->errorJmp->err);
-    L->errorJmp->status = errcode;
-    longjmp(L->errorJmp->b, 1);
-  }
-  else {
-    G(L)->panic(L);
-    exit(EXIT_FAILURE);
-  }
-}
-
-
-int luaD_runprotected (lua_State *L, Pfunc f, TObject *ud) {
-  struct lua_longjmp lj;
-  lj.ci = L->ci;
-  lj.top = L->top;
-  lj.allowhooks = allowhook(L);
-  lj.status = 0;
-  lj.err = ud;
-  lj.previous = L->errorJmp;  /* chain new error handler */
-  L->errorJmp = &lj;
-  if (setjmp(lj.b) == 0)
-    (*f)(L, ud);
-  else {  /* an error occurred */
-    L->ci = lj.ci;  /* restore the state */
-    L->top = lj.top;
-    setallowhook(L, lj.allowhooks);
-    restore_stack_limit(L);
+  else {  /* error */
+    StkId oldtop = restorestack(L, oldtopr);
+    seterrorobj(L, status);
+    setobj(oldtop, L->top - 1);  /* copy error message to old top */
+    L->top = oldtop+1;
   }
-  L->errorJmp = lj.previous;  /* restore old error handler */
-  return lj.status;
-}
-
-
-int luaD_isprotected (lua_State *L, CallInfo *ci) {
-  struct lua_longjmp *l;
-  for (l = L->errorJmp; l; l = l->previous)
-    if (l->ci+1 == ci) return 1;
-  return 0;
+  return status;
 }
 
-/* }====================================================== */
 

+ 7 - 4
ldo.h

@@ -1,5 +1,5 @@
 /*
-** $Id: ldo.h,v 1.47 2002/06/18 17:10:43 roberto Exp roberto $
+** $Id: ldo.h,v 1.48 2002/07/08 18:21:33 roberto Exp roberto $
 ** Stack and Call structure of Lua
 ** See Copyright Notice in lua.h
 */
@@ -27,10 +27,14 @@
 #define savestack(L,p)		((char *)(p) - (char *)L->stack)
 #define restorestack(L,n)	((TObject *)((char *)L->stack + (n)))
 
+#define saveci(L,p)		((char *)(p) - (char *)L->base_ci)
+#define restoreci(L,n)		((CallInfo *)((char *)L->base_ci + (n)))
+
 
 /* type of protected functions, to be ran by `runprotected' */
-typedef void (*Pfunc) (lua_State *L, void *v);
+typedef void (*Pfunc) (lua_State *L, void *ud);
 
+void luaD_resetprotection (lua_State *L);
 int luaD_protectedparser (lua_State *L, ZIO *z, int bin);
 void luaD_callhook (lua_State *L, lua_Hookevent event, int line);
 StkId luaD_precall (lua_State *L, StkId func);
@@ -42,8 +46,7 @@ void luaD_reallocstack (lua_State *L, int newsize);
 void luaD_growstack (lua_State *L, int n);
 
 void luaD_throw (lua_State *L, int errcode);
-int luaD_runprotected (lua_State *L, Pfunc f, TObject *ud);
-int luaD_isprotected (lua_State *L, CallInfo *ci);
+int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud);
 
 
 #endif

+ 15 - 8
lstate.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lstate.c,v 1.98 2002/07/08 18:21:33 roberto Exp roberto $
+** $Id: lstate.c,v 1.99 2002/07/16 14:26:56 roberto Exp roberto $
 ** Global State
 ** See Copyright Notice in lua.h
 */
@@ -35,17 +35,19 @@ static int default_panic (lua_State *L) {
 
 
 static void stack_init (lua_State *L, lua_State *OL) {
-  L->stack = luaM_newvector(OL, BASIC_STACK_SIZE, TObject);
-  L->stacksize = BASIC_STACK_SIZE;
+  L->stack = luaM_newvector(OL, BASIC_STACK_SIZE + EXTRA_STACK, TObject);
+  L->stacksize = BASIC_STACK_SIZE + EXTRA_STACK;
   L->top = L->stack;
-  L->stack_last = L->stack+(BASIC_STACK_SIZE-EXTRA_STACK)-1;
+  L->stack_last = L->stack+(L->stacksize - EXTRA_STACK)-1;
   L->base_ci = luaM_newvector(OL, BASIC_CI_SIZE, CallInfo);
   L->ci = L->base_ci;
-  L->ci->savedpc = NULL;
+  L->ci->pc = NULL;  /*  not a Lua function */
   L->ci->base = L->top;
   L->ci->top = L->top + LUA_MINSTACK;
   L->size_ci = BASIC_CI_SIZE;
   L->end_ci = L->base_ci + L->size_ci;
+  L->toreset = luaM_newvector(OL, 2, Protection);
+  L->size_toreset = 2;
 }
 
 
@@ -98,7 +100,12 @@ static void preinit_state (lua_State *L) {
   resethookcount(L);
   L->openupval = NULL;
   L->size_ci = 0;
-  L->base_ci = NULL;
+  L->base_ci = L->ci = NULL;
+  L->toreset = NULL;
+  L->size_toreset = L->number_toreset = 0;
+  setnilvalue(defaultmeta(L));
+  setnilvalue(gt(L));
+  setnilvalue(registry(L));
 }
 
 
@@ -124,13 +131,12 @@ LUA_API lua_State *lua_newthread (lua_State *OL) {
 
 LUA_API lua_State *lua_open (void) {
   lua_State *L;
-  TObject dummy[2];
   L = luaM_new(NULL, lua_State);
   if (L) {  /* allocation OK? */
     preinit_state(L);
     L->l_G = NULL;
     L->next = L->previous = L;
-    if (luaD_runprotected(L, f_luaopen, dummy) != 0) {
+    if (luaD_rawrunprotected(L, f_luaopen, NULL) != 0) {
       /* memory allocation error: free partial state */
       close_state(L);
       L = NULL;
@@ -147,6 +153,7 @@ void luaE_closethread (lua_State *OL, lua_State *L) {
   L->previous->next = L->next;
   L->next->previous = L->previous;
   luaM_freearray(OL, L->base_ci, L->size_ci, CallInfo);
+  luaM_freearray(OL, L->toreset, L->size_toreset, Protection);
   luaM_freearray(OL, L->stack, L->stacksize, TObject);
   luaM_freelem(OL, L);
 }

+ 21 - 10
lstate.h

@@ -1,5 +1,5 @@
 /*
-** $Id: lstate.h,v 1.88 2002/07/08 20:22:08 roberto Exp roberto $
+** $Id: lstate.h,v 1.89 2002/07/16 14:26:56 roberto Exp roberto $
 ** Global State
 ** See Copyright Notice in lua.h
 */
@@ -65,7 +65,7 @@ struct lua_longjmp;  /* defined in ldo.c */
 #define registry(L)	(L->globs + 2)
 
 
-/* space to handle TM calls and other temporary overflows */
+/* extra stack space to handle TM calls and some other extras */
 #define EXTRA_STACK   5
 
 
@@ -88,10 +88,10 @@ typedef struct stringtable {
 typedef struct CallInfo {
   StkId base;  /* base for called function */
   StkId	top;  /* top for this function */
-  const Instruction *savedpc;  /* NULL means not a Lua function */
+  const Instruction **pc;  /* points to `pc' variable in `luaV_execute' */
   union {
     struct {  /* for Lua functions */
-      const Instruction **pc;  /* points to `pc' variable in `luaV_execute' */
+      const Instruction *savedpc;
       StkId *pb;  /* points to `base' variable in `luaV_execute' */
     } l;
     struct {  /* for C functions */
@@ -101,7 +101,15 @@ typedef struct CallInfo {
 } CallInfo;
 
 
-#define isLua(ci)	((ci)->savedpc != NULL)
+/*
+** informations about a `protection' (error recovery points)
+*/
+typedef struct Protection {
+  ptrdiff_t ci;
+  ptrdiff_t top;
+  int allowhooks;
+} Protection;
+
 
 #define ci_func(ci)	(clvalue((ci)->base - 1))
 
@@ -133,22 +141,25 @@ typedef struct global_State {
 struct lua_State {
   LUA_USERSTATE
   StkId top;  /* first free slot in the stack */
+  global_State *l_G;
   CallInfo *ci;  /* call info for current function */
   StkId stack_last;  /* last free slot in the stack */
   StkId stack;  /* stack base */
+  int stacksize;
   CallInfo *end_ci;  /* points after end of ci array*/
   CallInfo *base_ci;  /* array of CallInfo's */
-  global_State *l_G;
+  int size_ci;  /* size of array `base_ci' */
   int hookmask;
   ls_count hookcount;
   lua_Hook hook;
-  TObject globs[NUMGLOBS];  /* registry, table of globals, etc. */
-  struct lua_longjmp *errorJmp;  /* current error recover point */
   UpVal *openupval;  /* list of open upvalues in this stack */
+  struct lua_longjmp *errorJmp;  /* current error recover point */
+  Protection *toreset;  /* array of pending pcall resets */
+  int number_toreset;
+  int size_toreset;
   lua_State *next;  /* circular double linked list of states */
   lua_State *previous;
-  int stacksize;
-  int size_ci;  /* size of array `base_ci' */
+  TObject globs[NUMGLOBS];  /* registry, table of globals, etc. */
 };
 
 

+ 1 - 2
luadebug.h

@@ -1,5 +1,5 @@
 /*
-** $Id: luadebug.h,v 1.29 2002/07/08 18:21:33 roberto Exp roberto $
+** $Id: luadebug.h,v 1.30 2002/07/08 20:22:08 roberto Exp $
 ** Debugging API
 ** See Copyright Notice in lua.h
 */
@@ -46,7 +46,6 @@ struct lua_Debug {
   const char *what;	/* (S) `Lua' function, `C' function, Lua `main' */
   const char *source;	/* (S) */
   int currentline;	/* (l) */
-  int isprotected;	/* (c) function was called in protected mode */
   int nups;		/* (u) number of upvalues */
   int linedefined;	/* (S) */
   char short_src[LUA_IDSIZE]; /* (S) */

+ 77 - 73
lvm.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lvm.c,v 1.247 2002/07/16 14:26:56 roberto Exp roberto $
+** $Id: lvm.c,v 1.248 2002/07/17 16:25:13 roberto Exp $
 ** Lua virtual machine
 ** See Copyright Notice in lua.h
 */
@@ -24,6 +24,9 @@
 #include "lvm.h"
 
 
+Instruction const *luaV_callingmark = NULL;
+
+
 /* function to convert a lua_Number to a string */
 #ifndef lua_number2str
 #include <stdio.h>
@@ -46,8 +49,8 @@ static void luaV_checkGC (lua_State *L, StkId top) {
 
 const TObject *luaV_tonumber (const TObject *obj, TObject *n) {
   lua_Number num;
-  if (ttype(obj) == LUA_TNUMBER) return obj;
-  if (ttype(obj) == LUA_TSTRING && luaO_str2d(svalue(obj), &num)) {
+  if (ttisnumber(obj)) return obj;
+  if (ttisstring(obj) && luaO_str2d(svalue(obj), &num)) {
     setnvalue(n, num);
     return n;
   }
@@ -57,7 +60,7 @@ const TObject *luaV_tonumber (const TObject *obj, TObject *n) {
 
 
 int luaV_tostring (lua_State *L, TObject *obj) {
-  if (ttype(obj) != LUA_TNUMBER)
+  if (!ttisnumber(obj))
     return 0;
   else {
     char s[32];  /* 16 digits, sign, point and \0  (+ some extra...) */
@@ -80,16 +83,16 @@ static void traceexec (lua_State *L) {
   if (mask & LUA_MASKLINE) {
     CallInfo *ci = L->ci;
     Proto *p = ci_func(ci)->l.p;
-    int newline = getline(p, pcRel(*ci->u.l.pc, p));
-    if (pcRel(*ci->u.l.pc, p) == 0)  /* tracing may be starting now? */
-      ci->savedpc = *ci->u.l.pc;  /* initialize `savedpc' */
+    int newline = getline(p, pcRel(*ci->pc, p));
+    if (pcRel(*ci->pc, p) == 0)  /* tracing may be starting now? */
+      ci->u.l.savedpc = *ci->pc;  /* initialize `savedpc' */
     /* calls linehook when enters a new line or jumps back (loop) */
-    if (*ci->u.l.pc <= ci->savedpc ||
-        newline != getline(p, pcRel(ci->savedpc, p))) {
+    if (*ci->pc <= ci->u.l.savedpc ||
+        newline != getline(p, pcRel(ci->u.l.savedpc, p))) {
       luaD_callhook(L, LUA_HOOKLINE, newline);
       ci = L->ci;  /* previous call may reallocate `ci' */
     }
-    ci->savedpc = *ci->u.l.pc;
+    ci->u.l.savedpc = *ci->pc;
   }
 }
 
@@ -123,7 +126,7 @@ static const TObject *luaV_index (lua_State *L, const TObject *t,
                                   TObject *key, int loop) {
   const TObject *tm = fasttm(L, hvalue(t)->metatable, TM_INDEX);
   if (tm == NULL) return &luaO_nilobject;  /* no TM */
-  if (ttype(tm) == LUA_TFUNCTION) {
+  if (ttisfunction(tm)) {
     callTMres(L, tm, t, key);
     return L->top;
   }
@@ -133,9 +136,9 @@ static const TObject *luaV_index (lua_State *L, const TObject *t,
 static const TObject *luaV_getnotable (lua_State *L, const TObject *t,
                                        TObject *key, int loop) {
   const TObject *tm = luaT_gettmbyobj(L, t, TM_GETTABLE);
-  if (ttype(tm) == LUA_TNIL)
+  if (ttisnil(tm))
     luaG_typeerror(L, t, "index");
-  if (ttype(tm) == LUA_TFUNCTION) {
+  if (ttisfunction(tm)) {
     callTMres(L, tm, t, key);
     return L->top;
   }
@@ -152,10 +155,10 @@ const TObject *luaV_gettable (lua_State *L, const TObject *t, TObject *key,
                               int loop) {
   if (loop > MAXTAGLOOP)
     luaG_runerror(L, "loop in gettable");
-  if (ttype(t) == LUA_TTABLE) {  /* `t' is a table? */
+  if (ttistable(t)) {  /* `t' is a table? */
     Table *h = hvalue(t);
     const TObject *v = luaH_get(h, key);  /* do a primitive get */
-    if (ttype(v) != LUA_TNIL) return v;
+    if (!ttisnil(v)) return v;
     else return luaV_index(L, t, key, loop+1);
   }
   else return luaV_getnotable(L, t, key, loop+1);
@@ -169,19 +172,19 @@ void luaV_settable (lua_State *L, const TObject *t, TObject *key, StkId val) {
   const TObject *tm;
   int loop = 0;
   do {
-    if (ttype(t) == LUA_TTABLE) {  /* `t' is a table? */
+    if (ttistable(t)) {  /* `t' is a table? */
       Table *h = hvalue(t);
       TObject *oldval = luaH_set(L, h, key); /* do a primitive set */
-      if (ttype(oldval) != LUA_TNIL ||  /* result is no nil? */
+      if (!ttisnil(oldval) ||  /* result is no nil? */
           (tm = fasttm(L, h->metatable, TM_NEWINDEX)) == NULL) { /* or no TM? */
         setobj(oldval, val);
         return;
       }
       /* else will try the tag method */
     }
-    else if (ttype(tm = luaT_gettmbyobj(L, t, TM_SETTABLE)) == LUA_TNIL)
+    else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_SETTABLE)))
       luaG_typeerror(L, t, "index");
-    if (ttype(tm) == LUA_TFUNCTION) {
+    if (ttisfunction(tm)) {
       callTM(L, tm, t, key, val);
       return;
     }
@@ -195,9 +198,9 @@ static int call_binTM (lua_State *L, const TObject *p1, const TObject *p2,
                        TObject *res, TMS event) {
   ptrdiff_t result = savestack(L, res);
   const TObject *tm = luaT_gettmbyobj(L, p1, event);  /* try first operand */
-  if (ttype(tm) == LUA_TNIL)
+  if (ttisnil(tm))
     tm = luaT_gettmbyobj(L, p2, event);  /* try second operand */
-  if (ttype(tm) != LUA_TFUNCTION) return 0;
+  if (!ttisfunction(tm)) return 0;
   callTMres(L, tm, p1, p2);
   res = restorestack(L, result);  /* previous call may change stack */
   setobj(res, L->top);
@@ -230,9 +233,9 @@ static int luaV_strcmp (const TString *ls, const TString *rs) {
 int luaV_lessthan (lua_State *L, const TObject *l, const TObject *r) {
   if (ttype(l) != ttype(r))
     return luaG_ordererror(L, l, r);
-  else if (ttype(l) == LUA_TNUMBER)
+  else if (ttisnumber(l))
     return nvalue(l) < nvalue(r);
-  else if (ttype(l) == LUA_TSTRING)
+  else if (ttisstring(l))
     return luaV_strcmp(tsvalue(l), tsvalue(r)) < 0;
   else if (call_binTM(L, l, r, L->top, TM_LT))
     return !l_isfalse(L->top);
@@ -243,9 +246,9 @@ int luaV_lessthan (lua_State *L, const TObject *l, const TObject *r) {
 static int luaV_lessequal (lua_State *L, const TObject *l, const TObject *r) {
   if (ttype(l) != ttype(r))
     return luaG_ordererror(L, l, r);
-  else if (ttype(l) == LUA_TNUMBER)
+  else if (ttisnumber(l))
     return nvalue(l) <= nvalue(r);
-  else if (ttype(l) == LUA_TSTRING)
+  else if (ttisstring(l))
     return luaV_strcmp(tsvalue(l), tsvalue(r)) <= 0;
   else if (call_binTM(L, l, r, L->top, TM_LE))  /* first try `le' */
     return !l_isfalse(L->top);
@@ -330,7 +333,7 @@ static void Arith (lua_State *L, StkId ra, StkId rb, StkId rc, TMS op) {
         const TObject *f = luaH_getstr(hvalue(registry(L)),
                                        G(L)->tmname[TM_POW]);
         ptrdiff_t res = savestack(L, ra);
-        if (ttype(f) != LUA_TFUNCTION)
+        if (!ttisfunction(f))
           luaG_runerror(L, "`pow' (for `^' operator) is not a function");
         callTMres(L, f, b, c);
         ra = restorestack(L, res);  /* previous call may change stack */
@@ -370,9 +373,9 @@ StkId luaV_execute (lua_State *L) {
   TObject *k;
   const Instruction *pc;
  callentry:  /* entry point when calling new functions */
-  L->ci->u.l.pc = &pc;
   L->ci->u.l.pb = &base;
-  pc = L->ci->savedpc;
+  L->ci->pc = &pc;
+  pc = L->ci->u.l.savedpc;
   if (L->hookmask & LUA_MASKCALL)
     luaD_callhook(L, LUA_HOOKCALL, -1);
  retentry:  /* entry point when returning to old functions */
@@ -382,11 +385,10 @@ StkId luaV_execute (lua_State *L) {
   /* main loop of interpreter */
   for (;;) {
     const Instruction i = *pc++;
-    StkId ra;
+    const StkId ra = RA(i);
     if (L->hookmask >= LUA_MASKLINE &&
         (--L->hookcount == 0 || L->hookmask & LUA_MASKLINE))
-        traceexec(L);
-    ra = RA(i);
+      traceexec(L);
     lua_assert(L->top <= L->stack + L->stacksize && L->top >= L->ci->base);
     lua_assert(L->top == L->ci->top ||
          GET_OPCODE(i) == OP_CALL ||   GET_OPCODE(i) == OP_TAILCALL ||
@@ -420,9 +422,9 @@ StkId luaV_execute (lua_State *L) {
       case OP_GETGLOBAL: {
         StkId rb = KBx(i);
         const TObject *v;
-        lua_assert(ttype(rb) == LUA_TSTRING && ttype(&cl->g) == LUA_TTABLE);
+        lua_assert(ttisstring(rb) && ttistable(&cl->g));
         v = luaH_getstr(hvalue(&cl->g), tsvalue(rb));
-        if (ttype(v) != LUA_TNIL) { setobj(ra, v); }
+        if (!ttisnil(v)) { setobj(ra, v); }
         else
           setobj(RA(i), luaV_index(L, &cl->g, rb, 0));
         break;
@@ -430,9 +432,9 @@ StkId luaV_execute (lua_State *L) {
       case OP_GETTABLE: {
         StkId rb = RB(i);
         TObject *rc = RKC(i);
-        if (ttype(rb) == LUA_TTABLE) {
+        if (ttistable(rb)) {
           const TObject *v = luaH_get(hvalue(rb), rc);
-          if (ttype(v) != LUA_TNIL) { setobj(ra, v); }
+          if (!ttisnil(v)) { setobj(ra, v); }
           else
             setobj(RA(i), luaV_index(L, rb, rc, 0));
         }
@@ -441,7 +443,7 @@ StkId luaV_execute (lua_State *L) {
         break;
       }
       case OP_SETGLOBAL: {
-        lua_assert(ttype(KBx(i)) == LUA_TSTRING && ttype(&cl->g) == LUA_TTABLE);
+        lua_assert(ttisstring(KBx(i)) && ttistable(&cl->g));
         luaV_settable(L, &cl->g, KBx(i), ra);
         break;
       }
@@ -464,11 +466,11 @@ StkId luaV_execute (lua_State *L) {
       case OP_SELF: {
         StkId rb = RB(i);
         TObject *rc = RKC(i);
-        runtime_check(L, ttype(rc) == LUA_TSTRING);
+        runtime_check(L, ttisstring(rc));
         setobj(ra+1, rb);
-        if (ttype(rb) == LUA_TTABLE) {
+        if (ttistable(rb)) {
           const TObject *v = luaH_getstr(hvalue(rb), tsvalue(rc));
-          if (ttype(v) != LUA_TNIL) { setobj(ra, v); }
+          if (!ttisnil(v)) { setobj(ra, v); }
           else
             setobj(RA(i), luaV_index(L, rb, rc, 0));
         }
@@ -479,7 +481,7 @@ StkId luaV_execute (lua_State *L) {
       case OP_ADD: {
         StkId rb = RB(i);
         StkId rc = RKC(i);
-        if (ttype(rb) == LUA_TNUMBER && ttype(rc) == LUA_TNUMBER) {
+        if (ttisnumber(rb) && ttisnumber(rc)) {
           setnvalue(ra, nvalue(rb) + nvalue(rc));
         }
         else
@@ -489,7 +491,7 @@ StkId luaV_execute (lua_State *L) {
       case OP_SUB: {
         StkId rb = RB(i);
         StkId rc = RKC(i);
-        if (ttype(rb) == LUA_TNUMBER && ttype(rc) == LUA_TNUMBER) {
+        if (ttisnumber(rb) && ttisnumber(rc)) {
           setnvalue(ra, nvalue(rb) - nvalue(rc));
         }
         else
@@ -499,7 +501,7 @@ StkId luaV_execute (lua_State *L) {
       case OP_MUL: {
         StkId rb = RB(i);
         StkId rc = RKC(i);
-        if (ttype(rb) == LUA_TNUMBER && ttype(rc) == LUA_TNUMBER) {
+        if (ttisnumber(rb) && ttisnumber(rc)) {
           setnvalue(ra, nvalue(rb) * nvalue(rc));
         }
         else
@@ -509,7 +511,7 @@ StkId luaV_execute (lua_State *L) {
       case OP_DIV: {
         StkId rb = RB(i);
         StkId rc = RKC(i);
-        if (ttype(rb) == LUA_TNUMBER && ttype(rc) == LUA_TNUMBER) {
+        if (ttisnumber(rb) && ttisnumber(rc)) {
           setnvalue(ra, nvalue(rb) / nvalue(rc));
         }
         else
@@ -584,7 +586,8 @@ StkId luaV_execute (lua_State *L) {
         }
         break;
       }
-      case OP_CALL: {
+      case OP_CALL:
+      case OP_TAILCALL: {
         StkId firstResult;
         int b = GETARG_B(i);
         int nresults;
@@ -593,46 +596,47 @@ StkId luaV_execute (lua_State *L) {
         firstResult = luaD_precall(L, ra);
         if (firstResult) {
           if (firstResult > L->top) {  /* yield? */
-            (L->ci-1)->savedpc = pc;
+            (L->ci - 1)->u.l.savedpc = pc;
+            (L->ci - 1)->pc = &luaV_callingmark;
             return NULL;
           }
           /* it was a C function (`precall' called it); adjust results */
           luaD_poscall(L, nresults, firstResult);
           if (nresults >= 0) L->top = L->ci->top;
         }
-        else {  /* it is a Lua function: `call' it */
-          (L->ci-1)->savedpc = pc;
+        else {  /* it is a Lua function */
+          if (GET_OPCODE(i) == OP_CALL) {  /* regular call? */
+            (L->ci-1)->u.l.savedpc = pc;  /* save `pc' to return later */
+            (L->ci-1)->pc = &luaV_callingmark;  /* function is calling */
+          }
+          else {  /* tail call: put new frame in place of previous one */
+            int aux;
+            StkId ra1 = RA(i);  /* `luaD_precall' may change the stack */
+            if (L->openupval) luaF_close(L, base);
+            for (aux = 0; ra1+aux < L->top; aux++)  /* move frame down */
+              setobj(base+aux-1, ra1+aux);
+            (L->ci - 1)->top = L->top = base+aux;  /* correct top */
+            (L->ci - 1)->u.l.savedpc = L->ci->u.l.savedpc;
+            L->ci--;  /* remove previous frame */
+          }
           goto callentry;
         }
         break;
       }
-      case OP_TAILCALL: {
-        int b = GETARG_B(i);
-        if (L->openupval) luaF_close(L, base);
-        if (b != 0) L->top = ra+b;  /* else previous instruction set top */
-        luaD_poscall(L, LUA_MULTRET, ra);  /* move down function and args. */
-        ra = luaD_precall(L, base-1);
-        if (ra == NULL) goto callentry;  /* it is a Lua function */
-        else if (ra > L->top) return NULL;  /* yield??? */
-        else goto ret;
-      }
       case OP_RETURN: {
-        int b;
-        if (L->openupval) luaF_close(L, base);
-        b = GETARG_B(i);
+        CallInfo *ci = L->ci - 1;
+        int b = GETARG_B(i);
         if (b != 0) L->top = ra+b-1;
-        lua_assert(L->ci->u.l.pc == &pc);
-      }
-      ret: {
-        CallInfo *ci;
-        ci = L->ci - 1;
+        lua_assert(L->ci->pc == &pc);
+        if (L->openupval) luaF_close(L, base);
         /* previous function was running `here'? */
-        if (!isLua(ci) || ci->u.l.pc != &pc)
+        if (ci->pc != &luaV_callingmark)
           return ra;  /* no: return */
-        else {  /* yes: continue its execution */
+        else {  /* yes: continue its execution (go through) */
           int nresults;
-          lua_assert(ttype(ci->base-1) == LUA_TFUNCTION);
-          pc = ci->savedpc;
+          lua_assert(ttisfunction(ci->base-1));
+          ci->pc = &pc;  /* function is active again */
+          pc = ci->u.l.savedpc;
           lua_assert(GET_OPCODE(*(pc-1)) == OP_CALL);
           nresults = GETARG_C(*(pc-1)) - 1;
           luaD_poscall(L, nresults, ra);
@@ -644,7 +648,7 @@ StkId luaV_execute (lua_State *L) {
         lua_Number step, index, limit;
         const TObject *plimit = ra+1;
         const TObject *pstep = ra+2;
-        if (ttype(ra) != LUA_TNUMBER)
+        if (!ttisnumber(ra))
           luaG_runerror(L, "`for' initial value must be a number");
         if (!tonumber(plimit, ra+1))
           luaG_runerror(L, "`for' limit must be a number");
@@ -666,12 +670,12 @@ StkId luaV_execute (lua_State *L) {
         L->top = ra+5;
         luaD_call(L, ra+2, GETARG_C(i) + 1);
         L->top = L->ci->top;
-        if (ttype(ra+2) == LUA_TNIL) pc++;  /* skip jump (break loop) */
+        if (ttisnil(ra+2)) pc++;  /* skip jump (break loop) */
         else dojump(pc, GETARG_sBx(*pc) + 1);  /* else jump back */
         break;
       }
       case OP_TFORPREP: {  /* for compatibility only */
-        if (ttype(ra) == LUA_TTABLE) {
+        if (ttistable(ra)) {
           setobj(ra+1, ra);
           setobj(ra, luaH_getstr(hvalue(gt(L)), luaS_new(L, "next")));
         }
@@ -683,7 +687,7 @@ StkId luaV_execute (lua_State *L) {
         int bc;
         int n;
         Table *h;
-        runtime_check(L, ttype(ra) == LUA_TTABLE);
+        runtime_check(L, ttistable(ra));
         h = hvalue(ra);
         bc = GETARG_Bx(i);
         if (GET_OPCODE(i) == OP_SETLIST)

+ 8 - 1
lvm.h

@@ -1,5 +1,5 @@
 /*
-** $Id: lvm.h,v 1.43 2002/06/24 13:08:45 roberto Exp roberto $
+** $Id: lvm.h,v 1.44 2002/07/05 18:27:39 roberto Exp $
 ** Lua virtual machine
 ** See Copyright Notice in lua.h
 */
@@ -22,6 +22,13 @@
 	(ttype(o1) == ttype(o2) && luaV_equalval(L, o1, o2))
 
 
+/*
+** dummy addrees, to mark Lua functions calling other Lua functions (and
+** therefore without a valid `pc'
+*/
+extern Instruction const *luaV_callingmark;
+
+
 int luaV_lessthan (lua_State *L, const TObject *l, const TObject *r);
 int luaV_equalval (lua_State *L, const TObject *t1, const TObject *t2);
 const TObject *luaV_tonumber (const TObject *obj, TObject *n);