diff --git a/lauxlib.c b/lauxlib.c index 60e28646..b90bf458 100644 --- a/lauxlib.c +++ b/lauxlib.c @@ -1,5 +1,5 @@ /* -** $Id: lauxlib.c,v 1.102 2003/05/16 18:59:08 roberto Exp roberto $ +** $Id: lauxlib.c,v 1.103 2003/10/01 16:50:53 roberto Exp roberto $ ** Auxiliary functions for building Lua libraries ** See Copyright Notice in lua.h */ @@ -9,6 +9,7 @@ #include #include #include +#include #include @@ -558,6 +559,22 @@ LUALIB_API int luaL_loadbuffer (lua_State *L, const char *buff, size_t size, /* }====================================================== */ +static void *l_alloc (void *ud, void *ptr, size_t osize, size_t nsize) { + (void)ud; + if (nsize == 0) { + free(ptr); + return NULL; + } + else + return realloc(ptr, nsize); +} + + +LUALIB_API lua_State *luaL_newstate (void) { + return lua_newstate(l_alloc, NULL); +} + + /* ** {====================================================== ** compatibility code diff --git a/lauxlib.h b/lauxlib.h index 25f3c441..a04c55e7 100644 --- a/lauxlib.h +++ b/lauxlib.h @@ -1,5 +1,5 @@ /* -** $Id: lauxlib.h,v 1.59 2003/03/18 12:25:32 roberto Exp roberto $ +** $Id: lauxlib.h,v 1.60 2003/04/03 13:35:34 roberto Exp roberto $ ** Auxiliary functions for building Lua libraries ** See Copyright Notice in lua.h */ @@ -62,6 +62,8 @@ LUALIB_API int luaL_loadfile (lua_State *L, const char *filename); LUALIB_API int luaL_loadbuffer (lua_State *L, const char *buff, size_t sz, const char *name); +LUALIB_API lua_State *(luaL_newstate) (void); + /* diff --git a/lmem.c b/lmem.c index 8b89b764..39e19647 100644 --- a/lmem.c +++ b/lmem.c @@ -1,11 +1,11 @@ /* -** $Id: lmem.c,v 1.60 2002/11/21 14:14:42 roberto Exp roberto $ +** $Id: lmem.c,v 1.61 2002/12/04 17:38:31 roberto Exp roberto $ ** Interface to Memory Manager ** See Copyright Notice in lua.h */ -#include +#include #define lmem_c @@ -20,21 +20,23 @@ /* -** definition for realloc function. It must assure that l_realloc(NULL, -** 0, x) allocates a new block (ANSI C assures that). (`os' is the old -** block size; some allocators may use that.) +** About the realloc function: +** void * realloc (void *ud, void *ptr, size_t osize, size_t nsize); +** (`osize' is the old size, `nsize' is the new size) +** +** Lua ensures that (ptr == NULL) iff (osize == 0). +** +** * realloc(ud, NULL, 0, x) creates a new block of size `x' +** +** * realloc(ud, p, x, 0) frees the block `p' +** (in this specific case, realloc must return NULL). +** particularly, realloc(ud, NULL, 0, 0) does nothing +** (which is equivalent to free(NULL) in ANSI C) +** +** realloc returns NULL if it cannot create or reallocate the area +** (any reallocation to an equal or smaller size cannot fail!) */ -#ifndef l_realloc -#define l_realloc(b,os,s) realloc(b,s) -#endif -/* -** definition for free function. (`os' is the old block size; some -** allocators may use that.) -*/ -#ifndef l_free -#define l_free(b,os) free(b) -#endif #define MINSIZEARRAY 4 @@ -62,30 +64,17 @@ void *luaM_growaux (lua_State *L, void *block, int *size, int size_elems, /* ** generic allocation routine. */ -void *luaM_realloc (lua_State *L, void *block, lu_mem oldsize, lu_mem size) { - lua_assert((oldsize == 0) == (block == NULL)); - if (size == 0) { - if (block != NULL) { - l_free(block, oldsize); - block = NULL; - } - else return NULL; /* avoid `nblocks' computations when oldsize==size==0 */ - } - else if (size >= MAX_SIZET) +void *luaM_realloc (lua_State *L, void *block, lu_mem osize, lu_mem nsize) { + global_State *g = G(L); + lua_assert((osize == 0) == (block == NULL)); + if (nsize >= MAX_SIZET) luaG_runerror(L, "memory allocation error: block too big"); - else { - block = l_realloc(block, oldsize, size); - if (block == NULL) { - if (L) - luaD_throw(L, LUA_ERRMEM); - else return NULL; /* error before creating state! */ - } - } - if (L) { - lua_assert(G(L) != NULL && G(L)->nblocks > 0); - G(L)->nblocks -= oldsize; - G(L)->nblocks += size; - } + block = (*g->realloc)(g->ud, block, osize, nsize); + if (block == NULL && nsize > 0) + luaD_throw(L, LUA_ERRMEM); + lua_assert((nsize == 0) == (block == NULL)); + g->nblocks -= osize; + g->nblocks += nsize; return block; } diff --git a/lstate.c b/lstate.c index dd80a7e1..12acb3eb 100644 --- a/lstate.c +++ b/lstate.c @@ -1,11 +1,11 @@ /* -** $Id: lstate.c,v 1.125 2003/07/16 20:51:47 roberto Exp roberto $ +** $Id: lstate.c,v 1.126 2003/09/04 20:19:07 roberto Exp roberto $ ** Global State ** See Copyright Notice in lua.h */ -#include +#include #define lstate_c @@ -34,6 +34,11 @@ union UEXTRASPACE {L_Umaxalign a; LUA_USERSTATE b;}; #endif +#define state_size(x) (sizeof(x) + EXTRASPACE) +#define tostate(l) (cast(lua_State *, cast(lu_byte *, l) + EXTRASPACE)) +#define fromstate(l) (cast(lu_byte *, (l)) - EXTRASPACE) + + /* ** Main thread combines a thread state and the global state */ @@ -44,23 +49,6 @@ typedef struct LG { - -static lua_State *mallocstate (lua_State *L, size_t size) { - lu_byte *block = (lu_byte *)luaM_malloc(L, size + EXTRASPACE); - if (block == NULL) return NULL; - else { - block += EXTRASPACE; - return cast(lua_State *, block); - } -} - - -static void freestate (lua_State *L, lua_State *L1, size_t size) { - luaM_free(L, cast(lu_byte *, L1) - EXTRASPACE, - size + EXTRASPACE); -} - - static void stack_init (lua_State *L1, lua_State *L) { L1->stack = luaM_newvector(L, BASIC_STACK_SIZE + EXTRA_STACK, TObject); L1->stacksize = BASIC_STACK_SIZE + EXTRA_STACK; @@ -122,20 +110,21 @@ static void preinit_state (lua_State *L) { static void close_state (lua_State *L) { + global_State *g = G(L); luaF_close(L, L->stack); /* close all upvalues for this thread */ luaC_sweep(L, 1); /* collect all elements */ - lua_assert(G(L)->rootgc == NULL); - lua_assert(G(L)->rootudata == NULL); + lua_assert(g->rootgc == NULL); + lua_assert(g->rootudata == NULL); luaS_freeall(L); - luaZ_freebuffer(L, &G(L)->buff); + luaZ_freebuffer(L, &g->buff); freestack(L, L); - lua_assert(G(L)->nblocks == sizeof(LG)); - freestate(NULL, L, sizeof(LG)); + lua_assert(g->nblocks == sizeof(LG)); + (*g->realloc)(g->ud, fromstate(L), state_size(LG), 0); } lua_State *luaE_newthread (lua_State *L) { - lua_State *L1 = mallocstate(L, sizeof(lua_State)); + lua_State *L1 = tostate(luaM_malloc(L, state_size(lua_State))); luaC_link(L, valtogco(L1), LUA_TTHREAD); preinit_state(L1); L1->l_G = L->l_G; @@ -149,20 +138,24 @@ void luaE_freethread (lua_State *L, lua_State *L1) { luaF_close(L1, L1->stack); /* close all upvalues for this thread */ lua_assert(L1->openupval == NULL); freestack(L, L1); - freestate(L, L1, sizeof(lua_State)); + luaM_free(L, fromstate(L1), state_size(lua_State)); } -LUA_API lua_State *lua_open (void) { - lua_State *L = mallocstate(NULL, sizeof(LG)); +LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) { + lua_State *L; global_State *g; - if (L == NULL) return NULL; + void *l = (*f)(ud, NULL, 0, state_size(LG)); + if (l == NULL) return NULL; + L = tostate(l); g = &((LG *)L)->g; L->tt = LUA_TTHREAD; L->marked = 0; L->next = L->gclist = NULL; preinit_state(L); L->l_G = g; + g->realloc = f; + g->ud = ud; g->mainthread = L; g->GCthreshold = 0; /* mark it as unfinished state */ g->strt.size = 0; diff --git a/lstate.h b/lstate.h index 009ea790..94e9bbfa 100644 --- a/lstate.h +++ b/lstate.h @@ -1,5 +1,5 @@ /* -** $Id: lstate.h,v 1.110 2003/04/28 19:26:16 roberto Exp roberto $ +** $Id: lstate.h,v 1.111 2003/07/16 20:49:02 roberto Exp roberto $ ** Global State ** See Copyright Notice in lua.h */ @@ -101,6 +101,8 @@ typedef struct global_State { GCObject *rootgc; /* list of (almost) all collectable objects */ GCObject *rootudata; /* (separated) list of all userdata */ GCObject *tmudata; /* list of userdata to be GC */ + lua_Alloc realloc; /* function to reallocate memory */ + void *ud; /* auxiliary data to `realloc' */ Mbuffer buff; /* temporary buffer for string concatentation */ lu_mem GCthreshold; lu_mem nblocks; /* number of `bytes' currently allocated */ diff --git a/ltests.c b/ltests.c index a659d3af..2c0f5869 100644 --- a/ltests.c +++ b/ltests.c @@ -1,5 +1,5 @@ /* -** $Id: ltests.c,v 1.162 2003/07/09 12:08:43 roberto Exp roberto $ +** $Id: ltests.c,v 1.163 2003/07/29 19:26:34 roberto Exp roberto $ ** Internal Module for Debugging of the Lua Implementation ** See Copyright Notice in lua.h */ @@ -80,10 +80,8 @@ static void setnameval (lua_State *L, const char *name, int val) { #define fillmem(mem,size) /* empty */ #endif -unsigned long memdebug_numblocks = 0; -unsigned long memdebug_total = 0; -unsigned long memdebug_maxmem = 0; -unsigned long memdebug_memlimit = ULONG_MAX; + +Memcontrol memcontrol = {0L, 0L, 0L, ULONG_MAX}; static void *checkblock (void *block, size_t size) { @@ -95,27 +93,26 @@ static void *checkblock (void *block, size_t size) { } -static void freeblock (void *block, size_t size) { +static void freeblock (Memcontrol *mc, void *block, size_t size) { if (block) { lua_assert(checkblocksize(block, size)); block = checkblock(block, size); fillmem(block, size+HEADER+MARKSIZE); /* erase block */ free(block); /* free original block */ - memdebug_numblocks--; - memdebug_total -= size; + mc->numblocks--; + mc->total -= size; } } -void *debug_realloc (void *block, size_t oldsize, size_t size) { +void *debug_realloc (void *ud, void *block, size_t oldsize, size_t size) { + Memcontrol *mc = cast(Memcontrol *, ud); lua_assert(oldsize == 0 || checkblocksize(block, oldsize)); - /* ISO does not specify what realloc(NULL, 0) does */ - lua_assert(block != NULL || size > 0); if (size == 0) { - freeblock(block, oldsize); + freeblock(mc, block, oldsize); return NULL; } - else if (size > oldsize && memdebug_total+size-oldsize > memdebug_memlimit) + else if (size > oldsize && mc->total+size-oldsize > mc->memlimit) return NULL; /* to test memory allocation errors */ else { void *newblock; @@ -127,14 +124,14 @@ void *debug_realloc (void *block, size_t oldsize, size_t size) { if (newblock == NULL) return NULL; if (block) { memcpy(cast(char *, newblock)+HEADER, block, commonsize); - freeblock(block, oldsize); /* erase (and check) old copy */ + freeblock(mc, block, oldsize); /* erase (and check) old copy */ } /* initialize new part of the block with something `weird' */ fillmem(cast(char *, newblock)+HEADER+commonsize, size-commonsize); - memdebug_total += size; - if (memdebug_total > memdebug_maxmem) - memdebug_maxmem = memdebug_total; - memdebug_numblocks++; + mc->total += size; + if (mc->total > mc->maxmem) + mc->maxmem = mc->total; + mc->numblocks++; setsize(newblock, size); for (i=0;i