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.
diff --git a/lgc.c b/lgc.c
index aa6921b..6562c92 100644
--- a/lgc.c
+++ b/lgc.c
@@ -794,10 +794,11 @@
*/
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 0186a86..b1d646a 100644
--- a/lmem.c
+++ b/lmem.c
@@ -44,23 +44,35 @@
/*
** 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 @@
}
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 @@
/*
-** 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 @@
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;