浏览代码

new way to count `nblocks' for GC (try to count bytes).

Roberto Ierusalimschy 25 年之前
父节点
当前提交
dad808a73a
共有 18 个文件被更改,包括 95 次插入63 次删除
  1. 2 1
      lapi.c
  2. 5 4
      lcode.c
  3. 7 4
      ldo.c
  4. 27 9
      lfunc.c
  5. 2 1
      lfunc.h
  6. 5 3
      lgc.c
  7. 2 9
      llimits.h
  8. 5 4
      lobject.c
  9. 8 6
      lobject.h
  10. 4 4
      lparser.c
  11. 1 2
      lparser.h
  12. 8 3
      lstate.c
  13. 2 2
      lstate.h
  14. 6 3
      lstring.c
  15. 3 3
      lstring.h
  16. 2 2
      ltable.c
  17. 3 2
      ltests.c
  18. 3 1
      ltm.c

+ 2 - 1
lapi.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lapi.c,v 1.99 2000/09/18 19:39:26 roberto Exp roberto $
+** $Id: lapi.c,v 1.100 2000/09/27 12:51:39 roberto Exp roberto $
 ** Lua API
 ** See Copyright Notice in lua.h
 */
@@ -355,6 +355,7 @@ int lua_ref (lua_State *L,  int lock) {
     else {  /* no more free places */
       luaM_growvector(L, L->refArray, L->refSize, 1, struct Ref,
                       "reference table overflow", MAX_INT);
+      L->nblocks += sizeof(struct Ref);
       ref = L->refSize++;
     }
     L->refArray[ref].o = *(L->top-1);

+ 5 - 4
lcode.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lcode.c,v 1.49 2000/08/15 13:18:28 roberto Exp roberto $
+** $Id: lcode.c,v 1.50 2000/08/31 14:08:27 roberto Exp roberto $
 ** Code generator for Lua
 ** See Copyright Notice in lua.h
 */
@@ -420,13 +420,14 @@ void luaK_posfix (LexState *ls, BinOpr op, expdesc *v1, expdesc *v2) {
 
 
 static void codelineinfo (FuncState *fs) {
+  Proto *f = fs->f;
   LexState *ls = fs->ls;
   if (ls->lastline > fs->lastline) {
-    luaM_growvector(fs->L, fs->f->lineinfo, fs->nlineinfo, 2, int,
+    luaM_growvector(fs->L, f->lineinfo, f->nlineinfo, 2, int,
                     "line info overflow", MAX_INT);
     if (ls->lastline > fs->lastline+1)
-      fs->f->lineinfo[fs->nlineinfo++] = -(ls->lastline - (fs->lastline+1));
-    fs->f->lineinfo[fs->nlineinfo++] = fs->pc;
+      f->lineinfo[f->nlineinfo++] = -(ls->lastline - (fs->lastline+1));
+    f->lineinfo[f->nlineinfo++] = fs->pc;
     fs->lastline = ls->lastline;
   }
 }

+ 7 - 4
ldo.c

@@ -1,5 +1,5 @@
 /*
-** $Id: ldo.c,v 1.96 2000/09/12 13:47:39 roberto Exp roberto $
+** $Id: ldo.c,v 1.97 2000/09/25 16:22:42 roberto Exp roberto $
 ** Stack and Call structure of Lua
 ** See Copyright Notice in lua.h
 */
@@ -33,6 +33,7 @@
 
 void luaD_init (lua_State *L, int stacksize) {
   L->stack = luaM_newvector(L, stacksize+EXTRA_STACK, TObject);
+  L->nblocks += stacksize*sizeof(TObject);
   L->stack_last = L->stack+(stacksize-1);
   L->stacksize = stacksize;
   L->Cbase = L->top = L->stack;
@@ -248,10 +249,12 @@ static int protectedparser (lua_State *L, ZIO *z, int bin) {
   luaC_checkGC(L);
   old_blocks = L->nblocks;
   status = luaD_runprotected(L, f_parser, &p);
-  if (status == LUA_ERRRUN)  /* an error occurred: correct error code */
+  if (status == 0) {
+    /* add new memory to threshould (as it probably will stay) */
+    L->GCthreshold += (L->nblocks - old_blocks);
+  }
+  else if (status == LUA_ERRRUN)  /* an error occurred: correct error code */
     status = LUA_ERRSYNTAX;
-  /* add new memory to threshould (as it probably will stay) */
-  L->GCthreshold += (L->nblocks - old_blocks);
   return status;
 }
 

+ 27 - 9
lfunc.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lfunc.c,v 1.29 2000/08/09 19:16:57 roberto Exp roberto $
+** $Id: lfunc.c,v 1.30 2000/08/22 17:44:17 roberto Exp roberto $
 ** Auxiliary functions to manipulate prototypes and closures
 ** See Copyright Notice in lua.h
 */
@@ -13,19 +13,18 @@
 #include "lmem.h"
 #include "lstate.h"
 
-#define gcsizeproto(L, p)	numblocks(L, 0, sizeof(Proto))
-#define gcsizeclosure(L, c)	numblocks(L, c->nupvalues, sizeof(Closure))
 
+#define sizeclosure(n)	(sizeof(Closure) + (lint32)sizeof(TObject)*((n)-1))
 
 
 Closure *luaF_newclosure (lua_State *L, int nelems) {
-  Closure *c = (Closure *)luaM_malloc(L, sizeof(Closure) +
-                                         (lint32)sizeof(TObject)*(nelems-1));
+  lint32 size = sizeclosure(nelems);
+  Closure *c = (Closure *)luaM_malloc(L, size);
   c->next = L->rootcl;
   L->rootcl = c;
   c->mark = c;
   c->nupvalues = nelems;
-  L->nblocks += gcsizeclosure(L, c);
+  L->nblocks += size;
   return c;
 }
 
@@ -33,7 +32,9 @@ Closure *luaF_newclosure (lua_State *L, int nelems) {
 Proto *luaF_newproto (lua_State *L) {
   Proto *f = luaM_new(L, Proto);
   f->code = NULL;
+  f->ncode = 0;
   f->lineinfo = NULL;
+  f->nlineinfo = 0;
   f->lineDefined = 0;
   f->source = NULL;
   f->kstr = NULL;
@@ -47,13 +48,30 @@ Proto *luaF_newproto (lua_State *L) {
   f->next = L->rootproto;
   L->rootproto = f;
   f->marked = 0;
-  L->nblocks += gcsizeproto(L, f);
   return f;
 }
 
 
+static size_t protosize (Proto *f) {
+  return sizeof(Proto)
+       + f->nknum*sizeof(Number)
+       + f->nkstr*sizeof(TString *)
+       + f->nkproto*sizeof(Proto *)
+       + f->ncode*sizeof(Instruction)
+       + f->nlocvars*sizeof(struct LocVar)
+       + f->nlineinfo*sizeof(int);
+}
+
+
+void luaF_protook (lua_State *L, Proto *f, int pc) {
+  f->ncode = pc;  /* signal that proto was properly created */
+  L->nblocks += protosize(f);
+}
+
+
 void luaF_freeproto (lua_State *L, Proto *f) {
-  L->nblocks -= gcsizeproto(L, f);
+  if (f->ncode > 0)  /* function was properly created? */
+    L->nblocks -= protosize(f);
   luaM_free(L, f->code);
   luaM_free(L, f->locvars);
   luaM_free(L, f->kstr);
@@ -65,7 +83,7 @@ void luaF_freeproto (lua_State *L, Proto *f) {
 
 
 void luaF_freeclosure (lua_State *L, Closure *c) {
-  L->nblocks -= gcsizeclosure(L, c);
+  L->nblocks -= sizeclosure(c->nupvalues);
   luaM_free(L, c);
 }
 

+ 2 - 1
lfunc.h

@@ -1,5 +1,5 @@
 /*
-** $Id: lfunc.h,v 1.11 2000/03/10 18:37:44 roberto Exp roberto $
+** $Id: lfunc.h,v 1.12 2000/06/26 19:28:31 roberto Exp roberto $
 ** Auxiliary functions to manipulate prototypes and closures
 ** See Copyright Notice in lua.h
 */
@@ -13,6 +13,7 @@
 
 
 Proto *luaF_newproto (lua_State *L);
+void luaF_protook (lua_State *L, Proto *f, int pc);
 Closure *luaF_newclosure (lua_State *L, int nelems);
 void luaF_freeproto (lua_State *L, Proto *f);
 void luaF_freeclosure (lua_State *L, Closure *c);

+ 5 - 3
lgc.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lgc.c,v 1.66 2000/09/19 08:42:35 roberto Exp roberto $
+** $Id: lgc.c,v 1.67 2000/09/25 14:52:10 roberto Exp roberto $
 ** Garbage Collector
 ** See Copyright Notice in lua.h
 */
@@ -254,7 +254,7 @@ static void collectstringtab (lua_State *L, int limit) {
       else {  /* collect */
         *p = next->nexthash;
         L->strt.nuse--;
-        L->nblocks -= gcsizestring(L, next->u.s.len);
+        L->nblocks -= sizestring(next->u.s.len);
         luaM_free(L, next);
       }
     }
@@ -343,7 +343,9 @@ long lua_collectgarbage (lua_State *L, long limit) {
   recovered = recovered - L->nblocks;
   L->GCthreshold = (limit == 0) ? 2*L->nblocks : L->nblocks+limit;
   if (L->Mbuffsize > MINBUFFER*2) {  /* is buffer too big? */
-    L->Mbuffsize /= 2;  /* still larger than MINBUFFER */
+    size_t diff = L->Mbuffsize/2;
+    L->Mbuffsize -= diff;  /* still larger than MINBUFFER */
+    L->nblocks -= diff*sizeof(char);
     luaM_reallocvector(L, L->Mbuffer, L->Mbuffsize, char);
   }
   callgcTM(L, &luaO_nilobject);

+ 2 - 9
llimits.h

@@ -1,5 +1,5 @@
 /*
-** $Id: llimits.h,v 1.13 2000/08/28 17:57:04 roberto Exp roberto $
+** $Id: llimits.h,v 1.14 2000/08/29 14:48:16 roberto Exp roberto $
 ** Limits, basic types, and some other "installation-dependent" definitions
 ** See Copyright Notice in lua.h
 */
@@ -57,13 +57,6 @@ typedef unsigned long lint32;  /* unsigned int with at least 32 bits */
 #define IntPoint(p)  (((unsigned long)(p)) >> 3)
 
 
-/*
-** number of `blocks' for garbage collection: each reference to other
-** objects count 1, and each 32 bytes of `raw' memory count 1; we add
-** 2 to the total as a minimum (and also to count the overhead of malloc)
-*/
-#define numblocks(L, o,b)       ((o)+((b)>>5)+2)
-
 
 #define MINPOWER2       4       /* minimum size for "growing" vectors */
 
@@ -77,7 +70,7 @@ typedef unsigned long lint32;  /* unsigned int with at least 32 bits */
 
 /*
 ** type for virtual-machine instructions
-** must be an unsigned with 4 bytes (see details in lopcodes.h)
+** must be an unsigned with (at least) 4 bytes (see details in lopcodes.h)
 ** For a very small machine, you may change that to 2 bytes (and adjust
 ** the following limits accordingly)
 */

+ 5 - 4
lobject.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lobject.c,v 1.47 2000/09/11 20:29:27 roberto Exp roberto $
+** $Id: lobject.c,v 1.48 2000/09/12 13:47:39 roberto Exp roberto $
 ** Some generic functions over Lua objects
 ** See Copyright Notice in lua.h
 */
@@ -18,7 +18,7 @@
 
 
 /*
-** you can use the fact that the 3rd letter or each name is always different
+** you can use the fact that the 3rd letter of each name is always different
 ** (e-m-r-b-n-l) to compare and switch these strings
 */
 const char *const luaO_typenames[] = { /* ORDER LUA_T */
@@ -61,6 +61,7 @@ int luaO_equalObj (const TObject *t1, const TObject *t2) {
 char *luaO_openspace (lua_State *L, size_t n) {
   if (n > L->Mbuffsize) {
     luaM_reallocvector(L, L->Mbuffer, n, char);
+    L->nblocks += (n - L->Mbuffsize)*sizeof(char);
     L->Mbuffsize = n;
   }
   return L->Mbuffer;
@@ -127,10 +128,10 @@ int luaO_str2d (const char *s, Number *result) {  /* LUA_NUMBER */
 }
 
 
-/* this function needs to handle only '%d' and '%.XXXs' formats */
+/* this function needs to handle only '%d' and '%.XXs' formats */
 void luaO_verror (lua_State *L, const char *fmt, ...) {
-  char buff[500];
   va_list argp;
+  char buff[600];  /* to hold formated message */
   va_start(argp, fmt);
   vsprintf(buff, fmt, argp);
   va_end(argp);

+ 8 - 6
lobject.h

@@ -1,5 +1,5 @@
 /*
-** $Id: lobject.h,v 1.75 2000/09/11 17:38:42 roberto Exp roberto $
+** $Id: lobject.h,v 1.76 2000/09/11 20:29:27 roberto Exp roberto $
 ** Type definitions for Lua objects
 ** See Copyright Notice in lua.h
 */
@@ -116,14 +116,16 @@ typedef struct Proto {
   int nkstr;  /* size of `kstr' */
   struct Proto **kproto;  /* functions defined inside the function */
   int nkproto;  /* size of `kproto' */
