|
@@ -24,12 +24,12 @@
|
|
|
|
|
|
#if defined(EMERGENCYGCTESTS)
|
|
|
/*
|
|
|
-** First allocation will fail whenever not building initial state
|
|
|
-** and not shrinking a block. (This fail will trigger 'tryagain' and
|
|
|
-** a full GC cycle at every allocation.)
|
|
|
+** First allocation will fail whenever not building initial state.
|
|
|
+** (This fail will trigger 'tryagain' and a full GC cycle at every
|
|
|
+** allocation.)
|
|
|
*/
|
|
|
static void *firsttry (global_State *g, void *block, size_t os, size_t ns) {
|
|
|
- if (completestate(g) && ns > os)
|
|
|
+ if (completestate(g) && ns > 0) /* frees never fail */
|
|
|
return NULL; /* fail */
|
|
|
else /* normal allocation */
|
|
|
return (*g->frealloc)(g->ud, block, os, ns);
|
|
@@ -138,15 +138,17 @@ void luaM_free_ (lua_State *L, void *block, size_t osize) {
|
|
|
|
|
|
|
|
|
/*
|
|
|
-** In case of allocation fail, this function will call the GC to try
|
|
|
-** to free some memory and then try the allocation again.
|
|
|
-** (It should not be called when shrinking a block, because then the
|
|
|
-** interpreter may be in the middle of a collection step.)
|
|
|
+** In case of allocation fail, this function will do an emergency
|
|
|
+** collection to free some memory and then try the allocation again.
|
|
|
+** The GC should not be called while state is not fully built, as the
|
|
|
+** collector is not yet fully initialized. Also, it should not be called
|
|
|
+** when 'gcstopem' is true, because then the interpreter is in the
|
|
|
+** middle of a collection step.
|
|
|
*/
|
|
|
static void *tryagain (lua_State *L, void *block,
|
|
|
size_t osize, size_t nsize) {
|
|
|
global_State *g = G(L);
|
|
|
- if (completestate(g)) { /* is state fully build? */
|
|
|
+ if (completestate(g) && !g->gcstopem) {
|
|
|
luaC_fullgc(L, 1); /* try to free some memory... */
|
|
|
return (*g->frealloc)(g->ud, block, osize, nsize); /* try again */
|
|
|
}
|
|
@@ -156,8 +158,6 @@ static void *tryagain (lua_State *L, void *block,
|
|
|
|
|
|
/*
|
|
|
** 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;
|
|
@@ -165,8 +165,7 @@ void *luaM_realloc_ (lua_State *L, void *block, size_t osize, size_t nsize) {
|
|
|
lua_assert((osize == 0) == (block == NULL));
|
|
|
newblock = firsttry(g, block, osize, nsize);
|
|
|
if (l_unlikely(newblock == NULL && nsize > 0)) {
|
|
|
- if (nsize > osize) /* not shrinking a block? */
|
|
|
- newblock = tryagain(L, block, osize, nsize);
|
|
|
+ newblock = tryagain(L, block, osize, nsize);
|
|
|
if (newblock == NULL) /* still no memory? */
|
|
|
return NULL; /* do not update 'GCdebt' */
|
|
|
}
|