Sfoglia il codice sorgente

emergency garbage collector (core forces a GC when allocation fails)

Roberto Ierusalimschy 19 anni fa
parent
commit
3ca9af51a4
19 ha cambiato i file con 190 aggiunte e 153 eliminazioni
  1. 12 32
      lapi.c
  2. 4 4
      lapi.h
  3. 10 7
      ldebug.c
  4. 12 9
      ldo.c
  5. 2 2
      ldo.h
  6. 46 30
      lgc.c
  7. 2 2
      lgc.h
  8. 5 2
      llex.c
  9. 19 6
      lmem.c
  10. 6 6
      lobject.c
  11. 16 10
      lparser.c
  12. 15 6
      lstate.c
  13. 2 2
      lstate.h
  14. 4 5
      lstring.c
  15. 6 10
      ltable.c
  16. 3 2
      ltable.h
  17. 13 6
      ltests.c
  18. 12 11
      lvm.c
  19. 1 1
      makefile

+ 12 - 32
lapi.c

@@ -1,5 +1,5 @@
 /*
 /*
-** $Id: lapi.c,v 2.54 2006/06/02 15:34:00 roberto Exp roberto $
+** $Id: lapi.c,v 2.55 2006/06/07 12:37:17 roberto Exp roberto $
 ** Lua API
 ** Lua API
 ** See Copyright Notice in lua.h
 ** See Copyright Notice in lua.h
 */
 */
@@ -42,9 +42,6 @@ const char lua_ident[] =
 
 
 #define api_checkvalidindex(L, i)	api_check(L, (i) != luaO_nilobject)
 #define api_checkvalidindex(L, i)	api_check(L, (i) != luaO_nilobject)
 
 
