diff options
| -rw-r--r-- | lgc.c | 7 | ||||
| -rw-r--r-- | lmem.c | 62 |
2 files changed, 42 insertions, 27 deletions
| @@ -794,10 +794,11 @@ static GCObject **sweeptolive (lua_State *L, GCObject **p) { | |||
| 794 | */ | 794 | */ |
| 795 | static void checkSizes (lua_State *L, global_State *g) { | 795 | static void checkSizes (lua_State *L, global_State *g) { |
| 796 | if (!g->gcemergency) { | 796 | if (!g->gcemergency) { |
| 797 | l_mem olddebt = g->GCdebt; | 797 | if (g->strt.nuse < g->strt.size / 4) { /* string table too big? */ |
| 798 | if (g->strt.nuse < g->strt.size / 4) /* string table too big? */ | 798 | l_mem olddebt = g->GCdebt; |
| 799 | luaS_resize(L, g->strt.size / 2); | 799 | luaS_resize(L, g->strt.size / 2); |
| 800 | g->GCestimate += g->GCdebt - olddebt; /* correct estimate */ | 800 | g->GCestimate += g->GCdebt - olddebt; /* correct estimate */ |
| 801 | } | ||
| 801 | } | 802 | } |
| 802 | } | 803 | } |
| 803 | 804 | ||
| @@ -44,23 +44,35 @@ static void *firsttry (global_State *g, void *block, size_t os, size_t ns) { | |||
| 44 | 44 | ||
| 45 | /* | 45 | /* |
| 46 | ** About the realloc function: | 46 | ** About the realloc function: |
| 47 | ** void * frealloc (void *ud, void *ptr, size_t osize, size_t nsize); | 47 | ** void *frealloc (void *ud, void *ptr, size_t osize, size_t nsize); |
| 48 | ** ('osize' is the old size, 'nsize' is the new size) | 48 | ** ('osize' is the old size, 'nsize' is the new size) |
| 49 | ** | 49 | ** |
| 50 | ** * frealloc(ud, NULL, x, s) creates a new block of size 's' (no | 50 | ** - frealloc(ud, p, x, 0) frees the block 'p' and returns NULL. |
| 51 | ** matter 'x'). | 51 | ** Particularly, frealloc(ud, NULL, 0, 0) does nothing, |
| 52 | ** which is equivalent to free(NULL) in ISO C. | ||
| 52 | ** | 53 | ** |
| 53 | ** * frealloc(ud, p, x, 0) frees the block 'p' | 54 | ** - frealloc(ud, NULL, x, s) creates a new block of size 's' |
| 54 | ** (in this specific case, frealloc must return NULL); | 55 | ** (no matter 'x'). Returns NULL if it cannot create the new block. |
| 55 | ** particularly, frealloc(ud, NULL, 0, 0) does nothing | ||
| 56 | ** (which is equivalent to free(NULL) in ISO C) | ||
| 57 | ** | 56 | ** |
| 58 | ** frealloc returns NULL if it cannot create or reallocate the area | 57 | ** - otherwise, frealloc(ud, b, x, y) reallocates the block 'b' from |
| 59 | ** (any reallocation to an equal or smaller size cannot fail!) | 58 | ** size 'x' to size 'y'. Returns NULL if it cannot reallocate the |
| 59 | ** block to the new size. | ||
| 60 | */ | 60 | */ |
| 61 | 61 | ||
| 62 | 62 | ||
| 63 | 63 | ||
| 64 | |||
| 65 | /* | ||
| 66 | ** {================================================================== | ||
| 67 | ** Functions to allocate/deallocate arrays for the Parser | ||
| 68 | ** =================================================================== | ||
| 69 | */ | ||
| 70 | |||
| 71 | /* | ||
| 72 | ** Minimum size for arrays during parsing, to avoid overhead of | ||
| 73 | ** reallocating to size 1, then 2, and then 4. All these arrays | ||
| 74 | ** will be reallocated to exact sizes or erased when parsing ends. | ||
| 75 | */ | ||
| 64 | #define MINSIZEARRAY 4 | 76 | #define MINSIZEARRAY 4 |
| 65 | 77 | ||
| 66 | 78 | ||
| @@ -82,32 +94,32 @@ void *luaM_growaux_ (lua_State *L, void *block, int nelems, int *psize, | |||
| 82 | } | 94 | } |
| 83 | lua_assert(nelems + 1 <= size && size <= limit); | 95 | lua_assert(nelems + 1 <= size && size <= limit); |
| 84 | /* 'limit' ensures that multiplication will not overflow */ | 96 | /* 'limit' ensures that multiplication will not overflow */ |
| 85 | newblock = luaM_realloc_(L, block, cast_sizet(*psize) * size_elems, | 97 | newblock = luaM_saferealloc_(L, block, cast_sizet(*psize) * size_elems, |
| 86 | cast_sizet(size) * size_elems); | 98 | cast_sizet(size) * size_elems); |
| 87 | if (unlikely(newblock == NULL)) | ||
| 88 | luaM_error(L); | ||
| 89 | *psize = size; /* update only when everything else is OK */ | 99 | *psize = size; /* update only when everything else is OK */ |
| 90 | return newblock; | 100 | return newblock; |
| 91 | } | 101 | } |
| 92 | 102 | ||
| 93 | 103 | ||
| 104 | /* | ||
| 105 | ** In prototypes, the size of the array is also its number of | ||
| 106 | ** elements (to save memory). So, if it cannot shrink an array | ||
| 107 | ** to its number of elements, the only option is to raise an | ||
| 108 | ** error. | ||
| 109 | */ | ||
| 94 | void *luaM_shrinkvector_ (lua_State *L, void *block, int *size, | 110 | void *luaM_shrinkvector_ (lua_State *L, void *block, int *size, |
| 95 | int final_n, int size_elem) { | 111 | int final_n, int size_elem) { |
| 96 | global_State *g = G(L); | ||
| 97 | void *newblock; | 112 | void *newblock; |
| 98 | size_t oldsize = cast_sizet((*size) * size_elem); | 113 | size_t oldsize = cast_sizet((*size) * size_elem); |
| 99 | size_t newsize = cast_sizet(final_n * size_elem); | 114 | size_t newsize = cast_sizet(final_n * size_elem); |
| 100 | lua_assert(newsize <= oldsize); | 115 | lua_assert(newsize <= oldsize); |
| 101 | newblock = (*g->frealloc)(g->ud, block, oldsize, newsize); | 116 | newblock = luaM_saferealloc_(L, block, oldsize, newsize); |
| 102 | if (unlikely(newblock == NULL && final_n > 0)) /* allocation failed? */ | 117 | *size = final_n; |
| 103 | luaM_error(L); | 118 | return newblock; |
| 104 | else { | ||
| 105 | g->GCdebt += newsize - oldsize; | ||
| 106 | *size = final_n; | ||
| 107 | return newblock; | ||
| 108 | } | ||
| 109 | } | 119 | } |
| 110 | 120 | ||
| 121 | /* }================================================================== */ | ||
| 122 | |||
| 111 | 123 | ||
| 112 | l_noret luaM_toobig (lua_State *L) { | 124 | l_noret luaM_toobig (lua_State *L) { |
| 113 | luaG_runerror(L, "memory allocation error: block too big"); | 125 | luaG_runerror(L, "memory allocation error: block too big"); |
| @@ -143,7 +155,9 @@ static void *tryagain (lua_State *L, void *block, | |||
| 143 | 155 | ||
| 144 | 156 | ||
| 145 | /* | 157 | /* |
| 146 | ** generic allocation routine. | 158 | ** 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. | ||
| 147 | */ | 161 | */ |
| 148 | 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) { |
| 149 | void *newblock; | 163 | void *newblock; |
| @@ -154,7 +168,7 @@ void *luaM_realloc_ (lua_State *L, void *block, size_t osize, size_t nsize) { | |||
| 154 | if (nsize > osize) /* not shrinking a block? */ | 168 | if (nsize > osize) /* not shrinking a block? */ |
| 155 | newblock = tryagain(L, block, osize, nsize); | 169 | newblock = tryagain(L, block, osize, nsize); |
| 156 | if (newblock == NULL) /* still no memory? */ | 170 | if (newblock == NULL) /* still no memory? */ |
| 157 | return NULL; | 171 | return NULL; /* do not update 'GCdebt' */ |
| 158 | } | 172 | } |
| 159 | lua_assert((nsize == 0) == (newblock == NULL)); | 173 | lua_assert((nsize == 0) == (newblock == NULL)); |
| 160 | g->GCdebt = (g->GCdebt + nsize) - osize; | 174 | g->GCdebt = (g->GCdebt + nsize) - osize; |
