Browse Source

complete control over number of each kind of object allocated

Roberto Ierusalimschy 15 years ago
parent
commit
973d81efb3
1 changed files with 53 additions and 46 deletions
  1. 53 46
      ltests.c

+ 53 - 46
ltests.c

@@ -1,5 +1,5 @@
 /*
-** $Id: ltests.c,v 2.94 2010/04/13 20:48:12 roberto Exp roberto $
+** $Id: ltests.c,v 2.95 2010/04/16 17:42:49 roberto Exp roberto $
 ** Internal Module for Debugging of the Lua Implementation
 ** See Copyright Notice in lua.h
 */
@@ -74,90 +74,97 @@ static int tpanic (lua_State *L) {
 
 #define MARK		0x55  /* 01010101 (a nice pattern) */
 
+typedef union Header {
+  L_Umaxalign a;  /* ensures maximum alignment for Header */
+  struct {
+    size_t size;
+    int type;
+  } d;
+} Header;
+
+
 #ifndef EXTERNMEMCHECK
+
 /* full memory check */
-#define HEADER	(sizeof(L_Umaxalign)) /* ensures maximum alignment for HEADER */
 #define MARKSIZE	16  /* size of marks after each block */
-#define blockhead(b)	(cast(char *, b) - HEADER)
-#define setsize(newblock, size)	(*cast(size_t *, newblock) = size)
-#define checkblocksize(b, size) (size == (*cast(size_t *, blockhead(b))))
 #define fillmem(mem,size)	memset(mem, -MARK, size)
+
 #else
+
 /* external memory check: don't do it twice */
-#define HEADER		0
 #define MARKSIZE	0
-#define blockhead(b)	(b)
-#define setsize(newblock, size)	/* empty */
-#define checkblocksize(b,size)	(1)
 #define fillmem(mem,size)	/* empty */
+
 #endif
 
+
 Memcontrol l_memcontrol =
   {0L, 0L, 0L, 0L, {0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L}};
 
 
-static void *checkblock (void *block, size_t size) {
-  void *b = blockhead(block);
-  int i;
-  for (i=0;i<MARKSIZE;i++)
-    lua_assert(*(cast(char *, b)+HEADER+size+i) == MARK+i); /* corrupted block? */
-  return b;
-}
-
-
-static void freeblock (Memcontrol *mc, void *block, size_t size) {
+static void freeblock (Memcontrol *mc, Header *block) {
   if (block) {
-    lua_assert(checkblocksize(block, size));
-    block = checkblock(block, size);
-    fillmem(block, size+HEADER+MARKSIZE);  /* erase block */
-    free(block);  /* free original block */
-    mc->numblocks--;
+    size_t size = block->d.size;
+    int i;
+    for (i = 0; i < MARKSIZE; i++)  /* check marks after block */
+      lua_assert(*(cast(char *, block + 1) + size + i) == MARK);
+    mc->objcount[block->d.type]--;
+    fillmem(block, sizeof(Header) + size + MARKSIZE);  /* erase block */
+    free(block);  /* actually free block */
+    mc->numblocks--;  /* update counts */
     mc->total -= size;
   }
 }
 
 
-void *debug_realloc (void *ud, void *block, size_t oldsize, size_t size) {
+void *debug_realloc (void *ud, void *b, size_t oldsize, size_t size) {
   Memcontrol *mc = cast(Memcontrol *, ud);
-  if (block == NULL) {
-    if (oldsize < LUA_NUMTAGS)
-      mc->objcount[oldsize]++;
-    oldsize = 0;
-  }
-  lua_assert((oldsize == 0) ? block == NULL :
-                              block && checkblocksize(block, oldsize));
+  Header *block = cast(Header *, b);
+  int type;
   if (mc->memlimit == 0) {  /* first time? */
     char *limit = getenv("MEMLIMIT");  /* initialize memory limit */
     mc->memlimit = limit ? strtoul(limit, NULL, 10) : ULONG_MAX;
   }
+  if (block == NULL) {
+    type = (oldsize < LUA_NUMTAGS) ? oldsize : 0;
+    oldsize = 0;
+  }
+  else {
+    block--;  /* go to real header */
+    type = block->d.type;
+    lua_assert(oldsize == block->d.size);
+  }
   if (size == 0) {
-    freeblock(mc, block, oldsize);
+    freeblock(mc, block);
     return NULL;
   }
   else if (size > oldsize && mc->total+size-oldsize > mc->memlimit)
-    return NULL;  /* to test memory allocation errors */
+    return NULL;  /* fake a memory allocation error */
   else {
-    void *newblock;
+    Header *newblock;
     int i;
-    size_t realsize = HEADER+size+MARKSIZE;
     size_t commonsize = (oldsize < size) ? oldsize : size;
-    if (realsize < size) return NULL;  /* overflow! */
-    newblock = malloc(realsize);  /* alloc a new block */
-    if (newblock == NULL) return NULL;
+    size_t realsize = sizeof(Header) + size + MARKSIZE;
+    if (realsize < size) return NULL;  /* arithmetic overflow! */
+    newblock = cast(Header *, malloc(realsize));  /* alloc a new block */
+    if (newblock == NULL) return NULL;  /* really out of memory? */
     if (block) {
-      memcpy(cast(char *, newblock)+HEADER, block, commonsize);
-      freeblock(mc, block, oldsize);  /* erase (and check) old copy */
+      memcpy(newblock + 1, block + 1, commonsize);  /* copy old contents */
+      freeblock(mc, block);  /* erase (and check) old copy */
     }
     /* initialize new part of the block with something `weird' */
-    fillmem(cast(char *, newblock)+HEADER+commonsize, size-commonsize);
+    fillmem(cast(char *, newblock + 1) + commonsize, size - commonsize);
+    /* initialize marks after block */
+    for (i = 0; i < MARKSIZE; i++)
+      *(cast(char *, newblock + 1) + size + i) = MARK;
+    newblock->d.size = size;
+    newblock->d.type = type;
     mc->total += size;
     if (mc->total > mc->maxmem)
       mc->maxmem = mc->total;
     mc->numblocks++;
-    setsize(newblock, size);
-    for (i=0;i<MARKSIZE;i++)
-      *(cast(char *, newblock)+HEADER+size+i) = cast(char, MARK+i);
-    return cast(char *, newblock)+HEADER;
+    mc->objcount[type]++;
+    return newblock + 1;
   }
 }