diff options
-rw-r--r-- | lapi.c | 14 | ||||
-rw-r--r-- | ldo.c | 42 | ||||
-rw-r--r-- | ldo.h | 9 | ||||
-rw-r--r-- | lgc.c | 11 | ||||
-rw-r--r-- | lmem.c | 30 | ||||
-rw-r--r-- | lmem.h | 23 | ||||
-rw-r--r-- | lstring.c | 7 | ||||
-rw-r--r-- | ltable.c | 95 |
8 files changed, 136 insertions, 95 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lapi.c,v 2.277 2017/11/23 19:29:04 roberto Exp roberto $ | 2 | ** $Id: lapi.c,v 2.278 2017/12/06 18:08:03 roberto Exp roberto $ |
3 | ** Lua API | 3 | ** Lua API |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -99,16 +99,6 @@ static StkId index2stack (lua_State *L, int idx) { | |||
99 | } | 99 | } |
100 | 100 | ||
101 | 101 | ||
102 | /* | ||
103 | ** to be called by 'lua_checkstack' in protected mode, to grow stack | ||
104 | ** capturing memory errors | ||
105 | */ | ||
106 | static void growstack (lua_State *L, void *ud) { | ||
107 | int size = *(int *)ud; | ||
108 | luaD_growstack(L, size); | ||
109 | } | ||
110 | |||
111 | |||
112 | LUA_API int lua_checkstack (lua_State *L, int n) { | 102 | LUA_API int lua_checkstack (lua_State *L, int n) { |
113 | int res; | 103 | int res; |
114 | CallInfo *ci = L->ci; | 104 | CallInfo *ci = L->ci; |
@@ -121,7 +111,7 @@ LUA_API int lua_checkstack (lua_State *L, int n) { | |||
121 | if (inuse > LUAI_MAXSTACK - n) /* can grow without overflow? */ | 111 | if (inuse > LUAI_MAXSTACK - n) /* can grow without overflow? */ |
122 | res = 0; /* no */ | 112 | res = 0; /* no */ |
123 | else /* try to grow stack */ | 113 | else /* try to grow stack */ |
124 | res = (luaD_rawrunprotected(L, &growstack, &n) == LUA_OK); | 114 | res = luaD_growstack(L, n, 0); |
125 | } | 115 | } |
126 | if (res && ci->top < L->top + n) | 116 | if (res && ci->top < L->top + n) |
127 | ci->top = L->top + n; /* adjust frame top */ | 117 | ci->top = L->top + n; /* adjust frame top */ |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: ldo.c,v 2.176 2017/11/29 13:02:17 roberto Exp roberto $ | 2 | ** $Id: ldo.c,v 2.177 2017/12/01 15:44:51 roberto Exp roberto $ |
3 | ** Stack and Call structure of Lua | 3 | ** Stack and Call structure of Lua |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -156,17 +156,17 @@ int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud) { | |||
156 | ** Stack reallocation | 156 | ** Stack reallocation |
157 | ** =================================================================== | 157 | ** =================================================================== |
158 | */ | 158 | */ |
159 | static void correctstack (lua_State *L, StkId oldstack) { | 159 | static void correctstack (lua_State *L, StkId oldstack, StkId newstack) { |
160 | CallInfo *ci; | 160 | CallInfo *ci; |
161 | UpVal *up; | 161 | UpVal *up; |
162 | if (L->stack == oldstack) | 162 | if (oldstack == newstack) |
163 | return; /* stack address did not change */ | 163 | return; /* stack address did not change */ |
164 | L->top = (L->top - oldstack) + L->stack; | 164 | L->top = (L->top - oldstack) + newstack; |
165 | for (up = L->openupval; up != NULL; up = up->u.open.next) | 165 | for (up = L->openupval; up != NULL; up = up->u.open.next) |
166 | up->v = s2v((uplevel(up) - oldstack) + L->stack); | 166 | up->v = s2v((uplevel(up) - oldstack) + newstack); |
167 | for (ci = L->ci; ci != NULL; ci = ci->previous) { | 167 | for (ci = L->ci; ci != NULL; ci = ci->previous) { |
168 | ci->top = (ci->top - oldstack) + L->stack; | 168 | ci->top = (ci->top - oldstack) + newstack; |
169 | ci->func = (ci->func - oldstack) + L->stack; | 169 | ci->func = (ci->func - oldstack) + newstack; |
170 | if (isLua(ci)) | 170 | if (isLua(ci)) |
171 | ci->u.l.trap = 1; /* signal to update 'trap' in 'luaV_execute' */ | 171 | ci->u.l.trap = 1; /* signal to update 'trap' in 'luaV_execute' */ |
172 | } | 172 | } |
@@ -177,36 +177,40 @@ static void correctstack (lua_State *L, StkId oldstack) { | |||
177 | #define ERRORSTACKSIZE (LUAI_MAXSTACK + 200) | 177 | #define ERRORSTACKSIZE (LUAI_MAXSTACK + 200) |
178 | 178 | ||
179 | 179 | ||
180 | void luaD_reallocstack (lua_State *L, int newsize) { | 180 | int luaD_reallocstack (lua_State *L, int newsize, int safe) { |
181 | StkId oldstack = L->stack; | ||
182 | int lim = L->stacksize; | 181 | int lim = L->stacksize; |
182 | StkId newstack = luaM_reallocvector(L, L->stack, lim, newsize, StackValue); | ||
183 | lua_assert(newsize <= LUAI_MAXSTACK || newsize == ERRORSTACKSIZE); | 183 | lua_assert(newsize <= LUAI_MAXSTACK || newsize == ERRORSTACKSIZE); |
184 | lua_assert(L->stack_last - L->stack == L->stacksize - EXTRA_STACK); | 184 | lua_assert(L->stack_last - L->stack == L->stacksize - EXTRA_STACK); |
185 | luaM_reallocvector(L, L->stack, L->stacksize, newsize, StackValue); | 185 | if (newstack == NULL) { /* reallocation failed? */ |
186 | if (safe) luaM_error(L); | ||
187 | else return 0; /* no-safe mode: signal the error */ | ||
188 | } | ||
186 | for (; lim < newsize; lim++) | 189 | for (; lim < newsize; lim++) |
187 | setnilvalue(s2v(L->stack + lim)); /* erase new segment */ | 190 | setnilvalue(s2v(newstack + lim)); /* erase new segment */ |
191 | correctstack(L, L->stack, newstack); | ||
192 | L->stack = newstack; | ||
188 | L->stacksize = newsize; | 193 | L->stacksize = newsize; |
189 | L->stack_last = L->stack + newsize - EXTRA_STACK; | 194 | L->stack_last = L->stack + newsize - EXTRA_STACK; |
190 | correctstack(L, oldstack); | 195 | return 1; |
191 | } | 196 | } |
192 | 197 | ||
193 | 198 | ||
194 | void luaD_growstack (lua_State *L, int n) { | 199 | int luaD_growstack (lua_State *L, int n, int safe) { |
195 | int size = L->stacksize; | 200 | int size = L->stacksize; |
201 | int newsize = 2 * size; | ||
196 | if (size > LUAI_MAXSTACK) /* error after extra size? */ | 202 | if (size > LUAI_MAXSTACK) /* error after extra size? */ |
197 | luaD_throw(L, LUA_ERRERR); | 203 | luaD_throw(L, LUA_ERRERR); |
198 | else { | 204 | else { |
199 | int needed = cast_int(L->top - L->stack) + n + EXTRA_STACK; | 205 | int needed = cast_int(L->top - L->stack) + n + EXTRA_STACK; |
200 | int newsize = 2 * size; | ||
201 | if (newsize > LUAI_MAXSTACK) newsize = LUAI_MAXSTACK; | 206 | if (newsize > LUAI_MAXSTACK) newsize = LUAI_MAXSTACK; |
202 | if (newsize < needed) newsize = needed; | 207 | if (newsize < needed) newsize = needed; |
203 | if (newsize > LUAI_MAXSTACK) { /* stack overflow? */ | 208 | if (newsize > LUAI_MAXSTACK) { /* stack overflow? */ |
204 | luaD_reallocstack(L, ERRORSTACKSIZE); | 209 | luaD_reallocstack(L, ERRORSTACKSIZE, 1); |
205 | luaG_runerror(L, "stack overflow"); | 210 | luaG_runerror(L, "stack overflow"); |
206 | } | 211 | } |
207 | else | 212 | } /* else */ |
208 | luaD_reallocstack(L, newsize); | 213 | return luaD_reallocstack(L, newsize, safe); |
209 | } | ||
210 | } | 214 | } |
211 | 215 | ||
212 | 216 | ||
@@ -234,7 +238,7 @@ void luaD_shrinkstack (lua_State *L) { | |||
234 | good size is smaller than current size, shrink its stack */ | 238 | good size is smaller than current size, shrink its stack */ |
235 | if (inuse <= (LUAI_MAXSTACK - EXTRA_STACK) && | 239 | if (inuse <= (LUAI_MAXSTACK - EXTRA_STACK) && |
236 | goodsize < L->stacksize) | 240 | goodsize < L->stacksize) |
237 | luaD_reallocstack(L, goodsize); | 241 | luaD_reallocstack(L, goodsize, 0); /* ok if that fails */ |
238 | else /* don't change stack */ | 242 | else /* don't change stack */ |
239 | condmovestack(L,{},{}); /* (change only for debugging) */ | 243 | condmovestack(L,{},{}); /* (change only for debugging) */ |
240 | } | 244 | } |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: ldo.h,v 2.35 2017/11/23 16:35:54 roberto Exp roberto $ | 2 | ** $Id: ldo.h,v 2.36 2017/11/23 18:29:41 roberto Exp roberto $ |
3 | ** Stack and Call structure of Lua | 3 | ** Stack and Call structure of Lua |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -22,7 +22,8 @@ | |||
22 | */ | 22 | */ |
23 | #define luaD_checkstackaux(L,n,pre,pos) \ | 23 | #define luaD_checkstackaux(L,n,pre,pos) \ |
24 | if (L->stack_last - L->top <= (n)) \ | 24 | if (L->stack_last - L->top <= (n)) \ |
25 | { pre; luaD_growstack(L, n); pos; } else { condmovestack(L,pre,pos); } | 25 | { pre; luaD_growstack(L, n, 1); pos; } \ |
26 | else { condmovestack(L,pre,pos); } | ||
26 | 27 | ||
27 | /* In general, 'pre'/'pos' are empty (nothing to save) */ | 28 | /* In general, 'pre'/'pos' are empty (nothing to save) */ |
28 | #define luaD_checkstack(L,n) luaD_checkstackaux(L,n,(void)0,(void)0) | 29 | #define luaD_checkstack(L,n) luaD_checkstackaux(L,n,(void)0,(void)0) |
@@ -55,8 +56,8 @@ LUAI_FUNC int luaD_pcall (lua_State *L, Pfunc func, void *u, | |||
55 | ptrdiff_t oldtop, ptrdiff_t ef); | 56 | ptrdiff_t oldtop, ptrdiff_t ef); |
56 | LUAI_FUNC void luaD_poscall (lua_State *L, CallInfo *ci, StkId firstResult, | 57 | LUAI_FUNC void luaD_poscall (lua_State *L, CallInfo *ci, StkId firstResult, |
57 | int nres); | 58 | int nres); |
58 | LUAI_FUNC void luaD_reallocstack (lua_State *L, int newsize); | 59 | LUAI_FUNC int luaD_reallocstack (lua_State *L, int newsize, int safe); |
59 | LUAI_FUNC void luaD_growstack (lua_State *L, int n); | 60 | LUAI_FUNC int luaD_growstack (lua_State *L, int n, int safe); |
60 | LUAI_FUNC void luaD_shrinkstack (lua_State *L); | 61 | LUAI_FUNC void luaD_shrinkstack (lua_State *L); |
61 | LUAI_FUNC void luaD_inctop (lua_State *L); | 62 | LUAI_FUNC void luaD_inctop (lua_State *L); |
62 | 63 | ||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lgc.c,v 2.240 2017/11/30 15:37:16 roberto Exp roberto $ | 2 | ** $Id: lgc.c,v 2.241 2017/12/01 17:38:49 roberto Exp roberto $ |
3 | ** Garbage Collector | 3 | ** Garbage Collector |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -816,18 +816,13 @@ static GCObject **sweeptolive (lua_State *L, GCObject **p) { | |||
816 | */ | 816 | */ |
817 | 817 | ||
818 | /* | 818 | /* |
819 | ** If possible, shrink string table (protected from memory errors). | 819 | ** If possible, shrink string table. |
820 | */ | 820 | */ |
821 | static void shrinkstrtable (lua_State *L, void *ud) { | ||
822 | luaS_resize(L, *cast(int*, ud) / 2); | ||
823 | } | ||
824 | |||
825 | |||
826 | static void checkSizes (lua_State *L, global_State *g) { | 821 | static void checkSizes (lua_State *L, global_State *g) { |
827 | if (!g->gcemergency) { | 822 | if (!g->gcemergency) { |
828 | l_mem olddebt = g->GCdebt; | 823 | l_mem olddebt = g->GCdebt; |
829 | if (g->strt.nuse < g->strt.size / 4) /* string table too big? */ | 824 | if (g->strt.nuse < g->strt.size / 4) /* string table too big? */ |
830 | luaD_rawrunprotected(L, &shrinkstrtable, &g->strt.size); | 825 | luaS_resize(L, g->strt.size / 2); |
831 | g->GCestimate += g->GCdebt - olddebt; /* correct estimate */ | 826 | g->GCestimate += g->GCdebt - olddebt; /* correct estimate */ |
832 | } | 827 | } |
833 | } | 828 | } |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lmem.c,v 1.92 2017/12/06 18:36:31 roberto Exp roberto $ | 2 | ** $Id: lmem.c,v 1.93 2017/12/07 18:59:52 roberto Exp roberto $ |
3 | ** Interface to Memory Manager | 3 | ** Interface to Memory Manager |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -69,9 +69,12 @@ void *luaM_growaux_ (lua_State *L, void *block, int nelems, int *psize, | |||
69 | if (size < MINSIZEARRAY) | 69 | if (size < MINSIZEARRAY) |
70 | size = MINSIZEARRAY; /* minimum size */ | 70 | size = MINSIZEARRAY; /* minimum size */ |
71 | } | 71 | } |
72 | lua_assert(nelems + 1 <= size && size <= limit); | ||
72 | /* 'limit' ensures that multiplication will not overflow */ | 73 | /* 'limit' ensures that multiplication will not overflow */ |
73 | newblock = luaM_realloc(L, block, cast(size_t, *psize) * size_elems, | 74 | newblock = luaM_realloc_(L, block, cast(size_t, *psize) * size_elems, |
74 | cast(size_t, size) * size_elems); | 75 | cast(size_t, size) * size_elems); |
76 | if (newblock == NULL) | ||
77 | luaM_error(L); | ||
75 | *psize = size; /* update only when everything else is OK */ | 78 | *psize = size; /* update only when everything else is OK */ |
76 | return newblock; | 79 | return newblock; |
77 | } | 80 | } |
@@ -115,20 +118,20 @@ void luaM_free_ (lua_State *L, void *block, size_t osize) { | |||
115 | /* | 118 | /* |
116 | ** generic allocation routine. | 119 | ** generic allocation routine. |
117 | */ | 120 | */ |
118 | void *luaM_realloc (lua_State *L, void *block, size_t osize, size_t nsize) { | 121 | void *luaM_realloc_ (lua_State *L, void *block, size_t osize, size_t nsize) { |
119 | void *newblock; | 122 | void *newblock; |
120 | global_State *g = G(L); | 123 | global_State *g = G(L); |
121 | lua_assert((osize == 0) == (block == NULL)); | 124 | lua_assert((osize == 0) == (block == NULL)); |
122 | hardtest(L, osize, nsize); | 125 | hardtest(L, osize, nsize); |
123 | newblock = (*g->frealloc)(g->ud, block, osize, nsize); | 126 | newblock = (*g->frealloc)(g->ud, block, osize, nsize); |
124 | if (newblock == NULL && nsize > 0) { | 127 | if (newblock == NULL && nsize > 0) { |
125 | lua_assert(nsize > osize); /* cannot fail when shrinking a block */ | 128 | /* Is state fully built? Not shrinking a block? */ |
126 | if (g->version) { /* is state fully built? */ | 129 | if (g->version && nsize > osize) { |
127 | luaC_fullgc(L, 1); /* try to free some memory... */ | 130 | luaC_fullgc(L, 1); /* try to free some memory... */ |
128 | newblock = (*g->frealloc)(g->ud, block, osize, nsize); /* try again */ | 131 | newblock = (*g->frealloc)(g->ud, block, osize, nsize); /* try again */ |
129 | } | 132 | } |
130 | if (newblock == NULL) | 133 | if (newblock == NULL) |
131 | luaD_throw(L, LUA_ERRMEM); | 134 | return NULL; |
132 | } | 135 | } |
133 | lua_assert((nsize == 0) == (newblock == NULL)); | 136 | lua_assert((nsize == 0) == (newblock == NULL)); |
134 | g->GCdebt = (g->GCdebt + nsize) - osize; | 137 | g->GCdebt = (g->GCdebt + nsize) - osize; |
@@ -136,7 +139,16 @@ void *luaM_realloc (lua_State *L, void *block, size_t osize, size_t nsize) { | |||
136 | } | 139 | } |
137 | 140 | ||
138 | 141 | ||
139 | void *luaM_malloc (lua_State *L, size_t size, int tag) { | 142 | void *luaM_saferealloc_ (lua_State *L, void *block, size_t osize, |
143 | size_t nsize) { | ||
144 | void *newblock = luaM_realloc_(L, block, osize, nsize); | ||
145 | if (newblock == NULL && nsize > 0) /* allocation failed? */ | ||
146 | luaM_error(L); | ||
147 | return newblock; | ||
148 | } | ||
149 | |||
150 | |||
151 | void *luaM_malloc_ (lua_State *L, size_t size, int tag) { | ||
140 | hardtest(L, 0, size); | 152 | hardtest(L, 0, size); |
141 | if (size == 0) | 153 | if (size == 0) |
142 | return NULL; /* that's all */ | 154 | return NULL; /* that's all */ |
@@ -149,7 +161,7 @@ void *luaM_malloc (lua_State *L, size_t size, int tag) { | |||
149 | newblock = (*g->frealloc)(g->ud, NULL, tag, size); /* try again */ | 161 | newblock = (*g->frealloc)(g->ud, NULL, tag, size); /* try again */ |
150 | } | 162 | } |
151 | if (newblock == NULL) | 163 | if (newblock == NULL) |
152 | luaD_throw(L, LUA_ERRMEM); | 164 | luaM_error(L); |
153 | } | 165 | } |
154 | g->GCdebt += size; | 166 | g->GCdebt += size; |
155 | return newblock; | 167 | return newblock; |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lmem.h,v 1.44 2017/12/06 18:36:31 roberto Exp roberto $ | 2 | ** $Id: lmem.h,v 1.45 2017/12/07 18:59:52 roberto Exp roberto $ |
3 | ** Interface to Memory Manager | 3 | ** Interface to Memory Manager |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -14,6 +14,9 @@ | |||
14 | #include "lua.h" | 14 | #include "lua.h" |
15 | 15 | ||
16 | 16 | ||
17 | #define luaM_error(L) luaD_throw(L, LUA_ERRMEM) | ||
18 | |||
19 | |||
17 | /* | 20 | /* |
18 | ** This macro tests whether it is safe to multiply 'n' by the size of | 21 | ** This macro tests whether it is safe to multiply 'n' by the size of |
19 | ** type 't' without overflows. Because 'e' is always constant, it avoids | 22 | ** type 't' without overflows. Because 'e' is always constant, it avoids |
@@ -45,26 +48,26 @@ | |||
45 | ** Arrays of chars do not need any test | 48 | ** Arrays of chars do not need any test |
46 | */ | 49 | */ |
47 | #define luaM_reallocvchar(L,b,on,n) \ | 50 | #define luaM_reallocvchar(L,b,on,n) \ |
48 | cast(char *, luaM_realloc(L, (b), (on)*sizeof(char), (n)*sizeof(char))) | 51 | cast(char *, luaM_saferealloc_(L, (b), (on)*sizeof(char), (n)*sizeof(char))) |
49 | 52 | ||
50 | #define luaM_freemem(L, b, s) luaM_free_(L, (b), (s)) | 53 | #define luaM_freemem(L, b, s) luaM_free_(L, (b), (s)) |
51 | #define luaM_free(L, b) luaM_free_(L, (b), sizeof(*(b))) | 54 | #define luaM_free(L, b) luaM_free_(L, (b), sizeof(*(b))) |
52 | #define luaM_freearray(L, b, n) luaM_free_(L, (b), (n)*sizeof(*(b))) | 55 | #define luaM_freearray(L, b, n) luaM_free_(L, (b), (n)*sizeof(*(b))) |
53 | 56 | ||
54 | #define luaM_new(L,t) cast(t*, luaM_malloc(L, sizeof(t), 0)) | 57 | #define luaM_new(L,t) cast(t*, luaM_malloc_(L, sizeof(t), 0)) |
55 | #define luaM_newvector(L,n,t) cast(t*, luaM_malloc(L, (n)*sizeof(t), 0)) | 58 | #define luaM_newvector(L,n,t) cast(t*, luaM_malloc_(L, (n)*sizeof(t), 0)) |
56 | #define luaM_newvectorchecked(L,n,t) \ | 59 | #define luaM_newvectorchecked(L,n,t) \ |
57 | (luaM_checksize(L,n,sizeof(t)), luaM_newvector(L,n,t)) | 60 | (luaM_checksize(L,n,sizeof(t)), luaM_newvector(L,n,t)) |
58 | 61 | ||
59 | #define luaM_newobject(L,tag,s) luaM_malloc(L, (s), tag) | 62 | #define luaM_newobject(L,tag,s) luaM_malloc_(L, (s), tag) |
60 | 63 | ||
61 | #define luaM_growvector(L,v,nelems,size,t,limit,e) \ | 64 | #define luaM_growvector(L,v,nelems,size,t,limit,e) \ |
62 | ((v)=cast(t *, luaM_growaux_(L,v,nelems,&(size),sizeof(t), \ | 65 | ((v)=cast(t *, luaM_growaux_(L,v,nelems,&(size),sizeof(t), \ |
63 | luaM_limitN(limit,t),e))) | 66 | luaM_limitN(limit,t),e))) |
64 | 67 | ||
65 | #define luaM_reallocvector(L, v,oldn,n,t) \ | 68 | #define luaM_reallocvector(L, v,oldn,n,t) \ |
66 | ((v)=cast(t *, luaM_realloc(L, v, cast(size_t, oldn) * sizeof(t), \ | 69 | (cast(t *, luaM_realloc_(L, v, cast(size_t, oldn) * sizeof(t), \ |
67 | cast(size_t, n) * sizeof(t)))) | 70 | cast(size_t, n) * sizeof(t)))) |
68 | 71 | ||
69 | #define luaM_shrinkvector(L,v,size,fs,t) \ | 72 | #define luaM_shrinkvector(L,v,size,fs,t) \ |
70 | ((v)=cast(t *, luaM_shrinkvector_(L, v, &(size), fs, sizeof(t)))) | 73 | ((v)=cast(t *, luaM_shrinkvector_(L, v, &(size), fs, sizeof(t)))) |
@@ -72,15 +75,17 @@ | |||
72 | LUAI_FUNC l_noret luaM_toobig (lua_State *L); | 75 | LUAI_FUNC l_noret luaM_toobig (lua_State *L); |
73 | 76 | ||
74 | /* not to be called directly */ | 77 | /* not to be called directly */ |
75 | LUAI_FUNC void *luaM_realloc (lua_State *L, void *block, size_t oldsize, | 78 | LUAI_FUNC void *luaM_realloc_ (lua_State *L, void *block, size_t oldsize, |
76 | size_t size); | 79 | size_t size); |
80 | LUAI_FUNC void *luaM_saferealloc_ (lua_State *L, void *block, size_t oldsize, | ||
81 | size_t size); | ||
77 | LUAI_FUNC void luaM_free_ (lua_State *L, void *block, size_t osize); | 82 | LUAI_FUNC void luaM_free_ (lua_State *L, void *block, size_t osize); |
78 | LUAI_FUNC void *luaM_growaux_ (lua_State *L, void *block, int nelems, | 83 | LUAI_FUNC void *luaM_growaux_ (lua_State *L, void *block, int nelems, |
79 | int *size, int size_elem, int limit, | 84 | int *size, int size_elem, int limit, |
80 | const char *what); | 85 | const char *what); |
81 | LUAI_FUNC void *luaM_shrinkvector_ (lua_State *L, void *block, int *nelem, | 86 | LUAI_FUNC void *luaM_shrinkvector_ (lua_State *L, void *block, int *nelem, |
82 | int final_n, int size_elem); | 87 | int final_n, int size_elem); |
83 | LUAI_FUNC void *luaM_malloc (lua_State *L, size_t size, int tag); | 88 | LUAI_FUNC void *luaM_malloc_ (lua_State *L, size_t size, int tag); |
84 | 89 | ||
85 | #endif | 90 | #endif |
86 | 91 | ||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lstring.c,v 2.58 2017/12/01 16:40:29 roberto Exp roberto $ | 2 | ** $Id: lstring.c,v 2.59 2017/12/07 18:59:52 roberto Exp roberto $ |
3 | ** String table (keeps all strings handled by Lua) | 3 | ** String table (keeps all strings handled by Lua) |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -70,12 +70,15 @@ unsigned int luaS_hashlongstr (TString *ts) { | |||
70 | 70 | ||
71 | 71 | ||
72 | /* | 72 | /* |
73 | ** Resizes the string table. | 73 | ** Resize the string table. If allocation fails, keep the current size. |
74 | ** (This can degrade performance, but any size should work correctly.) | ||
74 | */ | 75 | */ |
75 | void luaS_resize (lua_State *L, int newsize) { | 76 | void luaS_resize (lua_State *L, int newsize) { |
76 | int i; | 77 | int i; |
77 | TString **newhash = luaM_newvector(L, newsize, TString *); | 78 | TString **newhash = luaM_newvector(L, newsize, TString *); |
78 | stringtable *tb = &G(L)->strt; | 79 | stringtable *tb = &G(L)->strt; |
80 | if (newhash == NULL) /* allocation failed? */ | ||
81 | return; /* leave hash as it is */ | ||
79 | for (i = 0; i < newsize; i++) /* initialize new hash array */ | 82 | for (i = 0; i < newsize; i++) /* initialize new hash array */ |
80 | newhash[i] = NULL; | 83 | newhash[i] = NULL; |
81 | for (i = 0; i < tb->size; i++) { /* rehash all elements into new array */ | 84 | for (i = 0; i < tb->size; i++) { /* rehash all elements into new array */ |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: ltable.c,v 2.127 2017/11/23 19:29:04 roberto Exp roberto $ | 2 | ** $Id: ltable.c,v 2.128 2017/12/07 18:59:52 roberto Exp roberto $ |
3 | ** Lua tables (hash) | 3 | ** Lua tables (hash) |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -357,15 +357,6 @@ static int numusehash (const Table *t, unsigned int *nums, unsigned int *pna) { | |||
357 | } | 357 | } |
358 | 358 | ||
359 | 359 | ||
360 | static void setarrayvector (lua_State *L, Table *t, unsigned int size) { | ||
361 | unsigned int i; | ||
362 | luaM_reallocvector(L, t->array, t->sizearray, size, TValue); | ||
363 | for (i=t->sizearray; i<size; i++) | ||
364 | setnilvalue(&t->array[i]); | ||
365 | t->sizearray = size; | ||
366 | } | ||
367 | |||
368 | |||
369 | /* | 360 | /* |
370 | ** Creates an array for the hash part of a table with the given | 361 | ** Creates an array for the hash part of a table with the given |
371 | ** size, or reuses the dummy node if size is zero. | 362 | ** size, or reuses the dummy node if size is zero. |
@@ -398,39 +389,79 @@ static void setnodevector (lua_State *L, Table *t, unsigned int size) { | |||
398 | } | 389 | } |
399 | 390 | ||
400 | 391 | ||
401 | void luaH_resize (lua_State *L, Table *t, unsigned int nasize, | 392 | /* |
393 | ** (Re)insert all elements from list 'nodes' into table 't'. | ||
394 | */ | ||
395 | static void reinsert(lua_State *L, Node *nodes, int nsize, Table *t) { | ||
396 | int j; | ||
397 | for (j = nsize - 1; j >= 0; j--) { | ||
398 | Node *old = nodes + j; | ||
399 | if (!ttisnil(gval(old))) { | ||
400 | /* doesn't need barrier/invalidate cache, as entry was | ||
401 | already present in the table */ | ||
402 | TValue k; | ||
403 | getnodekey(L, &k, old); | ||
404 | setobjt2t(L, luaH_set(L, t, &k), gval(old)); | ||
405 | } | ||
406 | } | ||
407 | } | ||
408 | |||
409 | |||
410 | /* | ||
411 | ** Resize table 't' for the new given sizes. Both allocations | ||
412 | ** (for the hash part and for the array part) can fail, which | ||
413 | ** creates some subtleties. If the first allocation, for the hash | ||
414 | ** part, fails, an error is raised and that is it. Otherwise, | ||
415 | ** copy the elements in the shrinking part of the array (if it | ||
416 | ** is shrinking) into the new hash. Then it reallocates the array part. | ||
417 | ** If that fails, it frees the new hash part and restores the old hash | ||
418 | ** part (to restore the original state of the table), and then raises | ||
419 | ** the allocation error. Otherwise, initialize the new part of the | ||
420 | ** array (if any) with nils and reinsert the elements in the old | ||
421 | ** hash back into the new parts of the table. | ||
422 | */ | ||
423 | void luaH_resize (lua_State *L, Table *t, unsigned int newasize, | ||
402 | unsigned int nhsize) { | 424 | unsigned int nhsize) { |
403 | unsigned int i; | 425 | unsigned int i; |
404 | int j; | 426 | Node *oldnode = t->node; /* save old hash ... */ |
405 | unsigned int oldasize = t->sizearray; | 427 | Node *oldlastfree = t->lastfree; |
428 | int oldlsizenode = t->lsizenode; | ||
406 | int oldhsize = allocsizenode(t); | 429 | int oldhsize = allocsizenode(t); |
407 | Node *nold = t->node; /* save old hash ... */ | 430 | unsigned int oldasize = t->sizearray; |
408 | if (nasize > oldasize) /* array part must grow? */ | 431 | TValue *newarray; |
409 | setarrayvector(L, t, nasize); | ||
410 | /* create new hash part with appropriate size */ | 432 | /* create new hash part with appropriate size */ |
411 | setnodevector(L, t, nhsize); | 433 | setnodevector(L, t, nhsize); |
412 | if (nasize < oldasize) { /* array part must shrink? */ | 434 | if (newasize < oldasize) { /* will array shrink? */ |
413 | t->sizearray = nasize; | 435 | /* re-insert into the hash the elements from vanishing slice */ |
414 | /* re-insert elements from vanishing slice */ | 436 | t->sizearray = newasize; /* pretend array has new size */ |
415 | for (i=nasize; i<oldasize; i++) { | 437 | for (i = newasize; i < oldasize; i++) { |
416 | if (!ttisnil(&t->array[i])) | 438 | if (!ttisnil(&t->array[i])) |
417 | luaH_setint(L, t, i + 1, &t->array[i]); | 439 | luaH_setint(L, t, i + 1, &t->array[i]); |
418 | } | 440 | } |
419 | /* shrink array */ | 441 | t->sizearray = oldasize; /* restore current size */ |
420 | luaM_reallocvector(L, t->array, oldasize, nasize, TValue); | ||
421 | } | 442 | } |
422 | /* re-insert elements from hash part */ | 443 | /* allocate new array */ |
423 | for (j = oldhsize - 1; j >= 0; j--) { | 444 | newarray = luaM_reallocvector(L, t->array, oldasize, newasize, TValue); |
424 | Node *old = nold + j; | 445 | if (newarray == NULL && newasize > 0) { /* allocation failed? */ |
425 | if (!ttisnil(gval(old))) { | 446 | if (nhsize > 0) /* not the dummy node? */ |
426 | /* doesn't need barrier/invalidate cache, as entry was | 447 | luaM_freearray(L, t->node, allocsizenode(t)); /* release new hash part */ |
427 | already present in the table */ | 448 | t->node = oldnode; /* restore original hash part */ |
428 | TValue k; getnodekey(L, &k, old); | 449 | t->lastfree = oldlastfree; |
429 | setobjt2t(L, luaH_set(L, t, &k), gval(old)); | 450 | t->lsizenode = oldlsizenode; |
430 | } | 451 | lua_assert(!isdummy(t) == (t->node != dummynode)); |
452 | luaM_error(L); /* error with array unchanged */ | ||
431 | } | 453 | } |
454 | /* allocation ok; initialize new part of the array */ | ||
455 | t->array = newarray; | ||
456 | t->sizearray = newasize; | ||
457 | for (i = oldasize; i < newasize; i++) | ||
458 | setnilvalue(&t->array[i]); | ||
459 | /* re-insert elements from old hash part into new parts */ | ||
460 | reinsert(L, oldnode, oldhsize, t); | ||
461 | /* free old hash */ | ||
432 | if (oldhsize > 0) /* not the dummy node? */ | 462 | if (oldhsize > 0) /* not the dummy node? */ |
433 | luaM_freearray(L, nold, cast(size_t, oldhsize)); /* free old hash */ | 463 | luaM_freearray(L, oldnode, cast(size_t, oldhsize)); |
464 | lua_assert(!isdummy(t) == (t->node != dummynode)); | ||
434 | } | 465 | } |
435 | 466 | ||
436 | 467 | ||