aboutsummaryrefslogtreecommitdiff
path: root/lmem.c
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2019-07-19 09:43:35 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2019-07-19 09:43:35 -0300
commit9cdf6b7082c49e6bf7daf8c7c4c649bcaacf9fad (patch)
tree6543c7498f1c455cb2520411b17638bae50ca743 /lmem.c
parent3c1d415bd3fef686b27f853bdf3eaf1f0a9bb0be (diff)
downloadlua-9cdf6b7082c49e6bf7daf8c7c4c649bcaacf9fad.tar.gz
lua-9cdf6b7082c49e6bf7daf8c7c4c649bcaacf9fad.tar.bz2
lua-9cdf6b7082c49e6bf7daf8c7c4c649bcaacf9fad.zip
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.
Diffstat (limited to 'lmem.c')
-rw-r--r--lmem.c62
1 files changed, 38 insertions, 24 deletions
diff --git a/lmem.c b/lmem.c
index 0186a86b..b1d646a5 100644
--- a/lmem.c
+++ b/lmem.c
@@ -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*/
94void *luaM_shrinkvector_ (lua_State *L, void *block, int *size, 110void *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
112l_noret luaM_toobig (lua_State *L) { 124l_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*/
148void *luaM_realloc_ (lua_State *L, void *block, size_t osize, size_t nsize) { 162void *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;