ソースを参照

'CallInfo' stack implemented as double-linked list instead of an array

Roberto Ierusalimschy 16 年 前
コミット
4f88418170
10 ファイル変更127 行追加126 行削除
  1. 3 3
      lapi.c
  2. 12 12
      ldebug.c
  3. 21 48
      ldo.c
  4. 1 4
      ldo.h
  5. 19 20
      lgc.c
  6. 47 14
      lstate.c
  7. 8 5
      lstate.h
  8. 7 11
      ltests.c
  9. 2 2
      lua.h
  10. 7 7
      lvm.c

+ 3 - 3
lapi.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lapi.c,v 2.73 2009/03/30 18:39:20 roberto Exp roberto $
+** $Id: lapi.c,v 2.74 2009/04/08 18:04:33 roberto Exp roberto $
 ** Lua API
 ** See Copyright Notice in lua.h
 */
@@ -72,7 +72,7 @@ static TValue *index2adr (lua_State *L, int idx) {
 
 
 static Table *getcurrenv (lua_State *L) {
-  if (L->ci == L->base_ci)  /* no enclosing function? */
+  if (L->ci->previous == NULL)  /* no enclosing function? */
     return hvalue(gt(L));  /* use global table as environment */
   else {
     Closure *func = curr_func(L);
@@ -185,7 +185,7 @@ LUA_API void lua_replace (lua_State *L, int idx) {
   StkId o;
   lua_lock(L);
   /* explicit test for incompatible code */
-  if (idx == LUA_ENVIRONINDEX && L->ci == L->base_ci)
+  if (idx == LUA_ENVIRONINDEX && L->ci->previous == NULL)
     luaG_runerror(L, "no calling environment");
   api_checknelems(L, 1);
   o = index2adr(L, idx);

+ 12 - 12
ldebug.c

@@ -1,5 +1,5 @@
 /*
-** $Id: ldebug.c,v 2.44 2009/03/10 17:14:37 roberto Exp roberto $
+** $Id: ldebug.c,v 2.45 2009/03/26 12:56:38 roberto Exp roberto $
 ** Debug Interface
 ** See Copyright Notice in lua.h
 */
@@ -86,18 +86,18 @@ LUA_API int lua_getstack (lua_State *L, int level, lua_Debug *ar) {
   int status;
   CallInfo *ci;
   lua_lock(L);
-  for (ci = L->ci; level > 0 && ci > L->base_ci; ci--) {
+  for (ci = L->ci; level > 0 && ci != &L->base_ci; ci = ci->previous) {
     level--;
     if (isLua(ci))  /* Lua function? */
       level -= ci->u.l.tailcalls;  /* skip lost tail calls */
   }
-  if (level == 0 && ci > L->base_ci) {  /* level found? */
+  if (level == 0 && ci != &L->base_ci) {  /* level found? */
     status = 1;
-    ar->i_ci = cast_int(ci - L->base_ci);
+    ar->i_ci = ci;
   }
   else if (level < 0) {  /* level is of a lost tail call? */
     status = 1;
-    ar->i_ci = 0;
+    ar->i_ci = NULL;
   }
   else status = 0;  /* no such level */
   lua_unlock(L);
@@ -116,7 +116,7 @@ static const char *findlocal (lua_State *L, CallInfo *ci, int n) {
   if (fp && (name = luaF_getlocalname(fp, n, currentpc(L, ci))) != NULL)
     return name;  /* is a local variable in a Lua function */
   else {
-    StkId limit = (ci == L->ci) ? L->top : (ci+1)->func;
+    StkId limit = (ci == L->ci) ? L->top : ci->next->func;
     if (limit - ci->base >= n && n > 0)  /* is 'n' inside 'ci' stack? */
       return "(*temporary)";
     else
@@ -126,7 +126,7 @@ static const char *findlocal (lua_State *L, CallInfo *ci, int n) {
 
 
 LUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n) {
-  CallInfo *ci = L->base_ci + ar->i_ci;
+  CallInfo *ci = ar->i_ci;
   const char *name = findlocal(L, ci, n);
   lua_lock(L);
   if (name) {
@@ -139,7 +139,7 @@ LUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n) {
 
 
 LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n) {
-  CallInfo *ci = L->base_ci + ar->i_ci;
+  CallInfo *ci = ar->i_ci;
   const char *name = findlocal(L, ci, n);
   lua_lock(L);
   if (name)
@@ -246,8 +246,8 @@ LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar) {
     f = clvalue(func);
     L->top--;  /* pop function */
   }
-  else if (ar->i_ci != 0) {  /* no tail call? */
-    ci = L->base_ci + ar->i_ci;
+  else if (ar->i_ci != NULL) {  /* no tail call? */
+    ci = ar->i_ci;
     lua_assert(ttisfunction(ci->func));
     f = clvalue(ci->func);
   }
@@ -525,9 +525,9 @@ static const char *getobjname (lua_State *L, CallInfo *ci, int stackpos,
 static const char *getfuncname (lua_State *L, CallInfo *ci, const char **name) {
   TMS tm = 0;
   Instruction i;
-  if ((isLua(ci) && ci->u.l.tailcalls > 0) || !isLua(ci - 1))
+  if ((isLua(ci) && ci->u.l.tailcalls > 0) || !isLua(ci->previous))
     return NULL;  /* calling function is not Lua (or is unknown) */
-  ci--;  /* calling function */
+  ci = ci->previous;  /* calling function */
   i = ci_func(ci)->l.p->code[currentpc(L, ci)];
   switch (GET_OPCODE(i)) {
     case OP_CALL:

+ 21 - 48
ldo.c

@@ -1,5 +1,5 @@
 /*
-** $Id: ldo.c,v 2.58 2009/04/08 18:04:33 roberto Exp roberto $
+** $Id: ldo.c,v 2.59 2009/04/15 16:53:39 roberto Exp roberto $
 ** Stack and Call structure of Lua
 ** See Copyright Notice in lua.h
 */
@@ -70,12 +70,8 @@ void luaD_seterrorobj (lua_State *L, int errcode, StkId oldtop) {
 
 
 static void restore_stack_limit (lua_State *L) {
-  lua_assert(L->stack_last - L->stack == L->stacksize - EXTRA_STACK - 1);
-  if (L->size_ci > LUAI_MAXCALLS) {  /* there was an overflow? */
-    int inuse = cast_int(L->ci - L->base_ci);
-    if (inuse + 1 < LUAI_MAXCALLS)  /* can `undo' overflow? */
-      luaD_reallocCI(L, LUAI_MAXCALLS);
-  }
+  if (L->nci >= LUAI_MAXCALLS)  /* stack overflow? */
+    luaE_freeCI(L);  /* erase all extras CIs */
 }
 
 
@@ -124,7 +120,7 @@ static void correctstack (lua_State *L, TValue *oldstack) {
   L->top = (L->top - oldstack) + L->stack;
   for (up = L->openupval; up != NULL; up = up->gch.next)
     gco2uv(up)->v = (gco2uv(up)->v - oldstack) + L->stack;
-  for (ci = L->base_ci; ci <= L->ci; ci++) {
+  for (ci = L->ci; ci != NULL; ci = ci->previous) {
     ci->top = (ci->top - oldstack) + L->stack;
     ci->base = (ci->base - oldstack) + L->stack;
     ci->func = (ci->func - oldstack) + L->stack;
@@ -144,15 +140,6 @@ void luaD_reallocstack (lua_State *L, int newsize) {
 }
 
 
-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 - 1;
-}
-
-
 void luaD_growstack (lua_State *L, int n) {
   if (n <= L->stacksize)  /* double size is enough? */
     luaD_reallocstack(L, 2*L->stacksize);
@@ -161,18 +148,6 @@ void luaD_growstack (lua_State *L, int n) {
 }
 
 
-static CallInfo *growCI (lua_State *L) {
-  if (L->size_ci > LUAI_MAXCALLS)  /* overflow while handling overflow? */
-    luaD_throw(L, LUA_ERRERR);
-  else {
-    luaD_reallocCI(L, 2*L->size_ci);
-    if (L->size_ci > LUAI_MAXCALLS)
-      luaG_runerror(L, "stack overflow");
-  }
-  return ++L->ci;
-}
-
-
 void luaD_callhook (lua_State *L, int event, int line) {
   lua_Hook hook = L->hook;
   if (hook && L->allowhook) {
@@ -182,9 +157,9 @@ void luaD_callhook (lua_State *L, int event, int line) {
     ar.event = event;
     ar.currentline = line;
     if (event == LUA_HOOKTAILRET)
-      ar.i_ci = 0;  /* tail call; no debug information about it */
+      ar.i_ci = NULL;  /* tail call; no debug information about it */
     else
-      ar.i_ci = cast_int(L->ci - L->base_ci);
+      ar.i_ci = L->ci;
     luaD_checkstack(L, LUA_MINSTACK);  /* ensure minimum stack size */
     L->ci->top = L->top + LUA_MINSTACK;
     lua_assert(L->ci->top <= L->stack_last);
@@ -235,9 +210,7 @@ static StkId tryfuncTM (lua_State *L, StkId func) {
 
 
 
-#define inc_ci(L) \
-  ((L->ci == L->end_ci) ? growCI(L) : \
-   (condhardstacktests(luaD_reallocCI(L, L->size_ci)), ++L->ci))
+#define next_ci(L) (L->ci = (L->ci->next ? L->ci->next : luaE_extendCI(L)))
 
 
 /*
@@ -265,7 +238,7 @@ int luaD_precall (lua_State *L, StkId func, int nresults) {
       base = adjust_varargs(L, p, nargs);
       func = restorestack(L, funcr);  /* previous call may change the stack */
     }
-    ci = inc_ci(L);  /* now `enter' new function */
+    ci = next_ci(L);  /* now 'enter' new function */
     ci->func = func;
     L->base = ci->base = base;
     ci->top = L->base + p->maxstacksize;
@@ -287,7 +260,7 @@ int luaD_precall (lua_State *L, StkId func, int nresults) {
     CallInfo *ci;
     int n;
     luaD_checkstack(L, LUA_MINSTACK);  /* ensure minimum stack size */
-    ci = inc_ci(L);  /* now `enter' new function */
+    ci = next_ci(L);  /* now 'enter' new function */
     ci->func = restorestack(L, funcr);
     L->base = ci->base = ci->func + 1;
     ci->top = L->top + LUA_MINSTACK;
@@ -318,17 +291,17 @@ static StkId callrethooks (lua_State *L, StkId firstResult) {
 int luaD_poscall (lua_State *L, StkId firstResult) {
   StkId res;
   int wanted, i;
-  CallInfo *ci;
+  CallInfo *ci = L->ci;
   if (L->hookmask & (LUA_MASKRET | LUA_MASKLINE)) {
     if (L->hookmask & LUA_MASKRET)
       firstResult = callrethooks(L, firstResult);
-    L->oldpc = (L->ci - 1)->savedpc;  /* set 'oldpc' for returning function */
+    L->oldpc = L->ci->previous->savedpc;  /* 'oldpc' for returning function */
   }
-  ci = L->ci--;
   res = ci->func;  /* res == final position of 1st result */
-  wanted = (ci - 1)->nresults;
-  L->base = (ci - 1)->base;  /* restore base */
-  L->savedpc = (ci - 1)->savedpc;  /* restore savedpc */
+  L->ci = ci = L->ci->previous;  /* back to caller */
+  wanted = ci->nresults;
+  L->base = ci->base;  /* restore base */
+  L->savedpc = ci->savedpc;  /* restore savedpc */
   /* move results to correct place */
   for (i = wanted; i != 0 && firstResult < L->top; i--)
     setobjs2s(L, res++, firstResult++);
@@ -387,7 +360,7 @@ static void finishCcall (lua_State *L) {
 static void unroll (lua_State *L, void *ud) {
   UNUSED(ud);
   for (;;) {
-    if (L->ci == L->base_ci)  /* stack is empty? */
+    if (L->ci == &L->base_ci)  /* stack is empty? */
       return;  /* coroutine finished normally */
     if (!isLua(L->ci))  /* C function? */
       finishCcall(L);
@@ -403,7 +376,7 @@ static void resume (lua_State *L, void *ud) {
   StkId firstArg = cast(StkId, ud);
   CallInfo *ci = L->ci;
   if (L->status == LUA_OK) {  /* start coroutine? */
-    lua_assert(ci == L->base_ci && firstArg > L->base);
+    lua_assert(ci == &L->base_ci && firstArg > L->base);
     if (!luaD_precall(L, firstArg - 1, LUA_MULTRET))  /* Lua function? */
       luaV_execute(L);  /* call it */
   }
@@ -437,7 +410,7 @@ static int resume_error (lua_State *L, const char *msg) {
 */
 static CallInfo *findpcall (lua_State *L) {
   CallInfo *ci;
-  for (ci = L->ci; ci > L->base_ci; ci--) {  /* search for first pcall */
+  for (ci = L->ci; ci != NULL; ci = ci->previous) {  /* search for a pcall */
     if (ci->callstatus & CIST_YPCALL)
       return ci;
   }
@@ -471,7 +444,7 @@ LUA_API int lua_resume (lua_State *L, int nargs) {
   if (L->status != LUA_YIELD) {
     if (L->status != LUA_OK)
       return resume_error(L, "cannot resume dead coroutine");
-    else if (L->ci != L->base_ci)
+    else if (L->ci != &L->base_ci)
       return resume_error(L, "cannot resume non-suspended coroutine");
   }
   luai_userstateresume(L, nargs);
@@ -515,7 +488,7 @@ LUA_API int lua_yield (lua_State *L, int nresults) {
 int luaD_pcall (lua_State *L, Pfunc func, void *u,
                 ptrdiff_t old_top, ptrdiff_t ef) {
   int status;
-  ptrdiff_t old_ci = saveci(L, L->ci);
+  CallInfo *old_ci = L->ci;
   lu_byte old_allowhooks = L->allowhook;
   unsigned short old_nny = L->nny;
   ptrdiff_t old_errfunc = L->errfunc;
@@ -525,7 +498,7 @@ int luaD_pcall (lua_State *L, Pfunc func, void *u,
     StkId oldtop = restorestack(L, old_top);
     luaF_close(L, oldtop);  /* close possible pending closures */
     luaD_seterrorobj(L, status, oldtop);
-    L->ci = restoreci(L, old_ci);
+    L->ci = old_ci;
     L->base = L->ci->base;
     L->savedpc = L->ci->savedpc;
     L->allowhook = old_allowhooks;

+ 1 - 4
ldo.h

@@ -1,5 +1,5 @@
 /*
-** $Id: ldo.h,v 2.10 2008/08/13 17:02:42 roberto Exp roberto $
+** $Id: ldo.h,v 2.11 2009/03/10 17:14:37 roberto Exp roberto $
 ** Stack and Call structure of Lua
 ** See Copyright Notice in lua.h
 */
@@ -24,9 +24,6 @@
 #define savestack(L,p)		((char *)(p) - (char *)L->stack)
 #define restorestack(L,n)	((TValue *)((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 *ud);

+ 19 - 20
lgc.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lgc.c,v 2.48 2009/02/17 19:47:58 roberto Exp roberto $
+** $Id: lgc.c,v 2.49 2009/03/10 17:14:37 roberto Exp roberto $
 ** Garbage Collector
 ** See Copyright Notice in lua.h
 */
@@ -379,38 +379,34 @@ static void traverseclosure (global_State *g, Closure *cl) {
 }
 
 
-static void checkstacksizes (lua_State *L, StkId max) {
-  /* should not change the stack when  handling overflow or
-     during an emergency gc cycle */
-  if (L->size_ci > LUAI_MAXCALLS || G(L)->gckind == KGC_EMERGENCY)
-    return;  /* do not touch the stacks */
+static void checkstacksize (lua_State *L, StkId max) {
+  /* should not change the stack during an emergency gc cycle */
+  if (G(L)->gckind == KGC_EMERGENCY)
+    return;  /* do not touch the stack */
   else {
-    int ci_used = cast_int(L->ci - L->base_ci) + 1;  /* number of `ci' in use */
     int s_used = cast_int(max - L->stack) + 1;  /* part of stack in use */
-    if (2*ci_used < L->size_ci)
-      luaD_reallocCI(L, 2*ci_used);
     if (2*s_used < (L->stacksize - EXTRA_STACK))
       luaD_reallocstack(L, 2*s_used);
   }
 }
 
 
-static void traversestack (global_State *g, lua_State *l) {
+static void traversestack (global_State *g, lua_State *L) {
   StkId o, lim;
   CallInfo *ci;
-  if (l->stack == NULL || l->base_ci == NULL)
+  if (L->stack == NULL)
     return;  /* stack not completely built yet */
-  markvalue(g, gt(l));
-  lim = l->top;
-  for (ci = l->base_ci; ci <= l->ci; ci++) {
-    lua_assert(ci->top <= l->stack_last);
+  markvalue(g, gt(L));
+  lim = L->top;
+  for (ci = L->ci; ci != NULL; ci = ci->previous) {
+    lua_assert(ci->top <= L->stack_last);
     if (lim < ci->top) lim = ci->top;
   }
-  for (o = l->stack; o < l->top; o++)
+  for (o = L->stack; o < L->top; o++)
     markvalue(g, o);
   for (; o <= lim; o++)
     setnilvalue(o);
-  checkstacksizes(l, lim);
+  checkstacksize(L, lim);
 }
 
 
@@ -445,7 +441,7 @@ static l_mem propagatemark (global_State *g) {
       black2gray(o);
       traversestack(g, th);
       return sizeof(lua_State) + sizeof(TValue) * th->stacksize +
-                                 sizeof(CallInfo) * th->size_ci;
+                                 sizeof(CallInfo) * th->nci;
     }
     case LUA_TPROTO: {
       Proto *p = gco2p(o);
@@ -554,8 +550,11 @@ static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count) {
   global_State *g = G(L);
   int deadmask = otherwhite(g);
   while ((curr = *p) != NULL && count-- > 0) {
-    if (ttisthread(gch(curr)))  /* sweep open upvalues of each thread */
-      sweepwholelist(L, &gco2th(curr)->openupval);
+    if (ttisthread(gch(curr))) {
+      lua_State *L1 = gco2th(curr);
+      sweepwholelist(L, &L1->openupval);  /* sweep open upvalues */
+      luaE_freeCI(L1);  /* free extra CallInfo slots */
+    }
     if ((gch(curr)->marked ^ WHITEBITS) & deadmask) {  /* not dead? */
       lua_assert(!isdead(g, curr) || testbit(gch(curr)->marked, FIXEDBIT));
       makewhite(g, curr);  /* make it white (for next cycle) */

+ 47 - 14
lstate.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lstate.c,v 2.49 2009/02/18 17:20:56 roberto Exp roberto $
+** $Id: lstate.c,v 2.50 2009/03/10 17:14:37 roberto Exp roberto $
 ** Global State
 ** See Copyright Notice in lua.h
 */
@@ -40,12 +40,41 @@ typedef struct LG {
 
 
 
+/*
+** maximum number of nested calls made by error-handling function
+*/
+#define LUAI_EXTRACALLS		10
+
+
+CallInfo *luaE_extendCI (lua_State *L) {
+  CallInfo *ci = luaM_new(L, CallInfo);
+  lua_assert(L->ci->next == NULL);
+  L->ci->next = ci;
+  ci->previous = L->ci;
+  ci->next = NULL;
+  if (++L->nci >= LUAI_MAXCALLS) {
+    if (L->nci == LUAI_MAXCALLS)  /* overflow? */
+      luaG_runerror(L, "stack overflow");
+    if (L->nci >= LUAI_MAXCALLS + LUAI_EXTRACALLS)  /* again? */
+      luaD_throw(L, LUA_ERRERR);  /* error while handling overflow */
+  }
+  return ci;
+}
+
+
+void luaE_freeCI (lua_State *L) {
+  CallInfo *ci = L->ci;
+  CallInfo *next = ci->next;
+  ci->next = NULL;
+  while ((ci = next) != NULL) {
+    next = ci->next;
+    luaM_free(L, ci);
+    L->nci--;
+  }
+}
+
+
 static void stack_init (lua_State *L1, lua_State *L) {
-  /* initialize CallInfo array */
-  L1->base_ci = luaM_newvector(L, BASIC_CI_SIZE, CallInfo);
-  L1->ci = L1->base_ci;
-  L1->size_ci = BASIC_CI_SIZE;
-  L1->end_ci = L1->base_ci + L1->size_ci - 1;
   /* initialize stack array */
   L1->stack = luaM_newvector(L, BASIC_STACK_SIZE + EXTRA_STACK, TValue);
   L1->stacksize = BASIC_STACK_SIZE + EXTRA_STACK;
@@ -53,16 +82,18 @@ static void stack_init (lua_State *L1, lua_State *L) {
   L1->stack_last = L1->stack+(L1->stacksize - EXTRA_STACK)-1;
   /* initialize first ci */
   L1->ci->func = L1->top;
-  setnilvalue(L1->top++);  /* `function' entry for this `ci' */
+  setnilvalue(L1->top++);  /* 'function' entry for this 'ci' */
   L1->base = L1->ci->base = L1->top;
   L1->ci->top = L1->top + LUA_MINSTACK;
   L1->ci->callstatus = 0;
 }
 
 
-static void freestack (lua_State *L, lua_State *L1) {
-  luaM_freearray(L, L1->base_ci, L1->size_ci, CallInfo);
-  luaM_freearray(L, L1->stack, L1->stacksize, TValue);
+static void freestack (lua_State *L) {
+  L->ci = &L->base_ci;  /* reset 'ci' list */
+  luaE_freeCI(L);
+  lua_assert(L->nci == 0);
+  luaM_freearray(L, L->stack, L->stacksize, TValue);
 }
 
 
@@ -94,10 +125,11 @@ static void preinit_state (lua_State *L, global_State *g) {
   L->allowhook = 1;
   resethookcount(L);
   L->openupval = NULL;
-  L->size_ci = 0;
   L->nny = 1;
   L->status = LUA_OK;
-  L->base_ci = L->ci = NULL;
+  L->base_ci.next = L->base_ci.previous = NULL;
+  L->ci = &L->base_ci;
+  L->nci = 0;
   L->savedpc = NULL;
   L->errfunc = 0;
   setnilvalue(gt(L));
@@ -110,7 +142,7 @@ static void close_state (lua_State *L) {
   luaC_freeall(L);  /* collect all objects */
   luaM_freearray(L, G(L)->strt.hash, G(L)->strt.size, TString *);
   luaZ_freebuffer(L, &g->buff);
-  freestack(L, L);
+  freestack(L);
   lua_assert(g->totalbytes == sizeof(LG));
   (*g->frealloc)(g->ud, fromstate(L), state_size(LG), 0);
 }
@@ -142,7 +174,7 @@ void luaE_freethread (lua_State *L, lua_State *L1) {
   luaF_close(L1, L1->stack);  /* close all upvalues for this thread */
   lua_assert(L1->openupval == NULL);
   luai_userstatefree(L1);
-  freestack(L, L1);
+  freestack(L1);
   luaM_freemem(L, fromstate(L1), state_size(lua_State));
 }
 
@@ -211,3 +243,4 @@ LUA_API void lua_close (lua_State *L) {
   close_state(L);
 }
 
+

+ 8 - 5
lstate.h

@@ -1,5 +1,5 @@
 /*
-** $Id: lstate.h,v 2.40 2009/03/23 14:26:12 roberto Exp roberto $
+** $Id: lstate.h,v 2.41 2009/04/08 18:04:33 roberto Exp roberto $
 ** Global State
 ** See Copyright Notice in lua.h
 */
@@ -80,8 +80,9 @@ typedef struct CallInfo {
   StkId base;  /* base for this function */
   StkId func;  /* function index in the stack */
   StkId	top;  /* top for this function */
+  struct CallInfo *previous, *next;  /* dynamic call link */
   const Instruction *savedpc;
-  short nresults;  /* expected number of results from this function */
+  short nresults;  /* expected number of results from a call */
   lu_byte callstatus;
   union {
     struct {  /* only for Lua functions */
@@ -163,14 +164,12 @@ struct lua_State {
   StkId base;  /* base of current function */
   global_State *l_G;
   CallInfo *ci;  /* call info for current function */
+  int nci;  /* number of total CallInfo structures linked */
   const Instruction *savedpc;  /* `savedpc' of current function */
   const Instruction *oldpc;  /* last pc traced */
   StkId stack_last;  /* last free slot in the stack */
   StkId stack;  /* stack base */
-  CallInfo *end_ci;  /* points after end of ci array*/
-  CallInfo *base_ci;  /* array of CallInfo's */
   int stacksize;
-  int size_ci;  /* size of array `base_ci' */
   unsigned short nny;  /* number of non-yieldable calls in stack */
   lu_byte hookmask;
   lu_byte allowhook;
@@ -183,6 +182,7 @@ struct lua_State {
   GCObject *gclist;
   struct lua_longjmp *errorJmp;  /* current error recover point */
   ptrdiff_t errfunc;  /* current error handling function (stack index) */
+  CallInfo base_ci;  /* CallInfo for first level (C calling Lua) */
 };
 
 
@@ -223,6 +223,9 @@ union GCObject {
 
 
 LUAI_FUNC void luaE_freethread (lua_State *L, lua_State *L1);
+LUAI_FUNC CallInfo *luaE_extendCI (lua_State *L);
+LUAI_FUNC void luaE_freeCI (lua_State *L);
+
 
 #endif
 

+ 7 - 11
ltests.c

@@ -1,5 +1,5 @@
 /*
-** $Id: ltests.c,v 2.59 2009/03/03 18:52:36 roberto Exp roberto $
+** $Id: ltests.c,v 2.60 2009/04/14 19:10:17 roberto Exp roberto $
 ** Internal Module for Debugging of the Lua Implementation
 ** See Copyright Notice in lua.h
 */
@@ -296,13 +296,10 @@ static void checkstack (global_State *g, lua_State *L1) {
     lua_assert(!isblack(uvo));  /* open upvalues cannot be black */
   }
   checkliveness(g, gt(L1));
-  if (L1->base_ci) {
-    for (ci = L1->base_ci; ci <= L1->ci; ci++) {
-      lua_assert(ci->top <= L1->stack_last);
-      lua_assert(lua_checkpc(L1, ci));
-    }
+  for (ci = L1->ci; ci != NULL; ci = ci->previous) {
+    lua_assert(ci->top <= L1->stack_last);
+    lua_assert(lua_checkpc(L1, ci));
   }
-  else lua_assert(L1->size_ci == 0);
   if (L1->stack) {
     for (o = L1->stack; o < L1->top; o++)
       checkliveness(g, o);
@@ -356,10 +353,10 @@ printf(">>> %d  %s  %02x\n", g->gcstate, luaT_typenames[gch(o)->tt], gch(o)->mar
 
 
 int lua_checkpc (lua_State *L, pCallInfo ci) {
-  if (ci == L->base_ci || !isLua(ci)) return 1;
+  if (!isLua(ci)) return 1;
   else {
     Proto *p = ci_func(ci)->l.p;
-    if (ci < L->ci)
+    if (ci != L->ci)
       return p->code <= ci->savedpc && ci->savedpc <= p->code + p->sizecode;
     else
       return p->code <= L->savedpc && L->savedpc <= p->code + p->sizecode;
@@ -575,8 +572,7 @@ static int stacklevel (lua_State *L) {
   unsigned long a = 0;
   lua_pushinteger(L, (L->top - L->stack));
   lua_pushinteger(L, (L->stack_last - L->stack));
-  lua_pushinteger(L, (L->ci - L->base_ci));
-  lua_pushinteger(L, (L->end_ci - L->base_ci));
+  lua_pushinteger(L, L->nci);
   lua_pushinteger(L, (unsigned long)&a);
   return 5;
 }

+ 2 - 2
lua.h

@@ -1,5 +1,5 @@
 /*
-** $Id: lua.h,v 1.234 2009/03/23 14:26:12 roberto Exp roberto $
+** $Id: lua.h,v 1.235 2009/04/08 18:04:33 roberto Exp roberto $
 ** Lua - An Extensible Extension Language
 ** Lua.org, PUC-Rio, Brazil (http://www.lua.org)
 ** See Copyright Notice at the end of this file
@@ -367,7 +367,7 @@ struct lua_Debug {
   int lastlinedefined;	/* (S) */
   char short_src[LUA_IDSIZE]; /* (S) */
   /* private part */
-  int i_ci;  /* active function */
+  struct CallInfo *i_ci;  /* active function */
 };
 
 /* }====================================================================== */

+ 7 - 7
lvm.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lvm.c,v 2.83 2009/03/04 13:32:29 roberto Exp roberto $
+** $Id: lvm.c,v 2.84 2009/03/10 17:14:37 roberto Exp roberto $
 ** Lua virtual machine
 ** See Copyright Notice in lua.h
 */
@@ -663,19 +663,19 @@ void luaV_execute (lua_State *L) {
         }
         else {
           /* tail call: put new frame in place of previous one */
-          CallInfo *ci = L->ci - 1;  /* previous frame */
-          int aux;
+          StkId pfunc = L->ci->func;  /* called function index */
+          CallInfo *ci = L->ci->previous;  /* caller frame */
           StkId func = ci->func;
-          StkId pfunc = (ci+1)->func;  /* previous function index */
+          int aux;
           if (cl->p->sizep > 0) luaF_close(L, ci->base);
-          L->base = ci->base = ci->func + ((ci+1)->base - pfunc);
+          L->base = ci->base = ci->func + (L->ci->base - pfunc);
           for (aux = 0; pfunc+aux < L->top; aux++)  /* move frame down */
             setobjs2s(L, func+aux, pfunc+aux);
           ci->top = L->top = func+aux;  /* correct top */
           lua_assert(L->top == L->base + clvalue(func)->l.p->maxstacksize);
           ci->savedpc = L->savedpc;
           ci->u.l.tailcalls++;  /* one more call lost */
-          L->ci--;  /* remove new frame */
+          L->ci = ci;  /* remove new frame */
           goto reentry;
         }
       }
@@ -684,7 +684,7 @@ void luaV_execute (lua_State *L) {
         if (b != 0) L->top = ra+b-1;
         if (cl->p->sizep > 0) luaF_close(L, base);
         b = luaD_poscall(L, ra);
-        if (!((L->ci + 1)->callstatus & CIST_REENTRY))
+        if (!(L->ci->next->callstatus & CIST_REENTRY))
           return;  /* external invocation: return */
         else {  /* invocation via reentry: continue execution */
           if (b) L->top = L->ci->top;