diff options
Diffstat (limited to 'lmem.c')
-rw-r--r-- | lmem.c | 25 |
1 files changed, 12 insertions, 13 deletions
@@ -24,12 +24,12 @@ | |||
24 | 24 | ||
25 | #if defined(EMERGENCYGCTESTS) | 25 | #if defined(EMERGENCYGCTESTS) |
26 | /* | 26 | /* |
27 | ** First allocation will fail whenever not building initial state | 27 | ** First allocation will fail whenever not building initial state. |
28 | ** and not shrinking a block. (This fail will trigger 'tryagain' and | 28 | ** (This fail will trigger 'tryagain' and a full GC cycle at every |
29 | ** a full GC cycle at every allocation.) | 29 | ** allocation.) |
30 | */ | 30 | */ |
31 | static void *firsttry (global_State *g, void *block, size_t os, size_t ns) { | 31 | static void *firsttry (global_State *g, void *block, size_t os, size_t ns) { |
32 | if (completestate(g) && ns > os) | 32 | if (completestate(g) && ns > 0) /* frees never fail */ |
33 | return NULL; /* fail */ | 33 | return NULL; /* fail */ |
34 | else /* normal allocation */ | 34 | else /* normal allocation */ |
35 | return (*g->frealloc)(g->ud, block, os, ns); | 35 | return (*g->frealloc)(g->ud, block, os, ns); |
@@ -138,15 +138,17 @@ void luaM_free_ (lua_State *L, void *block, size_t osize) { | |||
138 | 138 | ||
139 | 139 | ||
140 | /* | 140 | /* |
141 | ** In case of allocation fail, this function will call the GC to try | 141 | ** In case of allocation fail, this function will do an emergency |
142 | ** to free some memory and then try the allocation again. | 142 | ** collection to free some memory and then try the allocation again. |
143 | ** (It should not be called when shrinking a block, because then the | 143 | ** The GC should not be called while state is not fully built, as the |
144 | ** interpreter may be in the middle of a collection step.) | 144 | ** collector is not yet fully initialized. Also, it should not be called |
145 | ** when 'gcstopem' is true, because then the interpreter is in the | ||
146 | ** middle of a collection step. | ||
145 | */ | 147 | */ |
146 | static void *tryagain (lua_State *L, void *block, | 148 | static void *tryagain (lua_State *L, void *block, |
147 | size_t osize, size_t nsize) { | 149 | size_t osize, size_t nsize) { |
148 | global_State *g = G(L); | 150 | global_State *g = G(L); |
149 | if (completestate(g)) { /* is state fully build? */ | 151 | if (completestate(g) && !g->gcstopem) { |
150 | luaC_fullgc(L, 1); /* try to free some memory... */ | 152 | luaC_fullgc(L, 1); /* try to free some memory... */ |
151 | return (*g->frealloc)(g->ud, block, osize, nsize); /* try again */ | 153 | return (*g->frealloc)(g->ud, block, osize, nsize); /* try again */ |
152 | } | 154 | } |
@@ -156,8 +158,6 @@ static void *tryagain (lua_State *L, void *block, | |||
156 | 158 | ||
157 | /* | 159 | /* |
158 | ** Generic allocation routine. | 160 | ** Generic allocation routine. |
159 | ** If allocation fails while shrinking a block, do not try again; the | ||
160 | ** GC shrinks some blocks and it is not reentrant. | ||
161 | */ | 161 | */ |
162 | void *luaM_realloc_ (lua_State *L, void *block, size_t osize, size_t nsize) { | 162 | void *luaM_realloc_ (lua_State *L, void *block, size_t osize, size_t nsize) { |
163 | void *newblock; | 163 | void *newblock; |
@@ -165,8 +165,7 @@ void *luaM_realloc_ (lua_State *L, void *block, size_t osize, size_t nsize) { | |||
165 | lua_assert((osize == 0) == (block == NULL)); | 165 | lua_assert((osize == 0) == (block == NULL)); |
166 | newblock = firsttry(g, block, osize, nsize); | 166 | newblock = firsttry(g, block, osize, nsize); |
167 | if (l_unlikely(newblock == NULL && nsize > 0)) { | 167 | if (l_unlikely(newblock == NULL && nsize > 0)) { |
168 | if (nsize > osize) /* not shrinking a block? */ | 168 | newblock = tryagain(L, block, osize, nsize); |
169 | newblock = tryagain(L, block, osize, nsize); | ||
170 | if (newblock == NULL) /* still no memory? */ | 169 | if (newblock == NULL) /* still no memory? */ |
171 | return NULL; /* do not update 'GCdebt' */ | 170 | return NULL; /* do not update 'GCdebt' */ |
172 | } | 171 | } |