Browse Source

explicit control of size for growing vectors

Roberto Ierusalimschy 25 năm trước cách đây
mục cha
commit
8c49e19865
12 tập tin đã thay đổi với 95 bổ sung70 xóa
  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[];