-#define api_incr_top(L)   {api_check(L, L->top < L->ci->top); L->top++;}
-
-
 
 
 static TValue *index2adr (lua_State *L, int idx) {
 static TValue *index2adr (lua_State *L, int idx) {
   if (idx > 0) {
   if (idx > 0) {
@@ -86,12 +83,6 @@ static Table *getcurrenv (lua_State *L) {
 }
 }
 
 
 
 
-void luaA_pushobject (lua_State *L, const TValue *o) {
-  setobj2s(L, L->top, o);
-  api_incr_top(L);
-}
-
-
 LUA_API int lua_checkstack (lua_State *L, int size) {
 LUA_API int lua_checkstack (lua_State *L, int size) {
   int res;
   int res;
   lua_lock(L);
   lua_lock(L);
@@ -133,19 +124,6 @@ LUA_API lua_CFunction lua_atpanic (lua_State *L, lua_CFunction panicf) {
 }
 }
 
 
 
 
-LUA_API lua_State *lua_newthread (lua_State *L) {
-  lua_State *L1;
-  lua_lock(L);
-  luaC_checkGC(L);
-  L1 = luaE_newthread(L);
-  setthvalue(L, L->top, L1);
-  api_incr_top(L);
-  lua_unlock(L);
-  luai_userstatethread(L, L1);
-  return L1;
-}
-
-
 
 
 /*
 /*
 ** basic stack manipulation
 ** basic stack manipulation
@@ -539,13 +517,12 @@ LUA_API void lua_gettable (lua_State *L, int idx) {
 
 
 LUA_API void lua_getfield (lua_State *L, int idx, const char *k) {
 LUA_API void lua_getfield (lua_State *L, int idx, const char *k) {
   StkId t;
   StkId t;
-  TValue key;
   lua_lock(L);
   lua_lock(L);
   t = index2adr(L, idx);
   t = index2adr(L, idx);
   api_checkvalidindex(L, t);
   api_checkvalidindex(L, t);
-  setsvalue(L, &key, luaS_new(L, k));
-  luaV_gettable(L, t, &key, L->top);
+  setsvalue2s(L, L->top, luaS_new(L, k));
   api_incr_top(L);
   api_incr_top(L);
+  luaV_gettable(L, t, L->top - 1, L->top - 1);
   lua_unlock(L);
   lua_unlock(L);
 }
 }
 
 
@@ -572,10 +549,14 @@ LUA_API void lua_rawgeti (lua_State *L, int idx, int n) {
 
 
 
 
 LUA_API void lua_createtable (lua_State *L, int narray, int nrec) {
 LUA_API void lua_createtable (lua_State *L, int narray, int nrec) {
+  Table *t;
   lua_lock(L);
   lua_lock(L);
   luaC_checkGC(L);
   luaC_checkGC(L);
-  sethvalue(L, L->top, luaH_new(L, narray, nrec));
+  t = luaH_new(L);
+  sethvalue(L, L->top, t);
   api_incr_top(L);
   api_incr_top(L);
+  if (narray > 0 || nrec > 0)
+    luaH_resize(L, t, narray, nrec);
   lua_unlock(L);
   lua_unlock(L);
 }
 }
 
 
@@ -652,14 +633,13 @@ LUA_API void lua_settable (lua_State *L, int idx) {
 
 
 LUA_API void lua_setfield (lua_State *L, int idx, const char *k) {
 LUA_API void lua_setfield (lua_State *L, int idx, const char *k) {
   StkId t;
   StkId t;
-  TValue key;
   lua_lock(L);
   lua_lock(L);
   api_checknelems(L, 1);
   api_checknelems(L, 1);
   t = index2adr(L, idx);
   t = index2adr(L, idx);
   api_checkvalidindex(L, t);
   api_checkvalidindex(L, t);
-  setsvalue(L, &key, luaS_new(L, k));
-  luaV_settable(L, t, &key, L->top - 1);
-  L->top--;  /* pop value */
+  setsvalue2s(L, L->top++, luaS_new(L, k));
+  luaV_settable(L, t, L->top - 1, L->top - 2);
+  L->top -= 2;  /* pop value and key */
   lua_unlock(L);
   lua_unlock(L);
 }
 }
 
 
@@ -907,7 +887,7 @@ LUA_API int lua_gc (lua_State *L, int what, int data) {
       break;
       break;
     }
     }
     case LUA_GCCOLLECT: {
     case LUA_GCCOLLECT: {
-      luaC_fullgc(L);
+      luaC_fullgc(L, 0);
       break;
       break;
     }
     }
     case LUA_GCCOUNT: {
     case LUA_GCCOUNT: {

+ 4 - 4
lapi.h

@@ -1,5 +1,5 @@
 /*
 /*
-** $Id: lapi.h,v 2.1 2003/12/10 12:13:36 roberto Exp roberto $
+** $Id: lapi.h,v 2.2 2005/04/25 19:24:10 roberto Exp roberto $
 ** Auxiliary functions from Lua API
 ** Auxiliary functions from Lua API
 ** See Copyright Notice in lua.h
 ** See Copyright Notice in lua.h
 */
 */
@@ -8,9 +8,9 @@
 #define lapi_h
 #define lapi_h
 
 
 
 
-#include "lobject.h"
+#include "llimits.h"
+#include "lstate.h"
 
 
-
-LUAI_FUNC void luaA_pushobject (lua_State *L, const TValue *o);
+#define api_incr_top(L)   {L->top++; api_check(L, L->top <= L->ci->top);}
 
 
 #endif
 #endif

+ 10 - 7
ldebug.c

@@ -1,5 +1,5 @@
 /*
 /*
-** $Id: ldebug.c,v 2.28 2005/11/01 16:08:52 roberto Exp roberto $
+** $Id: ldebug.c,v 2.29 2005/12/22 16:19:56 roberto Exp roberto $
 ** Debug Interface
 ** Debug Interface
 ** See Copyright Notice in lua.h
 ** See Copyright Notice in lua.h
 */
 */
@@ -128,8 +128,10 @@ 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 = L->base_ci + ar->i_ci;
   const char *name = findlocal(L, ci, n);
   const char *name = findlocal(L, ci, n);
   lua_lock(L);
   lua_lock(L);
-  if (name)
-      luaA_pushobject(L, ci->base + (n - 1));
+  if (name) {
+    setobj2s(L, L->top, ci->base + (n - 1));
+    api_incr_top(L);
+  }
   lua_unlock(L);
   lua_unlock(L);
   return name;
   return name;
 }
 }
@@ -177,16 +179,17 @@ static void info_tailcall (lua_Debug *ar) {
 static void collectvalidlines (lua_State *L, Closure *f) {
 static void collectvalidlines (lua_State *L, Closure *f) {
   if (f == NULL || f->c.isC) {
   if (f == NULL || f->c.isC) {
     setnilvalue(L->top);
     setnilvalue(L->top);
+    incr_top(L);
   }
   }
   else {
   else {
-    Table *t = luaH_new(L, 0, 0);
-    int *lineinfo = f->l.p->lineinfo;
     int i;
     int i;
+    int *lineinfo = f->l.p->lineinfo;
+    Table *t = luaH_new(L);
+    sethvalue(L, L->top, t); 
+    incr_top(L);
     for (i=0; i<f->l.p->sizelineinfo; i++)
     for (i=0; i<f->l.p->sizelineinfo; i++)
       setbvalue(luaH_setnum(L, t, lineinfo[i]), 1);
       setbvalue(luaH_setnum(L, t, lineinfo[i]), 1);
-    sethvalue(L, L->top, t); 
   }
   }
-  incr_top(L);
 }
 }
 
 
 
 

+ 12 - 9
ldo.c

@@ -1,5 +1,5 @@
 /*
 /*
-** $Id: ldo.c,v 2.37 2005/12/22 16:19:56 roberto Exp roberto $
+** $Id: ldo.c,v 2.38 2006/06/05 19:36:14 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
 */
 */
@@ -81,7 +81,7 @@ static void restore_stack_limit (lua_State *L) {
 static void resetstack (lua_State *L, int status) {
 static void resetstack (lua_State *L, int status) {
   L->ci = L->base_ci;
   L->ci = L->base_ci;
   L->base = L->ci->base;
   L->base = L->ci->base;
-  luaF_close(L, L->base);  /* close eventual pending closures */
+  luaF_close(L, L->base);  /* close possible pending closures */
   luaD_seterrorobj(L, status, L->base);
   luaD_seterrorobj(L, status, L->base);
   L->nCcalls = 0;
   L->nCcalls = 0;
   L->allowhook = 1;
   L->allowhook = 1;
@@ -217,11 +217,13 @@ static StkId adjust_varargs (lua_State *L, Proto *p, int actual) {
     int nvar = actual - nfixargs;  /* number of extra arguments */
     int nvar = actual - nfixargs;  /* number of extra arguments */
     lua_assert(p->is_vararg & VARARG_HASARG);
     lua_assert(p->is_vararg & VARARG_HASARG);
     luaC_checkGC(L);
     luaC_checkGC(L);
-    htab = luaH_new(L, nvar, 1);  /* create `arg' table */
+    htab = luaH_new(L);  /* create `arg' table */
+    sethvalue(L, L->top++, htab);
     for (i=0; i<nvar; i++)  /* put extra arguments into `arg' table */
     for (i=0; i<nvar; i++)  /* put extra arguments into `arg' table */
-      setobj2n(L, luaH_setnum(L, htab, i+1), L->top - nvar + i);
+      setobj2n(L, luaH_setnum(L, htab, i+1), L->top - nvar + i - 1);
     /* store counter in field `n' */
     /* store counter in field `n' */
     setnvalue(luaH_setstr(L, htab, luaS_newliteral(L, "n")), cast_num(nvar));
     setnvalue(luaH_setstr(L, htab, luaS_newliteral(L, "n")), cast_num(nvar));
+    L->top--;
   }
   }
 #endif
 #endif
   /* move fixed parameters to final position */
   /* move fixed parameters to final position */
@@ -332,7 +334,7 @@ static StkId callrethooks (lua_State *L, StkId firstResult) {
   ptrdiff_t fr = savestack(L, firstResult);  /* next call may change stack */
   ptrdiff_t fr = savestack(L, firstResult);  /* next call may change stack */
   luaD_callhook(L, LUA_HOOKRET, -1);
   luaD_callhook(L, LUA_HOOKRET, -1);
   if (f_isLua(L->ci)) {  /* Lua function? */
   if (f_isLua(L->ci)) {  /* Lua function? */
-    while (L->ci->tailcalls--)  /* call hook for eventual tail calls */
+    while (L->ci->tailcalls--)  /* call hook for possible tail calls */
       luaD_callhook(L, LUA_HOOKTAILRET, -1);
       luaD_callhook(L, LUA_HOOKTAILRET, -1);
   }
   }
   return restorestack(L, fr);
   return restorestack(L, fr);
@@ -461,7 +463,7 @@ int luaD_pcall (lua_State *L, Pfunc func, void *u,
   status = luaD_rawrunprotected(L, func, u);
   status = luaD_rawrunprotected(L, func, u);
   if (status != 0) {  /* an error occurred? */
   if (status != 0) {  /* an error occurred? */
     StkId oldtop = restorestack(L, old_top);
     StkId oldtop = restorestack(L, old_top);
-    luaF_close(L, oldtop);  /* close eventual pending closures */
+    luaF_close(L, oldtop);  /* close possible pending closures */
     luaD_seterrorobj(L, status, oldtop);
     luaD_seterrorobj(L, status, oldtop);
     L->nCcalls = oldnCcalls;
     L->nCcalls = oldnCcalls;
     L->ci = restoreci(L, old_ci);
     L->ci = restoreci(L, old_ci);
@@ -494,12 +496,13 @@ static void f_parser (lua_State *L, void *ud) {
   luaC_checkGC(L);
   luaC_checkGC(L);
   tf = ((c == LUA_SIGNATURE[0]) ? luaU_undump : luaY_parser)(L, p->z,
   tf = ((c == LUA_SIGNATURE[0]) ? luaU_undump : luaY_parser)(L, p->z,
                                                              &p->buff, p->name);
                                                              &p->buff, p->name);
+  setptvalue2s(L, L->top, tf);
+  incr_top(L);
   cl = luaF_newLclosure(L, tf->nups, hvalue(gt(L)));
   cl = luaF_newLclosure(L, tf->nups, hvalue(gt(L)));
   cl->l.p = tf;
   cl->l.p = tf;
-  for (i = 0; i < tf->nups; i++)  /* initialize eventual upvalues */
+  setclvalue(L, L->top - 1, cl);
+  for (i = 0; i < tf->nups; i++)  /* initialize upvalues */
     cl->l.upvals[i] = luaF_newupval(L);
     cl->l.upvals[i] = luaF_newupval(L);
-  setclvalue(L, L->top, cl);
-  incr_top(L);
 }
 }
 
 
 
 

+ 2 - 2
ldo.h

@@ -1,5 +1,5 @@
 /*
 /*
-** $Id: ldo.h,v 2.6 2005/08/22 19:58:29 roberto Exp roberto $
+** $Id: ldo.h,v 2.7 2005/08/24 16:15:49 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
 */
 */
@@ -19,7 +19,7 @@
   else condhardstacktests(luaD_reallocstack(L, L->stacksize - EXTRA_STACK - 1));
   else condhardstacktests(luaD_reallocstack(L, L->stacksize - EXTRA_STACK - 1));
 
 
 
 
-#define incr_top(L) {luaD_checkstack(L,1); L->top++;}
+#define incr_top(L) {L->top++; luaD_checkstack(L,0);}
 
 
 #define savestack(L,p)		((char *)(p) - (char *)L->stack)
 #define savestack(L,p)		((char *)(p) - (char *)L->stack)
 #define restorestack(L,n)	((TValue *)((char *)L->stack + (n)))
 #define restorestack(L,n)	((TValue *)((char *)L->stack + (n)))

+ 46 - 30
lgc.c

@@ -1,5 +1,5 @@
 /*
 /*
-** $Id: lgc.c,v 2.37 2005/12/22 16:19:56 roberto Exp roberto $
+** $Id: lgc.c,v 2.38 2006/05/24 14:34:06 roberto Exp roberto $
 ** Garbage Collector
 ** Garbage Collector
 ** See Copyright Notice in lua.h
 ** See Copyright Notice in lua.h
 */
 */
@@ -52,7 +52,7 @@
 #define markvalue(g,o) { checkconsistency(o); \
 #define markvalue(g,o) { checkconsistency(o); \
   if (iscollectable(o) && iswhite(gcvalue(o))) reallymarkobject(g,gcvalue(o)); }
   if (iscollectable(o) && iswhite(gcvalue(o))) reallymarkobject(g,gcvalue(o)); }
 
 
-#define markobject(g,t) { if (iswhite(obj2gco(t))) \
+#define markobject(g,t) { if ((t) && iswhite(obj2gco(t))) \
 		reallymarkobject(g, obj2gco(t)); }
 		reallymarkobject(g, obj2gco(t)); }
 
 
 
 
@@ -76,7 +76,7 @@ static void reallymarkobject (global_State *g, GCObject *o) {
     case LUA_TUSERDATA: {
     case LUA_TUSERDATA: {
       Table *mt = gco2u(o)->metatable;
       Table *mt = gco2u(o)->metatable;
       gray2black(o);  /* udata are never gray */
       gray2black(o);  /* udata are never gray */
-      if (mt) markobject(g, mt);
+      markobject(g, mt);
       markobject(g, gco2u(o)->env);
       markobject(g, gco2u(o)->env);
       return;
       return;
     }
     }
@@ -160,8 +160,7 @@ static int traversetable (global_State *g, Table *h) {
   int weakkey = 0;
   int weakkey = 0;
   int weakvalue = 0;
   int weakvalue = 0;
   const TValue *mode;
   const TValue *mode;
-  if (h->metatable)
-    markobject(g, h->metatable);
+  markobject(g, h->metatable);
   mode = gfasttm(g, h->metatable, TM_MODE);
   mode = gfasttm(g, h->metatable, TM_MODE);
   if (mode && ttisstring(mode)) {  /* is there a weak mode? */
   if (mode && ttisstring(mode)) {  /* is there a weak mode? */
     weakkey = (strchr(svalue(mode), 'k') != NULL);
     weakkey = (strchr(svalue(mode), 'k') != NULL);
@@ -209,10 +208,8 @@ static void traverseproto (global_State *g, Proto *f) {
     if (f->upvalues[i])
     if (f->upvalues[i])
       stringmark(f->upvalues[i]);
       stringmark(f->upvalues[i]);
   }
   }
-  for (i=0; i<f->sizep; i++) {  /* mark nested protos */
-    if (f->p[i])
-      markobject(g, f->p[i]);
-  }
+  for (i=0; i<f->sizep; i++)  /* mark nested protos */
+    markobject(g, f->p[i]);
   for (i=0; i<f->sizelocvars; i++) {  /* mark local-variable names */
   for (i=0; i<f->sizelocvars; i++) {  /* mark local-variable names */
     if (f->locvars[i].varname)
     if (f->locvars[i].varname)
       stringmark(f->locvars[i].varname);
       stringmark(f->locvars[i].varname);
@@ -256,6 +253,8 @@ static void checkstacksizes (lua_State *L, StkId max) {
 static void traversestack (global_State *g, lua_State *l) {
 static void traversestack (global_State *g, lua_State *l) {
   StkId o, lim;
   StkId o, lim;
   CallInfo *ci;
   CallInfo *ci;
+  if (l->stack == NULL || l->base_ci == NULL)
+    return;  /* stack not completely built yet */
   markvalue(g, gt(l));
   markvalue(g, gt(l));
   lim = l->top;
   lim = l->top;
   for (ci = l->base_ci; ci <= l->ci; ci++) {
   for (ci = l->base_ci; ci <= l->ci; ci++) {
@@ -266,7 +265,8 @@ static void traversestack (global_State *g, lua_State *l) {
     markvalue(g, o);
     markvalue(g, o);
   for (; o <= lim; o++)
   for (; o <= lim; o++)
     setnilvalue(o);
     setnilvalue(o);
-  checkstacksizes(l, lim);
+  if (!g->emergencygc)  /* cannot change stack in emergency... */
+    checkstacksizes(l, lim);  /* ...(interpreter does not expect that change) */
 }
 }
 
 
 
 
@@ -442,11 +442,9 @@ static void checkSizes (lua_State *L) {
 }
 }
 
 
 
 
-static void GCTM (lua_State *L) {
-  global_State *g = G(L);
+static Udata *udata2finalize (global_State *g) {
   GCObject *o = g->tmudata->gch.next;  /* get first element */
   GCObject *o = g->tmudata->gch.next;  /* get first element */
   Udata *udata = rawgco2u(o);
   Udata *udata = rawgco2u(o);
-  const TValue *tm;
   /* remove udata from `tmudata' */
   /* remove udata from `tmudata' */
   if (o == g->tmudata)  /* last element? */
   if (o == g->tmudata)  /* last element? */
     g->tmudata = NULL;
     g->tmudata = NULL;
@@ -455,7 +453,14 @@ static void GCTM (lua_State *L) {
   udata->uv.next = g->mainthread->next;  /* return it to `root' list */
   udata->uv.next = g->mainthread->next;  /* return it to `root' list */
   g->mainthread->next = o;
   g->mainthread->next = o;
   makewhite(g, o);
   makewhite(g, o);
-  tm = fasttm(L, udata->uv.metatable, TM_GC);
+  return udata;
+}
+
+
+static void GCTM (lua_State *L) {
+  global_State *g = G(L);
+  Udata *udata = udata2finalize(g);
+  const TValue *tm = fasttm(L, udata->uv.metatable, TM_GC);
   if (tm != NULL) {
   if (tm != NULL) {
     lu_byte oldah = L->allowhook;
     lu_byte oldah = L->allowhook;
     lu_mem oldt = g->GCthreshold;
     lu_mem oldt = g->GCthreshold;
@@ -475,8 +480,17 @@ static void GCTM (lua_State *L) {
 ** Call all GC tag methods
 ** Call all GC tag methods
 */
 */
 void luaC_callGCTM (lua_State *L) {
 void luaC_callGCTM (lua_State *L) {
-  while (G(L)->tmudata)
+  global_State *g = G(L);
+  GCObject *last = g->tmudata;
+  GCObject *curr;
+  if (last == NULL) return;  /* empty list? */
+  do {
+    curr = g->tmudata->gch.next;  /* element to be collected */
     GCTM(L);
     GCTM(L);
+  } while (curr != last);  /* go only until original last */
+  /* do not finalize new udata created during previous finalizations  */
+  while (g->tmudata)
+    udata2finalize(g);  /* simply remove them from list */
 }
 }
 
 
 
 
@@ -493,7 +507,7 @@ void luaC_freeall (lua_State *L) {
 static void markmt (global_State *g) {
 static void markmt (global_State *g) {
   int i;
   int i;
   for (i=0; i<NUM_TAGS; i++)
   for (i=0; i<NUM_TAGS; i++)
-    if (g->mt[i]) markobject(g, g->mt[i]);
+    markobject(g, g->mt[i]);
 }
 }
 
 
 
 
@@ -553,6 +567,10 @@ static void atomic (lua_State *L) {
 }
 }
 
 
 
 
+#define correctestimate(g,s)  {lu_mem old = g->totalbytes; s; \
+          lua_assert(old >= g->totalbytes); g->estimate -= old - g->totalbytes;}
+     
+
 static l_mem singlestep (lua_State *L) {
 static l_mem singlestep (lua_State *L) {
   global_State *g = G(L);
   global_State *g = G(L);
   /*lua_checkmemory(L);*/
   /*lua_checkmemory(L);*/
@@ -570,23 +588,15 @@ static l_mem singlestep (lua_State *L) {
       }
       }
     }
     }
     case GCSsweepstring: {
     case GCSsweepstring: {
-      lu_mem old = g->totalbytes;
-      sweepwholelist(L, &g->strt.hash[g->sweepstrgc++]);
+      correctestimate(g, sweepwholelist(L, &g->strt.hash[g->sweepstrgc++]));
       if (g->sweepstrgc >= g->strt.size)  /* nothing more to sweep? */
       if (g->sweepstrgc >= g->strt.size)  /* nothing more to sweep? */
         g->gcstate = GCSsweep;  /* end sweep-string phase */
         g->gcstate = GCSsweep;  /* end sweep-string phase */
-      lua_assert(old >= g->totalbytes);
-      g->estimate -= old - g->totalbytes;
       return GCSWEEPCOST;
       return GCSWEEPCOST;
     }
     }
     case GCSsweep: {
     case GCSsweep: {
-      lu_mem old = g->totalbytes;
-      g->sweepgc = sweeplist(L, g->sweepgc, GCSWEEPMAX);
-      if (*g->sweepgc == NULL) {  /* nothing more to sweep? */
-        checkSizes(L);
+      correctestimate(g, g->sweepgc = sweeplist(L, g->sweepgc, GCSWEEPMAX));
+      if (*g->sweepgc == NULL)  /* nothing more to sweep? */
         g->gcstate = GCSfinalize;  /* end sweep phase */
         g->gcstate = GCSfinalize;  /* end sweep phase */
-      }
-      lua_assert(old >= g->totalbytes);
-      g->estimate -= old - g->totalbytes;
       return GCSWEEPMAX*GCSWEEPCOST;
       return GCSWEEPMAX*GCSWEEPCOST;
     }
     }
     case GCSfinalize: {
     case GCSfinalize: {
@@ -597,6 +607,7 @@ static l_mem singlestep (lua_State *L) {
         return GCFINALIZECOST;
         return GCFINALIZECOST;
       }
       }
       else {
       else {
+        correctestimate(g, checkSizes(L));
         g->gcstate = GCSpause;  /* end collection */
         g->gcstate = GCSpause;  /* end collection */
         g->gcdept = 0;
         g->gcdept = 0;
         return 0;
         return 0;
@@ -610,6 +621,7 @@ static l_mem singlestep (lua_State *L) {
 void luaC_step (lua_State *L) {
 void luaC_step (lua_State *L) {
   global_State *g = G(L);
   global_State *g = G(L);
   l_mem lim = (GCSTEPSIZE/100) * g->gcstepmul;
   l_mem lim = (GCSTEPSIZE/100) * g->gcstepmul;
+  lua_assert(!g->emergencygc);
   if (lim == 0)
   if (lim == 0)
     lim = (MAX_LUMEM-1)/2;  /* no limit */
     lim = (MAX_LUMEM-1)/2;  /* no limit */
   g->gcdept += g->totalbytes - g->GCthreshold;
   g->gcdept += g->totalbytes - g->GCthreshold;
@@ -633,8 +645,10 @@ void luaC_step (lua_State *L) {
 }
 }
 
 
 
 
-void luaC_fullgc (lua_State *L) {
+void luaC_fullgc (lua_State *L, int isemergency) {
+  int stopstate;
   global_State *g = G(L);
   global_State *g = G(L);
+  g->emergencygc = isemergency;
   if (g->gcstate <= GCSpropagate) {
   if (g->gcstate <= GCSpropagate) {
     /* reset sweep marks to sweep all elements (returning them to white) */
     /* reset sweep marks to sweep all elements (returning them to white) */
     g->sweepstrgc = 0;
     g->sweepstrgc = 0;
@@ -652,10 +666,12 @@ void luaC_fullgc (lua_State *L) {
     singlestep(L);
     singlestep(L);
   }
   }
   markroot(L);
   markroot(L);
-  while (g->gcstate != GCSpause) {
+  /* do not run finalizers during emergency GC */
+  stopstate = isemergency ? GCSfinalize : GCSpause;
+  while (g->gcstate != stopstate)
     singlestep(L);
     singlestep(L);
-  }
   setthreshold(g);
   setthreshold(g);
+  g->emergencygc = 0;
 }
 }
 
 
 
 

+ 2 - 2
lgc.h

@@ -1,5 +1,5 @@
 /*
 /*
-** $Id: lgc.h,v 2.14 2005/06/07 18:53:45 roberto Exp roberto $
+** $Id: lgc.h,v 2.15 2005/08/24 16:15:49 roberto Exp roberto $
 ** Garbage Collector
 ** Garbage Collector
 ** See Copyright Notice in lua.h
 ** See Copyright Notice in lua.h
 */
 */
@@ -100,7 +100,7 @@ LUAI_FUNC size_t luaC_separateudata (lua_State *L, int all);
 LUAI_FUNC void luaC_callGCTM (lua_State *L);
 LUAI_FUNC void luaC_callGCTM (lua_State *L);
 LUAI_FUNC void luaC_freeall (lua_State *L);
 LUAI_FUNC void luaC_freeall (lua_State *L);
 LUAI_FUNC void luaC_step (lua_State *L);
 LUAI_FUNC void luaC_step (lua_State *L);
-LUAI_FUNC void luaC_fullgc (lua_State *L);
+LUAI_FUNC void luaC_fullgc (lua_State *L, int isemergency);
 LUAI_FUNC void luaC_link (lua_State *L, GCObject *o, lu_byte tt);
 LUAI_FUNC void luaC_link (lua_State *L, GCObject *o, lu_byte tt);
 LUAI_FUNC void luaC_linkupval (lua_State *L, UpVal *uv);
 LUAI_FUNC void luaC_linkupval (lua_State *L, UpVal *uv);
 LUAI_FUNC void luaC_barrierf (lua_State *L, GCObject *o, GCObject *v);
 LUAI_FUNC void luaC_barrierf (lua_State *L, GCObject *o, GCObject *v);

+ 5 - 2
llex.c

@@ -1,5 +1,5 @@
 /*
 /*
-** $Id: llex.c,v 2.19 2006/02/06 18:28:16 roberto Exp roberto $
+** $Id: llex.c,v 2.20 2006/03/09 18:14:31 roberto Exp roberto $
 ** Lexical Analyzer
 ** Lexical Analyzer
 ** See Copyright Notice in lua.h
 ** See Copyright Notice in lua.h
 */
 */
@@ -116,10 +116,13 @@ void luaX_syntaxerror (LexState *ls, const char *msg) {
 
 
 TString *luaX_newstring (LexState *ls, const char *str, size_t l) {
 TString *luaX_newstring (LexState *ls, const char *str, size_t l) {
   lua_State *L = ls->L;
   lua_State *L = ls->L;
+  TValue *o;  /* entry for `str' */
   TString *ts = luaS_newlstr(L, str, l);
   TString *ts = luaS_newlstr(L, str, l);
-  TValue *o = luaH_setstr(L, ls->fs->h, ts);  /* entry for `str' */
+  setsvalue2s(L, L->top++, ts);  /* anchor string */
+  o = luaH_setstr(L, ls->fs->h, ts);
   if (ttisnil(o))
   if (ttisnil(o))
     setbvalue(o, 1);  /* make sure `str' will not be collected */
     setbvalue(o, 1);  /* make sure `str' will not be collected */
+  L->top--;
   return ts;
   return ts;
 }
 }
 
 

+ 19 - 6
lmem.c

@@ -1,5 +1,5 @@
 /*
 /*
-** $Id: lmem.c,v 1.69 2005/02/23 17:30:22 roberto Exp roberto $
+** $Id: lmem.c,v 1.70 2005/12/26 13:35:47 roberto Exp roberto $
 ** Interface to Memory Manager
 ** Interface to Memory Manager
 ** See Copyright Notice in lua.h
 ** See Copyright Notice in lua.h
 */
 */
@@ -14,6 +14,7 @@
 
 
 #include "ldebug.h"
 #include "ldebug.h"
 #include "ldo.h"
 #include "ldo.h"
+#include "lgc.h"
 #include "lmem.h"
 #include "lmem.h"
 #include "lobject.h"
 #include "lobject.h"
 #include "lstate.h"
 #include "lstate.h"
@@ -74,13 +75,25 @@ void *luaM_toobig (lua_State *L) {
 ** generic allocation routine.
 ** generic allocation routine.
 */
 */
 void *luaM_realloc_ (lua_State *L, void *block, size_t osize, size_t nsize) {
 void *luaM_realloc_ (lua_State *L, void *block, size_t osize, size_t nsize) {
+  void *newblock;
   global_State *g = G(L);
   global_State *g = G(L);
   lua_assert((osize == 0) == (block == NULL));
   lua_assert((osize == 0) == (block == NULL));
-  block = (*g->frealloc)(g->ud, block, osize, nsize);
-  if (block == NULL && nsize > 0)
-    luaD_throw(L, LUA_ERRMEM);
-  lua_assert((nsize == 0) == (block == NULL));
+#if defined(HARDMEMTESTS)
+  if (nsize > osize && g->GCthreshold != MAX_LUMEM)
+    luaC_fullgc(L, 1);  /* force a GC whenever possible */
+#endif
+  newblock = (*g->frealloc)(g->ud, block, osize, nsize);
+  if (newblock == NULL && nsize > 0) {
+    lua_assert(nsize > osize);  /* cannot fail when shrinking a block */
+    if (g->GCthreshold != MAX_LUMEM) {
+      luaC_fullgc(L, 1);  /* try to free some memory... */
+      newblock = (*g->frealloc)(g->ud, block, osize, nsize);  /* try again */
+    }
+    if (newblock == NULL)
+      luaD_throw(L, LUA_ERRMEM);
+  }
+  lua_assert((nsize == 0) == (newblock == NULL));
   g->totalbytes = (g->totalbytes - osize) + nsize;
   g->totalbytes = (g->totalbytes - osize) + nsize;
-  return block;
+  return newblock;
 }
 }
 
 

+ 6 - 6
lobject.c

@@ -1,5 +1,5 @@
 /*
 /*
-** $Id: lobject.c,v 2.21 2006/01/10 12:50:00 roberto Exp roberto $
+** $Id: lobject.c,v 2.22 2006/02/10 17:43:52 roberto Exp roberto $
 ** Some generic functions over Lua objects
 ** Some generic functions over Lua objects
 ** See Copyright Notice in lua.h
 ** See Copyright Notice in lua.h
 */
 */
@@ -34,20 +34,20 @@ const TValue luaO_nilobject_ = {{NULL}, LUA_TNIL};
 */
 */
 int luaO_int2fb (unsigned int x) {
 int luaO_int2fb (unsigned int x) {
   int e = 0;  /* expoent */
   int e = 0;  /* expoent */
-  while (x >= 16) {
+  if (x < 8) return x;
+  while (x >= 0x10) {
     x = (x+1) >> 1;
     x = (x+1) >> 1;
     e++;
     e++;
   }
   }
-  if (x < 8) return x;
-  else return ((e+1) << 3) | (cast_int(x) - 8);
+  return ((e+1) << 3) | (cast_int(x) - 8);
 }
 }
 
 
 
 
 /* converts back */
 /* converts back */
 int luaO_fb2int (int x) {
 int luaO_fb2int (int x) {
-  int e = (x >> 3) & 31;
+  int e = (x >> 3) & 0x1f;
   if (e == 0) return x;
   if (e == 0) return x;
-  else return ((x & 7)+8) << (e - 1);
+  else return ((x & 7) + 8) << (e - 1);
 }
 }
 
 
 
 

+ 16 - 10
lparser.c

@@ -1,5 +1,5 @@
 /*
 /*
-** $Id: lparser.c,v 2.42 2006/06/05 15:57:59 roberto Exp roberto $
+** $Id: lparser.c,v 2.43 2006/06/22 16:12:59 roberto Exp roberto $
 ** Lua Parser
 ** Lua Parser
 ** See Copyright Notice in lua.h
 ** See Copyright Notice in lua.h
 */
 */
@@ -308,7 +308,7 @@ static void leaveblock (FuncState *fs) {
 
 
 
 
 static void pushclosure (LexState *ls, FuncState *func, expdesc *v) {
 static void pushclosure (LexState *ls, FuncState *func, expdesc *v) {
-  FuncState *fs = ls->fs;
+  FuncState *fs = ls->fs->prev;
   Proto *f = fs->f;
   Proto *f = fs->f;
   int oldsize = f->sizep;
   int oldsize = f->sizep;
   int i;
   int i;
@@ -327,8 +327,7 @@ static void pushclosure (LexState *ls, FuncState *func, expdesc *v) {
 
 
 static void open_func (LexState *ls, FuncState *fs) {
 static void open_func (LexState *ls, FuncState *fs) {
   lua_State *L = ls->L;
   lua_State *L = ls->L;
-  Proto *f = luaF_newproto(L);
-  fs->f = f;
+  Proto *f;
   fs->prev = ls->fs;  /* linked list of funcstates */
   fs->prev = ls->fs;  /* linked list of funcstates */
   fs->ls = ls;
   fs->ls = ls;
   fs->L = L;
   fs->L = L;
@@ -342,12 +341,15 @@ static void open_func (LexState *ls, FuncState *fs) {
   fs->nlocvars = 0;
   fs->nlocvars = 0;
   fs->nactvar = 0;
   fs->nactvar = 0;
   fs->bl = NULL;
   fs->bl = NULL;
-  f->source = ls->source;
-  f->maxstacksize = 2;  /* registers 0/1 are always valid */
-  fs->h = luaH_new(L, 0, 0);
-  /* anchor table of constants and prototype (to avoid being collected) */
+  fs->h = luaH_new(L);
+  /* anchor table of constants (to avoid being collected) */
   sethvalue2s(L, L->top, fs->h);
   sethvalue2s(L, L->top, fs->h);
   incr_top(L);
   incr_top(L);
+  f = luaF_newproto(L);
+  fs->f = f;
+  f->source = ls->source;
+  f->maxstacksize = 2;  /* registers 0/1 are always valid */
+  /* anchor prototype (to avoid being collected) */
   setptvalue2s(L, L->top, f);
   setptvalue2s(L, L->top, f);
   incr_top(L);
   incr_top(L);
 }
 }
@@ -383,14 +385,18 @@ static void close_func (LexState *ls) {
 Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, const char *name) {
 Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, const char *name) {
   struct LexState lexstate;
   struct LexState lexstate;
   struct FuncState funcstate;
   struct FuncState funcstate;
+  TString *tname = luaS_new(L, name);
+  setsvalue2s(L, L->top, tname);  /* protect name */
+  incr_top(L);
   lexstate.buff = buff;
   lexstate.buff = buff;
-  luaX_setinput(L, &lexstate, z, luaS_new(L, name));
+  luaX_setinput(L, &lexstate, z, tname);
   open_func(&lexstate, &funcstate);
   open_func(&lexstate, &funcstate);
   funcstate.f->is_vararg = VARARG_ISVARARG;  /* main func. is always vararg */
   funcstate.f->is_vararg = VARARG_ISVARARG;  /* main func. is always vararg */
   luaX_next(&lexstate);  /* read first token */
   luaX_next(&lexstate);  /* read first token */
   chunk(&lexstate);
   chunk(&lexstate);
   check(&lexstate, TK_EOS);
   check(&lexstate, TK_EOS);
   close_func(&lexstate);
   close_func(&lexstate);
+  L->top--;
   lua_assert(funcstate.prev == NULL);
   lua_assert(funcstate.prev == NULL);
   lua_assert(funcstate.f->nups == 0);
   lua_assert(funcstate.f->nups == 0);
   lua_assert(lexstate.fs == NULL);
   lua_assert(lexstate.fs == NULL);
@@ -588,8 +594,8 @@ static void body (LexState *ls, expdesc *e, int needself, int line) {
   chunk(ls);
   chunk(ls);
   new_fs.f->lastlinedefined = ls->linenumber;
   new_fs.f->lastlinedefined = ls->linenumber;
   check_match(ls, TK_END, TK_FUNCTION, line);
   check_match(ls, TK_END, TK_FUNCTION, line);
-  close_func(ls);
   pushclosure(ls, &new_fs, e);
   pushclosure(ls, &new_fs, e);
+  close_func(ls);
 }
 }
 
 
 
 

+ 15 - 6
lstate.c

@@ -1,5 +1,5 @@
 /*
 /*
-** $Id: lstate.c,v 2.35 2005/10/06 20:46:25 roberto Exp roberto $
+** $Id: lstate.c,v 2.36 2006/05/24 14:15:50 roberto Exp roberto $
 ** Global State
 ** Global State
 ** See Copyright Notice in lua.h
 ** See Copyright Notice in lua.h
 */
 */
@@ -12,6 +12,7 @@
 
 
 #include "lua.h"
 #include "lua.h"
 
 
+#include "lapi.h"
 #include "ldebug.h"
 #include "ldebug.h"
 #include "ldo.h"
 #include "ldo.h"
 #include "lfunc.h"
 #include "lfunc.h"
@@ -71,8 +72,8 @@ static void f_luaopen (lua_State *L, void *ud) {
   global_State *g = G(L);
   global_State *g = G(L);
   UNUSED(ud);
   UNUSED(ud);
   stack_init(L, L);  /* init stack */
   stack_init(L, L);  /* init stack */
-  sethvalue(L, gt(L), luaH_new(L, 0, 2));  /* table of globals */
-  sethvalue(L, registry(L), luaH_new(L, 0, 2));  /* registry */
+  sethvalue(L, gt(L), luaH_new(L));  /* table of globals */
+  sethvalue(L, registry(L), luaH_new(L));  /* registry */
   luaS_resize(L, MINSTRTABSIZE);  /* initial size of string table */
   luaS_resize(L, MINSTRTABSIZE);  /* initial size of string table */
   luaT_init(L);
   luaT_init(L);
   luaX_init(L);
   luaX_init(L);
@@ -116,9 +117,14 @@ static void close_state (lua_State *L) {
 }
 }
 
 
 
 
-lua_State *luaE_newthread (lua_State *L) {
-  lua_State *L1 = tostate(luaM_malloc(L, state_size(lua_State)));
+LUA_API lua_State *lua_newthread (lua_State *L) {
+  lua_State *L1;
+  lua_lock(L);
+  luaC_checkGC(L);
+  L1 = tostate(luaM_malloc(L, state_size(lua_State)));
   luaC_link(L, obj2gco(L1), LUA_TTHREAD);
   luaC_link(L, obj2gco(L1), LUA_TTHREAD);
+  setthvalue(L, L->top, L1);
+  api_incr_top(L);
   preinit_state(L1, G(L));
   preinit_state(L1, G(L));
   stack_init(L1, L);  /* init stack */
   stack_init(L1, L);  /* init stack */
   setobj2n(L, gt(L1), gt(L));  /* share table of globals */
   setobj2n(L, gt(L1), gt(L));  /* share table of globals */
@@ -127,6 +133,8 @@ lua_State *luaE_newthread (lua_State *L) {
   L1->hook = L->hook;
   L1->hook = L->hook;
   resethookcount(L1);
   resethookcount(L1);
   lua_assert(iswhite(obj2gco(L1)));
   lua_assert(iswhite(obj2gco(L1)));
+  lua_unlock(L);
+  luai_userstatethread(L, L1);
   return L1;
   return L1;
 }
 }
 
 
@@ -152,6 +160,7 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) {
   L->tt = LUA_TTHREAD;
   L->tt = LUA_TTHREAD;
   g->currentwhite = bit2mask(WHITE0BIT, FIXEDBIT);
   g->currentwhite = bit2mask(WHITE0BIT, FIXEDBIT);
   L->marked = luaC_white(g);
   L->marked = luaC_white(g);
+  g->emergencygc = 0;
   set2bits(L->marked, FIXEDBIT, SFIXEDBIT);
   set2bits(L->marked, FIXEDBIT, SFIXEDBIT);
   preinit_state(L, g);
   preinit_state(L, g);
   g->frealloc = f;
   g->frealloc = f;
@@ -159,7 +168,7 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) {
   g->mainthread = L;
   g->mainthread = L;
   g->uvhead.u.l.prev = &g->uvhead;
   g->uvhead.u.l.prev = &g->uvhead;
   g->uvhead.u.l.next = &g->uvhead;
   g->uvhead.u.l.next = &g->uvhead;
-  g->GCthreshold = 0;  /* mark it as unfinished state */
+  g->GCthreshold = MAX_LUMEM;  /* no GC while building state */
   g->strt.size = 0;
   g->strt.size = 0;
   g->strt.nuse = 0;
   g->strt.nuse = 0;
   g->strt.hash = NULL;
   g->strt.hash = NULL;

+ 2 - 2
lstate.h

@@ -1,5 +1,5 @@
 /*
 /*
-** $Id: lstate.h,v 2.23 2005/07/09 13:22:34 roberto Exp roberto $
+** $Id: lstate.h,v 2.24 2006/02/06 18:27:59 roberto Exp roberto $
 ** Global State
 ** Global State
 ** See Copyright Notice in lua.h
 ** See Copyright Notice in lua.h
 */
 */
@@ -71,6 +71,7 @@ typedef struct global_State {
   void *ud;         /* auxiliary data to `frealloc' */
   void *ud;         /* auxiliary data to `frealloc' */
   lu_byte currentwhite;
   lu_byte currentwhite;
   lu_byte gcstate;  /* state of garbage collector */
   lu_byte gcstate;  /* state of garbage collector */
+  lu_byte emergencygc;  /* true when collect was trigged by alloc error */
   int sweepstrgc;  /* position of sweep in `strt' */
   int sweepstrgc;  /* position of sweep in `strt' */
   GCObject *rootgc;  /* list of all collectable objects */
   GCObject *rootgc;  /* list of all collectable objects */
   GCObject **sweepgc;  /* position of sweep in `rootgc' */
   GCObject **sweepgc;  /* position of sweep in `rootgc' */
@@ -161,7 +162,6 @@ union GCObject {
 #define obj2gco(v)	(cast(GCObject *, (v)))
 #define obj2gco(v)	(cast(GCObject *, (v)))
 
 
 
 
-LUAI_FUNC lua_State *luaE_newthread (lua_State *L);
 LUAI_FUNC void luaE_freethread (lua_State *L, lua_State *L1);
 LUAI_FUNC void luaE_freethread (lua_State *L, lua_State *L1);
 
 
 #endif
 #endif

+ 4 - 5
lstring.c

@@ -1,5 +1,5 @@
 /*
 /*
-** $Id: lstring.c,v 2.7 2005/02/18 12:40:02 roberto Exp roberto $
+** $Id: lstring.c,v 2.8 2005/12/22 16:19:56 roberto Exp roberto $
 ** String table (keeps all strings handled by Lua)
 ** String table (keeps all strings handled by Lua)
 ** See Copyright Notice in lua.h
 ** See Copyright Notice in lua.h
 */
 */
@@ -50,9 +50,11 @@ void luaS_resize (lua_State *L, int newsize) {
 static TString *newlstr (lua_State *L, const char *str, size_t l,
 static TString *newlstr (lua_State *L, const char *str, size_t l,
                                        unsigned int h) {
                                        unsigned int h) {
   TString *ts;
   TString *ts;
-  stringtable *tb;
+  stringtable *tb = &G(L)->strt;
   if (l+1 > (MAX_SIZET - sizeof(TString))/sizeof(char))
   if (l+1 > (MAX_SIZET - sizeof(TString))/sizeof(char))
     luaM_toobig(L);
     luaM_toobig(L);
+  if (tb->nuse >= cast(lu_int32, tb->size) && tb->size <= MAX_INT/2)
+    luaS_resize(L, tb->size*2);  /* too crowded */
   ts = cast(TString *, luaM_malloc(L, (l+1)*sizeof(char)+sizeof(TString)));
   ts = cast(TString *, luaM_malloc(L, (l+1)*sizeof(char)+sizeof(TString)));
   ts->tsv.len = l;
   ts->tsv.len = l;
   ts->tsv.hash = h;
   ts->tsv.hash = h;
@@ -61,13 +63,10 @@ static TString *newlstr (lua_State *L, const char *str, size_t l,
   ts->tsv.reserved = 0;
   ts->tsv.reserved = 0;
   memcpy(ts+1, str, l*sizeof(char));
   memcpy(ts+1, str, l*sizeof(char));
   ((char *)(ts+1))[l] = '\0';  /* ending 0 */
   ((char *)(ts+1))[l] = '\0';  /* ending 0 */
-  tb = &G(L)->strt;
   h = lmod(h, tb->size);
   h = lmod(h, tb->size);
   ts->tsv.next = tb->hash[h];  /* chain new entry */
   ts->tsv.next = tb->hash[h];  /* chain new entry */
   tb->hash[h] = obj2gco(ts);
   tb->hash[h] = obj2gco(ts);
   tb->nuse++;
   tb->nuse++;
-  if (tb->nuse > cast(lu_int32, tb->size) && tb->size <= MAX_INT/2)
-    luaS_resize(L, tb->size*2);  /* too crowded */
   return ts;
   return ts;
 }
 }
 
 

+ 6 - 10
ltable.c

@@ -1,5 +1,5 @@
 /*
 /*
-** $Id: ltable.c,v 2.31 2006/01/10 13:13:06 roberto Exp roberto $
+** $Id: ltable.c,v 2.32 2006/01/18 11:49:02 roberto Exp roberto $
 ** Lua tables (hash)
 ** Lua tables (hash)
 ** See Copyright Notice in lua.h
 ** See Copyright Notice in lua.h
 */
 */
@@ -294,7 +294,7 @@ static void setnodevector (lua_State *L, Table *t, int size) {
 }
 }
 
 
 
 
-static void resize (lua_State *L, Table *t, int nasize, int nhsize) {
+void luaH_resize (lua_State *L, Table *t, int nasize, int nhsize) {
   int i;
   int i;
   int oldasize = t->sizearray;
   int oldasize = t->sizearray;
   int oldhsize = t->lsizenode;
   int oldhsize = t->lsizenode;
@@ -326,7 +326,7 @@ static void resize (lua_State *L, Table *t, int nasize, int nhsize) {
 
 
 void luaH_resizearray (lua_State *L, Table *t, int nasize) {
 void luaH_resizearray (lua_State *L, Table *t, int nasize) {
   int nsize = (t->node == dummynode) ? 0 : sizenode(t);
   int nsize = (t->node == dummynode) ? 0 : sizenode(t);
-  resize(L, t, nasize, nsize);
+  luaH_resize(L, t, nasize, nsize);
 }
 }
 
 
 
 
@@ -345,7 +345,7 @@ static void rehash (lua_State *L, Table *t, const TValue *ek) {
   /* compute new size for array part */
   /* compute new size for array part */
   na = computesizes(nums, &nasize);
   na = computesizes(nums, &nasize);
   /* resize the table to new computed sizes */
   /* resize the table to new computed sizes */
-  resize(L, t, nasize, totaluse - na);
+  luaH_resize(L, t, nasize, totaluse - na);
 }
 }
 
 
 
 
@@ -355,18 +355,14 @@ static void rehash (lua_State *L, Table *t, const TValue *ek) {
 */
 */
 
 
 
 
-Table *luaH_new (lua_State *L, int narray, int nhash) {
+Table *luaH_new (lua_State *L) {
   Table *t = luaM_new(L, Table);
   Table *t = luaM_new(L, Table);
   luaC_link(L, obj2gco(t), LUA_TTABLE);
   luaC_link(L, obj2gco(t), LUA_TTABLE);
   t->metatable = NULL;
   t->metatable = NULL;
   t->flags = cast_byte(~0);
   t->flags = cast_byte(~0);
-  /* temporary values (kept only if some malloc fails) */
   t->array = NULL;
   t->array = NULL;
   t->sizearray = 0;
   t->sizearray = 0;
-  t->lsizenode = 0;
-  t->node = cast(Node *, dummynode);
-  setarrayvector(L, t, narray);
-  setnodevector(L, t, nhash);
+  setnodevector(L, t, 0);
   return t;
   return t;
 }
 }
 
 

+ 3 - 2
ltable.h

@@ -1,5 +1,5 @@
 /*
 /*
-** $Id: ltable.h,v 2.9 2006/01/10 12:51:53 roberto Exp roberto $
+** $Id: ltable.h,v 2.10 2006/01/10 13:13:06 roberto Exp roberto $
 ** Lua tables (hash)
 ** Lua tables (hash)
 ** See Copyright Notice in lua.h
 ** See Copyright Notice in lua.h
 */
 */
@@ -24,7 +24,8 @@ LUAI_FUNC const TValue *luaH_getstr (Table *t, TString *key);
 LUAI_FUNC TValue *luaH_setstr (lua_State *L, Table *t, TString *key);
 LUAI_FUNC TValue *luaH_setstr (lua_State *L, Table *t, TString *key);
 LUAI_FUNC const TValue *luaH_get (Table *t, const TValue *key);
 LUAI_FUNC const TValue *luaH_get (Table *t, const TValue *key);
 LUAI_FUNC TValue *luaH_set (lua_State *L, Table *t, const TValue *key);
 LUAI_FUNC TValue *luaH_set (lua_State *L, Table *t, const TValue *key);
-LUAI_FUNC Table *luaH_new (lua_State *L, int narray, int lnhash);
+LUAI_FUNC Table *luaH_new (lua_State *L);
+LUAI_FUNC void luaH_resize (lua_State *L, Table *t, int nasize, int nhsize);
 LUAI_FUNC void luaH_resizearray (lua_State *L, Table *t, int nasize);
 LUAI_FUNC void luaH_resizearray (lua_State *L, Table *t, int nasize);
 LUAI_FUNC void luaH_free (lua_State *L, Table *t);
 LUAI_FUNC void luaH_free (lua_State *L, Table *t);
 LUAI_FUNC int luaH_next (lua_State *L, Table *t, StkId key);
 LUAI_FUNC int luaH_next (lua_State *L, Table *t, StkId key);

+ 13 - 6
ltests.c

@@ -1,5 +1,5 @@
 /*
 /*
-** $Id: ltests.c,v 2.36 2006/01/10 13:13:06 roberto Exp roberto $
+** $Id: ltests.c,v 2.37 2006/06/05 19:35:57 roberto Exp roberto $
 ** Internal Module for Debugging of the Lua Implementation
 ** Internal Module for Debugging of the Lua Implementation
 ** See Copyright Notice in lua.h
 ** See Copyright Notice in lua.h
 */
 */
@@ -55,6 +55,12 @@ static void setnameval (lua_State *L, const char *name, int val) {
 }
 }
 
 
 
 
+static void pushobject (lua_State *L, const TValue *o) {
+  setobj2s(L, L->top, o);
+  api_incr_top(L);
+}
+
+
 /*
 /*
 ** {======================================================================
 ** {======================================================================
 ** Controlled version for realloc.
 ** Controlled version for realloc.
@@ -108,7 +114,8 @@ static void freeblock (Memcontrol *mc, void *block, size_t size) {
 
 
 void *debug_realloc (void *ud, void *block, size_t oldsize, size_t size) {
 void *debug_realloc (void *ud, void *block, size_t oldsize, size_t size) {
   Memcontrol *mc = cast(Memcontrol *, ud);
   Memcontrol *mc = cast(Memcontrol *, ud);
-  lua_assert(oldsize == 0 || checkblocksize(block, oldsize));
+  lua_assert((oldsize == 0) ? block == NULL :
+                              block && checkblocksize(block, oldsize));
   if (mc->memlimit == 0) {  /* first time? */
   if (mc->memlimit == 0) {  /* first time? */
     char *limit = getenv("MEMLIMIT");  /* initialize memory limit */
     char *limit = getenv("MEMLIMIT");  /* initialize memory limit */
     mc->memlimit = limit ? strtoul(limit, NULL, 10) : ULONG_MAX;
     mc->memlimit = limit ? strtoul(limit, NULL, 10) : ULONG_MAX;
@@ -447,7 +454,7 @@ static int listk (lua_State *L) {
   p = clvalue(obj_at(L, 1))->l.p;
   p = clvalue(obj_at(L, 1))->l.p;
   lua_createtable(L, p->sizek, 0);
   lua_createtable(L, p->sizek, 0);
   for (i=0; i<p->sizek; i++) {
   for (i=0; i<p->sizek; i++) {
-    luaA_pushobject(L, p->k+i);
+    pushobject(L, p->k+i);
     lua_rawseti(L, -2, i+1);
     lua_rawseti(L, -2, i+1);
   }
   }
   return 1;
   return 1;
@@ -573,18 +580,18 @@ static int table_query (lua_State *L) {
   }
   }
   else if (i < t->sizearray) {
   else if (i < t->sizearray) {
     lua_pushinteger(L, i);
     lua_pushinteger(L, i);
-    luaA_pushobject(L, &t->array[i]);
+    pushobject(L, &t->array[i]);
     lua_pushnil(L); 
     lua_pushnil(L); 
   }
   }
   else if ((i -= t->sizearray) < sizenode(t)) {
   else if ((i -= t->sizearray) < sizenode(t)) {
     if (!ttisnil(gval(gnode(t, i))) ||
     if (!ttisnil(gval(gnode(t, i))) ||
         ttisnil(gkey(gnode(t, i))) ||
         ttisnil(gkey(gnode(t, i))) ||
         ttisnumber(gkey(gnode(t, i)))) {
         ttisnumber(gkey(gnode(t, i)))) {
-      luaA_pushobject(L, key2tval(gnode(t, i)));
+      pushobject(L, key2tval(gnode(t, i)));
     }
     }
     else
     else
       lua_pushliteral(L, "<undef>");
       lua_pushliteral(L, "<undef>");
-    luaA_pushobject(L, gval(gnode(t, i)));
+    pushobject(L, gval(gnode(t, i)));
     if (gnext(&t->node[i]))
     if (gnext(&t->node[i]))
       lua_pushinteger(L, gnext(&t->node[i]) - t->node);
       lua_pushinteger(L, gnext(&t->node[i]) - t->node);
     else
     else

+ 12 - 11
lvm.c

@@ -1,5 +1,5 @@
 /*
 /*
-** $Id: lvm.c,v 2.62 2006/01/23 19:51:43 roberto Exp roberto $
+** $Id: lvm.c,v 2.63 2006/06/05 15:58:59 roberto Exp roberto $
 ** Lua virtual machine
 ** Lua virtual machine
 ** See Copyright Notice in lua.h
 ** See Copyright Notice in lua.h
 */
 */
@@ -85,8 +85,8 @@ static void callTMres (lua_State *L, StkId res, const TValue *f,
   setobj2s(L, L->top, f);  /* push function */
   setobj2s(L, L->top, f);  /* push function */
   setobj2s(L, L->top+1, p1);  /* 1st argument */
   setobj2s(L, L->top+1, p1);  /* 1st argument */
   setobj2s(L, L->top+2, p2);  /* 2nd argument */
   setobj2s(L, L->top+2, p2);  /* 2nd argument */
-  luaD_checkstack(L, 3);
   L->top += 3;
   L->top += 3;
+  luaD_checkstack(L, 0);
   luaD_call(L, L->top - 3, 1);
   luaD_call(L, L->top - 3, 1);
   res = restorestack(L, result);
   res = restorestack(L, result);
   L->top--;
   L->top--;
@@ -101,8 +101,8 @@ static void callTM (lua_State *L, const TValue *f, const TValue *p1,
   setobj2s(L, L->top+1, p1);  /* 1st argument */
   setobj2s(L, L->top+1, p1);  /* 1st argument */
   setobj2s(L, L->top+2, p2);  /* 2nd argument */
   setobj2s(L, L->top+2, p2);  /* 2nd argument */
   setobj2s(L, L->top+3, p3);  /* 3th argument */
   setobj2s(L, L->top+3, p3);  /* 3th argument */
-  luaD_checkstack(L, 4);
   L->top += 4;
   L->top += 4;
+  luaD_checkstack(L, 0);
   luaD_call(L, L->top - 4, 0);
   luaD_call(L, L->top - 4, 0);
 }
 }
 
 
@@ -455,9 +455,12 @@ void luaV_execute (lua_State *L, int nexeccalls) {
         continue;
         continue;
       }
       }
       case OP_NEWTABLE: {
       case OP_NEWTABLE: {
-        int b = GETARG_B(i);
-        int c = GETARG_C(i);
-        sethvalue(L, ra, luaH_new(L, luaO_fb2int(b), luaO_fb2int(c)));
+        int asize = luaO_fb2int(GETARG_B(i));
+        int nsize = luaO_fb2int(GETARG_C(i));
+        Table *t = luaH_new(L);
+        sethvalue(L, ra, t);
+        if (asize > 0 || nsize > 0)
+          luaH_resize(L, t, asize, nsize);
         Protect(luaC_checkGC(L));
         Protect(luaC_checkGC(L));
         continue;
         continue;
       }
       }
@@ -695,10 +698,7 @@ void luaV_execute (lua_State *L, int nexeccalls) {
         int c = GETARG_C(i);
         int c = GETARG_C(i);
         int last;
         int last;
         Table *h;
         Table *h;
-        if (n == 0) {
-          n = cast_int(L->top - ra) - 1;
-          L->top = L->ci->top;
-        }
+        if (n == 0) n = cast_int(L->top - ra) - 1;
         if (c == 0) c = cast_int(*pc++);
         if (c == 0) c = cast_int(*pc++);
         runtime_check(L, ttistable(ra));
         runtime_check(L, ttistable(ra));
         h = hvalue(ra);
         h = hvalue(ra);
@@ -710,6 +710,7 @@ void luaV_execute (lua_State *L, int nexeccalls) {
           setobj2t(L, luaH_setnum(L, h, last--), val);
           setobj2t(L, luaH_setnum(L, h, last--), val);
           luaC_barriert(L, h, val);
           luaC_barriert(L, h, val);
         }
         }
+        L->top = L->ci->top;  /* correct top (in case of previous open call) */
         continue;
         continue;
       }
       }
       case OP_CLOSE: {
       case OP_CLOSE: {
@@ -724,6 +725,7 @@ void luaV_execute (lua_State *L, int nexeccalls) {
         nup = p->nups;
         nup = p->nups;
         ncl = luaF_newLclosure(L, nup, cl->env);
         ncl = luaF_newLclosure(L, nup, cl->env);
         ncl->l.p = p;
         ncl->l.p = p;
+        setclvalue(L, ra, ncl);
         for (j=0; j<nup; j++, pc++) {
         for (j=0; j<nup; j++, pc++) {
           if (GET_OPCODE(*pc) == OP_GETUPVAL)
           if (GET_OPCODE(*pc) == OP_GETUPVAL)
             ncl->l.upvals[j] = cl->upvals[GETARG_B(*pc)];
             ncl->l.upvals[j] = cl->upvals[GETARG_B(*pc)];
@@ -732,7 +734,6 @@ void luaV_execute (lua_State *L, int nexeccalls) {
             ncl->l.upvals[j] = luaF_findupval(L, base + GETARG_B(*pc));
             ncl->l.upvals[j] = luaF_findupval(L, base + GETARG_B(*pc));
           }
           }
         }
         }
-        setclvalue(L, ra, ncl);
         Protect(luaC_checkGC(L));
         Protect(luaC_checkGC(L));
         continue;
         continue;
       }
       }

+ 1 - 1
makefile

@@ -9,7 +9,7 @@ CWARNS= -pedantic -Waggregate-return -Wcast-align \
         -Wsign-compare -Wstrict-prototypes -Wundef -Wwrite-strings
         -Wsign-compare -Wstrict-prototypes -Wundef -Wwrite-strings
 # -Wcast-qual
 # -Wcast-qual
 
 
-# -DEXTERNMEMCHECK -DHARDSTACKTESTS
+# -DEXTERNMEMCHECK -DHARDSTACKTESTS -DHARDMEMTESTS
 # -g -DLUA_USER_H='"ltests.h"'
 # -g -DLUA_USER_H='"ltests.h"'
 # -fomit-frame-pointer #-pg -malign-double
 # -fomit-frame-pointer #-pg -malign-double
 TESTS= -g -DLUA_USER_H='"ltests.h"'
 TESTS= -g -DLUA_USER_H='"ltests.h"'