-  Instruction *code;  /* ends with opcode ENDCODE */
-  int numparams;
-  int is_vararg;
-  int maxstacksize;
+  Instruction *code;
+  int ncode;  /* size of `code'; when 0 means an incomplete `Proto' */
+  short numparams;
+  short is_vararg;
+  short maxstacksize;
+  short marked;
   struct Proto *next;
-  int marked;
   /* debug information */
   int *lineinfo;  /* map from opcodes to source lines */
+  int nlineinfo;  /* size of `lineinfo' */
   int nlocvars;
   struct LocVar *locvars;  /* information about local variables */
   int lineDefined;

+ 4 - 4
lparser.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lparser.c,v 1.112 2000/09/20 17:57:08 roberto Exp roberto $
+** $Id: lparser.c,v 1.113 2000/09/27 17:41:58 roberto Exp roberto $
 ** LL(1) Parser and code generator for Lua
 ** See Copyright Notice in lua.h
 */
@@ -315,7 +315,6 @@ static void open_func (LexState *ls, FuncState *fs) {
   f->source = ls->source;
   fs->pc = 0;
   fs->lasttarget = 0;
-  fs->nlineinfo = 0;
   fs->lastline = 0;
   fs->jlt = NO_JUMP;
   f->code = NULL;
@@ -337,8 +336,9 @@ static void close_func (LexState *ls) {
   luaM_reallocvector(L, f->kproto, f->nkproto, Proto *);
   removelocalvars(ls, fs->nactloc);
   luaM_reallocvector(L, f->locvars, f->nlocvars, LocVar);
-  luaM_reallocvector(L, f->lineinfo, fs->nlineinfo+1, int);
-  f->lineinfo[fs->nlineinfo] = MAX_INT;  /* end flag */
+  luaM_reallocvector(L, f->lineinfo, f->nlineinfo+1, int);
+  f->lineinfo[f->nlineinfo] = MAX_INT;  /* end flag */
+  luaF_protook(L, f, fs->pc);  /* proto is ok now */
   ls->fs = fs->prev;
   LUA_ASSERT(fs->bl == NULL, "wrong list end");
 }

+ 1 - 2
lparser.h

@@ -1,5 +1,5 @@
 /*
-** $Id: lparser.h,v 1.23 2000/08/22 17:44:17 roberto Exp roberto $
+** $Id: lparser.h,v 1.24 2000/08/30 18:50:18 roberto Exp roberto $
 ** LL(1) Parser and code generator for Lua
 ** See Copyright Notice in lua.h
 */
@@ -48,7 +48,6 @@ typedef struct FuncState {
   int nactloc;  /* number of active local variables */
   int nupvalues;  /* number of upvalues */
   int lastline;  /* line where last `lineinfo' was generated */
-  int nlineinfo;  /* index of next `lineinfo' to be generated */
   struct Breaklabel *bl;  /* chain of breakable blocks */
   expdesc upvalues[MAXUPVALUES];  /* upvalues */
   int actloc[MAXLOCALS];  /* local-variable stack (indices to locvars) */

+ 8 - 3
lstate.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lstate.c,v 1.40 2000/09/21 14:41:25 roberto Exp roberto $
+** $Id: lstate.c,v 1.41 2000/09/25 16:22:42 roberto Exp roberto $
 ** Global State
 ** See Copyright Notice in lua.h
 */
@@ -78,7 +78,7 @@ lua_State *lua_open (int stacksize) {
   L->refArray = NULL;
   L->refSize = 0;
   L->refFree = NONEXT;
-  L->nblocks = 0;
+  L->nblocks = sizeof(lua_State);
   L->GCthreshold = MAX_INT;  /* to avoid GC during pre-definitions */
   L->callhook = NULL;
   L->linehook = NULL;
@@ -100,11 +100,16 @@ void lua_close (lua_State *L) {
   LUA_ASSERT(L->rootcl == NULL, "list should be empty");
   LUA_ASSERT(L->roottable == NULL, "list should be empty");
   luaS_freeall(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 IM);
   luaM_free(L, L->IMtable);
+  L->nblocks -= (L->refSize)*sizeof(struct Ref);
   luaM_free(L, L->refArray);
+  L->nblocks -= (L->Mbuffsize)*sizeof(char);
   luaM_free(L, L->Mbuffer);
-  LUA_ASSERT(L->nblocks == 0, "wrong count for nblocks");
+  LUA_ASSERT(L->nblocks == sizeof(lua_State), "wrong count for nblocks");
   luaM_free(L, L);
   LUA_ASSERT(L != lua_state || memdebug_numblocks == 0, "memory leak!");
   LUA_ASSERT(L != lua_state || memdebug_total == 0,"memory leak!");

+ 2 - 2
lstate.h

@@ -1,5 +1,5 @@
 /*
-** $Id: lstate.h,v 1.38 2000/09/11 17:38:42 roberto Exp roberto $
+** $Id: lstate.h,v 1.39 2000/09/25 16:22:42 roberto Exp roberto $
 ** Global State
 ** See Copyright Notice in lua.h
 */
@@ -65,7 +65,7 @@ struct lua_State {
   int refSize;  /* size of refArray */
   int refFree;  /* list of free positions in refArray */
   unsigned long GCthreshold;
-  unsigned long nblocks;  /* number of `blocks' currently allocated */
+  unsigned long nblocks;  /* number of `bytes' currently allocated */
   lua_Hook callhook;
   lua_Hook linehook;
   int allowhooks;

+ 6 - 3
lstring.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lstring.c,v 1.41 2000/08/04 19:38:35 roberto Exp roberto $
+** $Id: lstring.c,v 1.42 2000/08/09 19:16:57 roberto Exp roberto $
 ** String table (keeps all strings handled by Lua)
 ** See Copyright Notice in lua.h
 */
@@ -19,6 +19,7 @@
 void luaS_init (lua_State *L) {
   L->strt.hash = luaM_newvector(L, 1, TString *);
   L->udt.hash = luaM_newvector(L, 1, TString *);
+  L->nblocks += 2*sizeof(TString *);
   L->strt.size = L->udt.size = 1;
   L->strt.nuse = L->udt.nuse = 0;
   L->strt.hash[0] = L->udt.hash[0] = NULL;
@@ -27,6 +28,7 @@ void luaS_init (lua_State *L) {
 
 void luaS_freeall (lua_State *L) {
   LUA_ASSERT(L->strt.nuse==0, "non-empty string table");
+  L->nblocks -= (L->strt.size + L->udt.size)*sizeof(TString *);
   luaM_free(L, L->strt.hash);
   LUA_ASSERT(L->udt.nuse==0, "non-empty udata table");
   luaM_free(L, L->udt.hash);
@@ -61,6 +63,7 @@ void luaS_resize (lua_State *L, stringtable *tb, int newsize) {
     }
   }
   luaM_free(L, tb->hash);
+  L->nblocks += (newsize - tb->size)*sizeof(TString *);
   tb->size = newsize;
   tb->hash = newhash;
 }
@@ -85,7 +88,7 @@ TString *luaS_newlstr (lua_State *L, const char *str, size_t l) {
       return ts;
   }
   /* not found */
-  ts = (TString *)luaM_malloc(L, sizeof(TString)+(lint32)l*sizeof(char));
+  ts = (TString *)luaM_malloc(L, sizestring(l));
   ts->marked = 0;
   ts->nexthash = NULL;
   ts->u.s.len = l;
@@ -93,7 +96,7 @@ TString *luaS_newlstr (lua_State *L, const char *str, size_t l) {
   ts->u.s.constindex = 0;
   memcpy(ts->str, str, l);
   ts->str[l] = 0;  /* ending 0 */
-  L->nblocks += gcsizestring(L, l);
+  L->nblocks += sizestring(l);
   newentry(L, &L->strt, ts, h1);  /* insert it on table */
   return ts;
 }

+ 3 - 3
lstring.h

@@ -1,5 +1,5 @@
 /*
-** $Id: lstring.h,v 1.20 2000/05/10 16:33:20 roberto Exp roberto $
+** $Id: lstring.h,v 1.21 2000/05/24 13:54:49 roberto Exp roberto $
 ** String table (keep all strings handled by Lua)
 ** See Copyright Notice in lua.h
 */
@@ -20,8 +20,8 @@
 #define RESERVEDMARK	3
 
 
-#define gcsizestring(L, l)      numblocks(L, 0, sizeof(TString)+l)
-#define gcsizeudata             gcsizestring(L, 0)
+#define sizestring(l)	(sizeof(TString)+(lint32)(l)*sizeof(char))
+#define gcsizeudata	(sizeof(TString))
 
 
 void luaS_init (lua_State *L);

+ 2 - 2
ltable.c

@@ -1,5 +1,5 @@
 /*
-** $Id: ltable.c,v 1.54 2000/08/31 14:08:27 roberto Exp roberto $
+** $Id: ltable.c,v 1.55 2000/09/11 20:29:27 roberto Exp roberto $
 ** Lua tables (hash)
 ** See Copyright Notice in lua.h
 */
@@ -27,7 +27,7 @@
 #include "ltable.h"
 
 
-#define gcsize(L, n)	numblocks(L, n*2, sizeof(Hash))
+#define gcsize(L, n)	(sizeof(Hash)+(n)*sizeof(Node))
 
 
 

+ 3 - 2
ltests.c

@@ -1,5 +1,5 @@
 /*
-** $Id: ltests.c,v 1.43 2000/09/25 14:48:42 roberto Exp roberto $
+** $Id: ltests.c,v 1.44 2000/09/25 16:22:42 roberto Exp roberto $
 ** Internal Module for Debugging of the Lua Implementation
 ** See Copyright Notice in lua.h
 */
@@ -166,7 +166,8 @@ static int mem_query (lua_State *L) {
     lua_pushnumber(L, memdebug_total);
     lua_pushnumber(L, memdebug_numblocks);
     lua_pushnumber(L, memdebug_maxmem);
-    return 3;
+lua_pushnumber(L, L->nblocks);
+    return 4;
   }
   else {
     memdebug_memlimit = luaL_check_int(L, 1);

+ 3 - 1
ltm.c

@@ -1,5 +1,5 @@
 /*
-** $Id: ltm.c,v 1.48 2000/09/11 19:45:27 roberto Exp roberto $
+** $Id: ltm.c,v 1.49 2000/09/11 20:29:27 roberto Exp roberto $
 ** Tag methods
 ** See Copyright Notice in lua.h
 */
@@ -77,6 +77,7 @@ static void init_entry (lua_State *L, int tag) {
 void luaT_init (lua_State *L) {
   int t;
   luaM_growvector(L, L->IMtable, 0, NUM_TAGS, struct IM, "", MAX_INT);
+  L->nblocks += NUM_TAGS*sizeof(struct IM);
   L->last_tag = NUM_TAGS-1;
   for (t=0; t<=L->last_tag; t++)
     init_entry(L, t);
@@ -86,6 +87,7 @@ void luaT_init (lua_State *L) {
 int lua_newtag (lua_State *L) {
   luaM_growvector(L, L->IMtable, L->last_tag, 1, struct IM,
                   "tag table overflow", MAX_INT);
+  L->nblocks += sizeof(struct IM);
   L->last_tag++;
   init_entry(L, L->last_tag);
   return L->last_tag;