Browse Source

explicit control of size for growing vectors

Roberto Ierusalimschy 24 years ago
parent
commit
8c49e19865
12 changed files with 95 additions and 70 deletions
  1. 6 6
      lapi.c
  2. 11 8
      lcode.c
  3. 2 2
      ldebug.c
  4. 5 5
      lgc.c
  5. 15 10
      lmem.c
  6. 6 6
      lmem.h
  7. 19 12
      lparser.c
  8. 7 1
      lparser.h
  9. 7 5
      lstate.c
  10. 5 3
      lstate.h
  11. 10 10
      ltm.c
  12. 2 2
      ltm.h

+ 6 - 6
lapi.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lapi.c,v 1.111 2000/11/24 17:39:56 roberto Exp roberto $
+** $Id: lapi.c,v 1.112 2000/12/04 18:33:40 roberto Exp roberto $
 ** Lua API
 ** See Copyright Notice in lua.h
 */
@@ -289,7 +289,7 @@ LUA_API void lua_getglobals (lua_State *L) {
 LUA_API int lua_getref (lua_State *L, int ref) {
   if (ref == LUA_REFNIL)
     ttype(L->top) = LUA_TNIL;
-  else if (0 <= ref && ref < L->refSize &&
+  else if (0 <= ref && ref < L->nref &&
           (L->refArray[ref].st == LOCK || L->refArray[ref].st == HOLD))
     *L->top = L->refArray[ref].o;
   else
@@ -360,10 +360,10 @@ LUA_API int lua_ref (lua_State *L,  int lock) {
       L->refFree = L->refArray[ref].st;
     }
     else {  /* no more free places */
-      luaM_growvector(L, L->refArray, L->refSize, 1, struct Ref,
-                      "reference table overflow", MAX_INT);
+      luaM_growvector(L, L->refArray, L->nref, L->sizeref, struct Ref,
+                      MAX_INT, "reference table overflow");
       L->nblocks += sizeof(struct Ref);
-      ref = L->refSize++;
+      ref = L->nref++;
     }
     L->refArray[ref].o = *(L->top-1);
     L->refArray[ref].st = lock ? LOCK : HOLD;
@@ -430,7 +430,7 @@ LUA_API void lua_settag (lua_State *L, int tag) {
 
 LUA_API void lua_unref (lua_State *L, int ref) {
   if (ref >= 0) {
-    LUA_ASSERT(ref < L->refSize && L->refArray[ref].st < 0, "invalid ref");
+    LUA_ASSERT(ref < L->nref && L->refArray[ref].st < 0, "invalid ref");
     L->refArray[ref].st = L->refFree;
     L->refFree = ref;
   }

+ 11 - 8
lcode.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lcode.c,v 1.52 2000/11/30 18:50:47 roberto Exp roberto $
+** $Id: lcode.c,v 1.53 2000/12/04 18:33:40 roberto Exp roberto $
 ** Code generator for Lua
 ** See Copyright Notice in lua.h
 */
@@ -107,8 +107,8 @@ static int number_constant (FuncState *fs, lua_Number r) {
   while (--c >= lim)
     if (f->knum[c] == r) return c;
   /* not found; create a new entry */
-  luaM_growvector(fs->L, f->knum, f->nknum, 1, lua_Number,
-                  "constant table overflow", MAXARG_U);
+  luaM_growvector(fs->L, f->knum, f->nknum, fs->sizeknum, lua_Number,
+                  MAXARG_U, "constant table overflow");
   c = f->nknum++;
   f->knum[c] = r;
   return c;
@@ -423,10 +423,13 @@ static void codelineinfo (FuncState *fs) {
   Proto *f = fs->f;
   LexState *ls = fs->ls;
   if (ls->lastline > fs->lastline) {
-    luaM_growvector(fs->L, f->lineinfo, f->nlineinfo, 2, int,
-                    "line info overflow", MAX_INT);
-    if (ls->lastline > fs->lastline+1)
+    if (ls->lastline > fs->lastline+1) {
+      luaM_growvector(fs->L, f->lineinfo, f->nlineinfo, fs->sizelineinfo, int,
+                      MAX_INT, "line info overflow");
       f->lineinfo[f->nlineinfo++] = -(ls->lastline - (fs->lastline+1));
+    }
+    luaM_growvector(fs->L, f->lineinfo, f->nlineinfo, fs->sizelineinfo, int,
+                    MAX_INT, "line info overflow");
     f->lineinfo[f->nlineinfo++] = fs->pc;
     fs->lastline = ls->lastline;
   }
@@ -640,8 +643,8 @@ int luaK_code2 (FuncState *fs, OpCode o, int arg1, int arg2) {
   }
   codelineinfo(fs);
   /* put new instruction in code array */
-  luaM_growvector(fs->L, fs->f->code, fs->pc, 1, Instruction,
-                  "code size overflow", MAX_INT);
+  luaM_growvector(fs->L, fs->f->code, fs->pc, fs->sizecode, Instruction,
+                  MAX_INT, "code size overflow");
   fs->f->code[fs->pc] = i;
   return fs->pc++;
 }

+ 2 - 2
ldebug.c

@@ -1,5 +1,5 @@
 /*
-** $Id: ldebug.c,v 1.50 2000/10/30 12:38:50 roberto Exp roberto $
+** $Id: ldebug.c,v 1.51 2000/11/30 18:50:47 roberto Exp roberto $
 ** Debug Interface
 ** See Copyright Notice in lua.h
 */
@@ -210,7 +210,7 @@ static const char *travtagmethods (lua_State *L, const TObject *o) {
     int e;
     for (e=0; e<TM_N; e++) {
       int t;
-      for (t=0; t<=L->last_tag; t++)
+      for (t=0; t<L->ntag; t++)
         if (clvalue(o) == luaT_gettm(L, t, e))
           return luaT_eventname[e];
     }

+ 5 - 5
lgc.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lgc.c,v 1.72 2000/10/26 12:47:05 roberto Exp roberto $
+** $Id: lgc.c,v 1.73 2000/11/24 17:39:56 roberto Exp roberto $
 ** Garbage Collector
 ** See Copyright Notice in lua.h
 */
@@ -56,7 +56,7 @@ static void markstack (lua_State *L, GCState *st) {
 
 static void marklock (lua_State *L, GCState *st) {
   int i;
-  for (i=0; i<L->refSize; i++) {
+  for (i=0; i<L->nref; i++) {
     if (L->refArray[i].st == LOCK)
       markobject(st, &L->refArray[i].o);
   }
@@ -77,7 +77,7 @@ static void marktagmethods (lua_State *L, GCState *st) {
   int e;
   for (e=0; e<TM_N; e++) {
     int t;
-    for (t=0; t<=L->last_tag; t++) {
+    for (t=0; t<L->ntag; t++) {
       Closure *cl = luaT_gettm(L, t, e);
       if (cl) markclosure(st, cl);
     }
@@ -162,7 +162,7 @@ static int hasmark (const TObject *o) {
 #define VALIDLINK(L, st,n)      (NONEXT <= (st) && (st) < (n))
 
 static void invalidaterefs (lua_State *L) {
-  int n = L->refSize;
+  int n = L->nref;
   int i;
   for (i=0; i<n; i++) {
     struct Ref *r = &L->refArray[i];
@@ -314,7 +314,7 @@ static void callgcTMudata (lua_State *L) {
   TObject o;
   ttype(&o) = LUA_TUSERDATA;
   L->GCthreshold = 2*L->nblocks;  /* avoid GC during tag methods */
-  for (tag=L->last_tag; tag>=0; tag--) {  /* for each tag (in reverse order) */
+  for (tag=L->ntag-1; tag>=0; tag--) {  /* for each tag (in reverse order) */
     TString *udata;
     while ((udata = L->TMtable[tag].collected) != NULL) {
       L->TMtable[tag].collected = udata->nexthash;  /* remove it from list */

+ 15 - 10
lmem.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lmem.c,v 1.39 2000/10/30 16:29:59 roberto Exp roberto $
+** $Id: lmem.c,v 1.40 2000/11/24 17:39:56 roberto Exp roberto $
 ** Interface to Memory Manager
 ** See Copyright Notice in lua.h
 */
@@ -116,15 +116,20 @@ static void *debug_realloc (void *block, size_t size) {
 #endif
 
 
-void *luaM_growaux (lua_State *L, void *block, size_t nelems,
-               int inc, size_t size, const char *errormsg, size_t limit) {
-  size_t newn = nelems+inc;
-  if (nelems >= limit-inc) lua_error(L, errormsg);
-  if ((newn ^ nelems) <= nelems ||  /* still the same power-of-2 limit? */
-       (nelems > 0 && newn < MINPOWER2))  /* or block already is MINPOWER2? */
-      return block;  /* do not need to reallocate */
-  else  /* it crossed a power-of-2 boundary; grow to next power */
-    return luaM_realloc(L, block, luaO_power2(newn)*size);
+void *luaM_growaux (lua_State *L, void *block, int *size, int size_elems,
+                    int limit, const char *errormsg) {
+  void *newblock;
+  int newsize = (*size)*2;
+  if (newsize < MINPOWER2)
+    newsize = MINPOWER2;  /* minimum size */
+  else if (*size >= limit/2) {  /* cannot double it? */
+    if (*size < limit - MINPOWER2)  /* try something smaller... */
+      newsize = limit;  /* still have at least MINPOWER2 free places */
+    else lua_error(L, errormsg);
+  }
+  newblock = luaM_realloc(L, block, (luint32)newsize*(luint32)size_elems);
+  *size = newsize;  /* update only when everything else is OK */
+  return newblock;
 }
 
 

+ 6 - 6
lmem.h

@@ -1,5 +1,5 @@
 /*
-** $Id: lmem.h,v 1.16 2000/10/30 16:29:59 roberto Exp roberto $
+** $Id: lmem.h,v 1.17 2000/11/24 17:39:56 roberto Exp roberto $
 ** Interface to Memory Manager
 ** See Copyright Notice in lua.h
 */
@@ -14,17 +14,17 @@
 #include "lua.h"
 
 void *luaM_realloc (lua_State *L, void *oldblock, luint32 size);
-void *luaM_growaux (lua_State *L, void *block, size_t nelems,
-                    int inc, size_t size, const char *errormsg,
-                    size_t limit);
+void *luaM_growaux (lua_State *L, void *block, int *size, int size_elem,
+                    int limit, const char *errormsg);
 
 #define luaM_free(L, b)		luaM_realloc(L, (b), 0)
 #define luaM_malloc(L, t)	luaM_realloc(L, NULL, (t))
 #define luaM_new(L, t)          ((t *)luaM_malloc(L, sizeof(t)))
 #define luaM_newvector(L, n,t)  ((t *)luaM_malloc(L, (n)*(luint32)sizeof(t)))
 
-#define luaM_growvector(L, v,nelems,inc,t,e,l) \
-          ((v)=(t *)luaM_growaux(L, v,nelems,inc,sizeof(t),e,l))
+#define luaM_growvector(L,v,nelems,size,t,limit,e) \
+          if (((nelems)+1) > (size)) \
+            ((v)=(t *)luaM_growaux(L,v,&(size),sizeof(t),limit,e))
 
 #define luaM_reallocvector(L, v,n,t) \
 	((v)=(t *)luaM_realloc(L, v,(n)*(luint32)sizeof(t)))

+ 19 - 12
lparser.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lparser.c,v 1.118 2000/11/30 18:50:47 roberto Exp roberto $
+** $Id: lparser.c,v 1.119 2000/12/04 18:33:40 roberto Exp roberto $
 ** LL(1) Parser and code generator for Lua
 ** See Copyright Notice in lua.h
 */
@@ -121,8 +121,8 @@ static int string_constant (FuncState *fs, TString *s) {
   Proto *f = fs->f;
   int c = s->u.s.constindex;
   if (c >= f->nkstr || f->kstr[c] != s) {
-    luaM_growvector(fs->L, f->kstr, f->nkstr, 1, TString *,
-                    "constant table overflow", MAXARG_U);
+    luaM_growvector(fs->L, f->kstr, f->nkstr, fs->sizekstr, TString *,
+                    MAXARG_U, "constant table overflow");
     c = f->nkstr++;
     f->kstr[c] = s;
     s->u.s.constindex = c;  /* hint for next time */
@@ -152,7 +152,8 @@ static int checkname (LexState *ls) {
 
 static int luaI_registerlocalvar (LexState *ls, TString *varname) {
   Proto *f = ls->fs->f;
-  luaM_growvector(ls->L, f->locvars, f->nlocvars, 1, LocVar, "", MAX_INT);
+  luaM_growvector(ls->L, f->locvars, f->nlocvars, ls->fs->sizelocvars,
+                  LocVar, MAX_INT, "");
   f->locvars[f->nlocvars].varname = varname;
   return f->nlocvars++;
 }
@@ -294,8 +295,8 @@ static void pushclosure (LexState *ls, FuncState *func) {
   int i;
   for (i=0; i<func->nupvalues; i++)
     luaK_tostack(ls, &func->upvalues[i], 1);
-  luaM_growvector(ls->L, f->kproto, f->nkproto, 1, Proto *,
-                  "constant table overflow", MAXARG_A);
+  luaM_growvector(ls->L, f->kproto, f->nkproto, fs->sizekproto, Proto *,
+                  MAXARG_A, "constant table overflow");
   f->kproto[f->nkproto++] = func->f;
   luaK_code2(fs, OP_CLOSURE, f->nkproto-1, func->nupvalues);
 }
@@ -303,21 +304,27 @@ static void pushclosure (LexState *ls, FuncState *func) {
 
 static void open_func (LexState *ls, FuncState *fs) {
   Proto *f = luaF_newproto(ls->L);
+  fs->f = f;
   fs->prev = ls->fs;  /* linked list of funcstates */
   fs->ls = ls;
   fs->L = ls->L;
   ls->fs = fs;
+  fs->pc = 0;
+  fs->lasttarget = 0;
+  fs->jlt = NO_JUMP;
   fs->stacklevel = 0;
+  fs->sizekstr = 0;
+  fs->sizekproto = 0;
+  fs->sizeknum = 0;
+  fs->sizelineinfo = 0;
+  fs->sizecode = 0;
+  fs->sizelocvars = 0;
   fs->nactloc = 0;
   fs->nupvalues = 0;
-  fs->bl = NULL;
-  fs->f = f;
-  f->source = ls->source;
-  fs->pc = 0;
-  fs->lasttarget = 0;
   fs->lastline = 0;
-  fs->jlt = NO_JUMP;
+  fs->bl = NULL;
   f->code = NULL;
+  f->source = ls->source;
   f->maxstacksize = 0;
   f->numparams = 0;  /* default for main chunk */
   f->is_vararg = 0;  /* default for main chunk */

+ 7 - 1
lparser.h

@@ -1,5 +1,5 @@
 /*
-** $Id: lparser.h,v 1.26 2000/10/09 13:47:46 roberto Exp roberto $
+** $Id: lparser.h,v 1.27 2000/11/30 18:50:47 roberto Exp roberto $
 ** LL(1) Parser and code generator for Lua
 ** See Copyright Notice in lua.h
 */
@@ -45,6 +45,12 @@ typedef struct FuncState {
   int lasttarget;   /* `pc' of last `jump target' */
   int jlt;  /* list of jumps to `lasttarget' */
   int stacklevel;  /* number of values on activation register */
+  int sizekstr;  /* size of array `kstr' */
+  int sizekproto;  /* size of array `kproto' */
+  int sizeknum;  /* size of array `knum' */
+  int sizelineinfo;  /* size of array `lineinfo' */
+  int sizecode;  /* size of array `code' */
+  int sizelocvars;  /* size of array `locvars' */
   int nactloc;  /* number of active local variables */
   int nupvalues;  /* number of upvalues */
   int lastline;  /* line where last `lineinfo' was generated */

+ 7 - 5
lstate.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lstate.c,v 1.47 2000/10/26 12:47:05 roberto Exp roberto $
+** $Id: lstate.c,v 1.48 2000/10/30 16:29:59 roberto Exp roberto $
 ** Global State
 ** See Copyright Notice in lua.h
 */
@@ -77,9 +77,11 @@ LUA_API lua_State *lua_open (int stacksize) {
   L->rootcl = NULL;
   L->roottable = NULL;
   L->TMtable = NULL;
-  L->last_tag = -1;
+  L->sizeTM = 0;
+  L->ntag = 0;
   L->refArray = NULL;
-  L->refSize = 0;
+  L->nref = 0;
+  L->sizeref = 0;
   L->refFree = NONEXT;
   L->nblocks = sizeof(lua_State);
   L->GCthreshold = MAX_INT;  /* to avoid GC during pre-definitions */
@@ -107,9 +109,9 @@ LUA_API void lua_close (lua_State *L) {
   if (L->stack)
     L->nblocks -= (L->stack_last - L->stack + 1)*sizeof(TObject);
   luaM_free(L, L->stack);
-  L->nblocks -= (L->last_tag+1)*sizeof(struct TM);
+  L->nblocks -= L->ntag*sizeof(struct TM);
   luaM_free(L, L->TMtable);
-  L->nblocks -= (L->refSize)*sizeof(struct Ref);
+  L->nblocks -= (L->nref)*sizeof(struct Ref);
   luaM_free(L, L->refArray);
   L->nblocks -= (L->Mbuffsize)*sizeof(char);
   luaM_free(L, L->Mbuffer);

+ 5 - 3
lstate.h

@@ -1,5 +1,5 @@
 /*
-** $Id: lstate.h,v 1.41 2000/10/05 13:00:17 roberto Exp roberto $
+** $Id: lstate.h,v 1.42 2000/11/24 17:39:56 roberto Exp roberto $
 ** Global State
 ** See Copyright Notice in lua.h
 */
@@ -61,9 +61,11 @@ struct lua_State {
   stringtable udt;   /* hash table for udata */
   Hash *gt;  /* table for globals */
   struct TM *TMtable;  /* table for tag methods */
-  int last_tag;  /* last used tag in TMtable */
+  int sizeTM;  /* size of TMtable */
+  int ntag;  /* number of tags in TMtable */
   struct Ref *refArray;  /* locked objects */
-  int refSize;  /* size of refArray */
+  int nref;  /* first unused element in refArray */
+  int sizeref;  /* size of refArray */
   int refFree;  /* list of free positions in refArray */
   mem_int GCthreshold;
   mem_int nblocks;  /* number of `bytes' currently allocated */

+ 10 - 10
ltm.c

@@ -1,5 +1,5 @@
 /*
-** $Id: ltm.c,v 1.56 2000/10/31 13:10:24 roberto Exp roberto $
+** $Id: ltm.c,v 1.57 2000/11/30 18:50:47 roberto Exp roberto $
 ** Tag methods
 ** See Copyright Notice in lua.h
 */
@@ -75,26 +75,26 @@ static void init_entry (lua_State *L, int tag) {
 
 void luaT_init (lua_State *L) {
   int t;
-  luaM_growvector(L, L->TMtable, 0, NUM_TAGS, struct TM, "", MAX_INT);
+  L->sizeTM = NUM_TAGS+2;
+  L->TMtable = luaM_newvector(L, L->sizeTM, struct TM);
   L->nblocks += NUM_TAGS*sizeof(struct TM);
-  L->last_tag = NUM_TAGS-1;
-  for (t=0; t<=L->last_tag; t++)
+  L->ntag = NUM_TAGS;
+  for (t=0; t<L->ntag; t++)
     init_entry(L, t);
 }
 
 
 LUA_API int lua_newtag (lua_State *L) {
-  luaM_growvector(L, L->TMtable, L->last_tag, 1, struct TM,
-                  "tag table overflow", MAX_INT);
+  luaM_growvector(L, L->TMtable, L->ntag, L->sizeTM, struct TM,
+                  MAX_INT, "tag table overflow");
   L->nblocks += sizeof(struct TM);
-  L->last_tag++;
-  init_entry(L, L->last_tag);
-  return L->last_tag;
+  init_entry(L, L->ntag);
+  return L->ntag++;
 }
 
 
 static void checktag (lua_State *L, int tag) {
-  if (!(0 <= tag && tag <= L->last_tag))
+  if (!(0 <= tag && tag < L->ntag))
     luaO_verror(L, "%d is not a valid tag", tag);
 }
 

+ 2 - 2
ltm.h

@@ -1,5 +1,5 @@
 /*
-** $Id: ltm.h,v 1.17 2000/10/05 12:14:08 roberto Exp roberto $
+** $Id: ltm.h,v 1.18 2000/10/05 13:00:17 roberto Exp roberto $
 ** Tag methods
 ** See Copyright Notice in lua.h
 */
@@ -45,7 +45,7 @@ struct TM {
 #define luaT_gettmbyObj(L,o,e)  (luaT_gettm((L),luaT_tag(o),(e)))
 
 
-#define validtag(t) (NUM_TAGS <= (t) && (t) <= L->last_tag)
+#define validtag(t) (NUM_TAGS <= (t) && (t) < L->ntag)
 
 extern const char *const luaT_eventname[];