diff options
Diffstat (limited to 'lmem.c')
-rw-r--r-- | lmem.c | 62 |
1 files changed, 38 insertions, 24 deletions
@@ -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; |