From 9cdf6b7082c49e6bf7daf8c7c4c649bcaacf9fad Mon Sep 17 00:00:00 2001 From: Roberto Ierusalimschy Date: Fri, 19 Jul 2019 09:43:35 -0300 Subject: [PATCH] Some details in 'lmem.c' and 'lgc.c' - Several new comments in 'lmem.c'. - Both 'luaM_growaux_' and 'luaM_shrinkvector_' use 'luaM_saferealloc_' to check for errors. Moreover, the use of 'luaM_saferealloc_' makes 'luaM_shrinkvector_' try again if shrink fails (which can happen now). - In 'checkSizes', save old debt only when needed. --- lgc.c | 7 ++++--- lmem.c | 62 +++++++++++++++++++++++++++++++++++----------------------- 2 files changed, 42 insertions(+), 27 deletions(-) diff --git a/lgc.c b/lgc.c index aa6921bc..6562c928 100644 --- a/lgc.c +++ b/lgc.c @@ -794,10 +794,11 @@ static GCObject **sweeptolive (lua_State *L, GCObject **p) { */ static void checkSizes (lua_State *L, global_State *g) { if (!g->gcemergency) { - l_mem olddebt = g->GCdebt; - if (g->strt.nuse < g->strt.size / 4) /* string table too big? */ + if (g->strt.nuse < g->strt.size / 4) { /* string table too big? */ + l_mem olddebt = g->GCdebt; luaS_resize(L, g->strt.size / 2); - g->GCestimate += g->GCdebt - olddebt; /* correct estimate */ + g->GCestimate += g->GCdebt - olddebt; /* correct estimate */ + } } } diff --git a/lmem.c b/lmem.c index 0186a86b..b1d646a5 100644 --- a/lmem.c +++ b/lmem.c @@ -44,23 +44,35 @@ static void *firsttry (global_State *g, void *block, size_t os, size_t ns) { /* ** About the realloc function: -** void * frealloc (void *ud, void *ptr, size_t osize, size_t nsize); +** void *frealloc (void *ud, void *ptr, size_t osize, size_t nsize); ** ('osize' is the old size, 'nsize' is the new size) ** -** * frealloc(ud, NULL, x, s) creates a new block of size 's' (no -** matter 'x'). +** - frealloc(ud, p, x, 0) frees the block 'p' and returns NULL. +** Particularly, frealloc(ud, NULL, 0, 0) does nothing, +** which is equivalent to free(NULL) in ISO C. ** -** * frealloc(ud, p, x, 0) frees the block 'p' -** (in this specific case, frealloc must return NULL); -** particularly, frealloc(ud, NULL, 0, 0) does nothing -** (which is equivalent to free(NULL) in ISO C) +** - frealloc(ud, NULL, x, s) creates a new block of size 's' +** (no matter 'x'). Returns NULL if it cannot create the new block. ** -** frealloc returns NULL if it cannot create or reallocate the area -** (any reallocation to an equal or smaller size cannot fail!) +** - otherwise, frealloc(ud, b, x, y) reallocates the block 'b' from +** size 'x' to size 'y'. Returns NULL if it cannot reallocate the +** block to the new size. */ + +/* +** {================================================================== +** Functions to allocate/deallocate arrays for the Parser +** =================================================================== +*/ + +/* +** Minimum size for arrays during parsing, to avoid overhead of +** reallocating to size 1, then 2, and then 4. All these arrays +** will be reallocated to exact sizes or erased when parsing ends. +*/ #define MINSIZEARRAY 4 @@ -82,32 +94,32 @@ void *luaM_growaux_ (lua_State *L, void *block, int nelems, int *psize, } lua_assert(nelems + 1 <= size && size <= limit); /* 'limit' ensures that multiplication will not overflow */ - newblock = luaM_realloc_(L, block, cast_sizet(*psize) * size_elems, - cast_sizet(size) * size_elems); - if (unlikely(newblock == NULL)) - luaM_error(L); + newblock = luaM_saferealloc_(L, block, cast_sizet(*psize) * size_elems, + cast_sizet(size) * size_elems); *psize = size; /* update only when everything else is OK */ return newblock; } +/* +** In prototypes, the size of the array is also its number of +** elements (to save memory). So, if it cannot shrink an array +** to its number of elements, the only option is to raise an +** error. +*/ void *luaM_shrinkvector_ (lua_State *L, void *block, int *size, int final_n, int size_elem) { - global_State *g = G(L); void *newblock; size_t oldsize = cast_sizet((*size) * size_elem); size_t newsize = cast_sizet(final_n * size_elem); lua_assert(newsize <= oldsize); - newblock = (*g->frealloc)(g->ud, block, oldsize, newsize); - if (unlikely(newblock == NULL && final_n > 0)) /* allocation failed? */ - luaM_error(L); - else { - g->GCdebt += newsize - oldsize; - *size = final_n; - return newblock; - } + newblock = luaM_saferealloc_(L, block, oldsize, newsize); + *size = final_n; + return newblock; } +/* }================================================================== */ + l_noret luaM_toobig (lua_State *L) { luaG_runerror(L, "memory allocation error: block too big"); @@ -143,7 +155,9 @@ static void *tryagain (lua_State *L, void *block, /* -** generic allocation routine. +** Generic allocation routine. +** If allocation fails while shrinking a block, do not try again; the +** GC shrinks some blocks and it is not reentrant. */ void *luaM_realloc_ (lua_State *L, void *block, size_t osize, size_t nsize) { void *newblock; @@ -154,7 +168,7 @@ void *luaM_realloc_ (lua_State *L, void *block, size_t osize, size_t nsize) { if (nsize > osize) /* not shrinking a block? */ newblock = tryagain(L, block, osize, nsize); if (newblock == NULL) /* still no memory? */ - return NULL; + return NULL; /* do not update 'GCdebt' */ } lua_assert((nsize == 0) == (newblock == NULL)); g->GCdebt = (g->GCdebt + nsize) - osize;