|
@@ -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;
|
|
|
}
|
|
|
}
|
|
|
|