diff options
Diffstat (limited to '')
| -rw-r--r-- | lmem.c | 77 | ||||
| -rw-r--r-- | lmem.h | 53 | ||||
| -rw-r--r-- | lparser.c | 25 |
3 files changed, 108 insertions, 47 deletions
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lmem.c,v 1.90 2015/03/03 18:18:29 roberto Exp roberto $ | 2 | ** $Id: lmem.c,v 1.91 2015/03/06 19:45:54 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 | */ |
| @@ -22,6 +22,14 @@ | |||
| 22 | #include "lstate.h" | 22 | #include "lstate.h" |
| 23 | 23 | ||
| 24 | 24 | ||
| 25 | #if defined(HARDMEMTESTS) | ||
| 26 | #define hardtest(L,os,s) /* force a GC whenever possible */ \ | ||
| 27 | if ((s) > (os) && (G(L))->gcrunning) luaC_fullgc(L, 1); | ||
| 28 | #else | ||
| 29 | #define hardtest(L,os,s) ((void)0) | ||
| 30 | #endif | ||
| 31 | |||
| 32 | |||
| 25 | 33 | ||
| 26 | /* | 34 | /* |
| 27 | ** About the realloc function: | 35 | ** About the realloc function: |
| @@ -45,10 +53,12 @@ | |||
| 45 | #define MINSIZEARRAY 4 | 53 | #define MINSIZEARRAY 4 |
| 46 | 54 | ||
| 47 | 55 | ||
| 48 | void *luaM_growaux_ (lua_State *L, void *block, int *size, size_t size_elems, | 56 | void *luaM_growaux_ (lua_State *L, void *block, int nelems, int *size, |
| 49 | int limit, const char *what) { | 57 | int size_elems, int limit, const char *what) { |
| 50 | void *newblock; | 58 | void *newblock; |
| 51 | int newsize; | 59 | int newsize; |
| 60 | if (nelems + 1 <= *size) /* does one extra element still fit? */ | ||
| 61 | return block; /* nothing to be done */ | ||
| 52 | if (*size >= limit/2) { /* cannot double it? */ | 62 | if (*size >= limit/2) { /* cannot double it? */ |
| 53 | if (*size >= limit) /* cannot grow even a little? */ | 63 | if (*size >= limit) /* cannot grow even a little? */ |
| 54 | luaG_runerror(L, "too many %s (limit is %d)", what, limit); | 64 | luaG_runerror(L, "too many %s (limit is %d)", what, limit); |
| @@ -65,11 +75,40 @@ void *luaM_growaux_ (lua_State *L, void *block, int *size, size_t size_elems, | |||
| 65 | } | 75 | } |
| 66 | 76 | ||
| 67 | 77 | ||
| 78 | void *luaM_shrinkvector_ (lua_State *L, void *block, int *size, | ||
| 79 | int final_n, int size_elem) { | ||
| 80 | global_State *g = G(L); | ||
| 81 | void *newblock; | ||
| 82 | size_t oldsize = cast(size_t, (*size) * size_elem); | ||
| 83 | size_t newsize = cast(size_t, final_n * size_elem); | ||
| 84 | lua_assert(newsize <= oldsize); | ||
| 85 | newblock = (*g->frealloc)(g->ud, block, oldsize, newsize); | ||
| 86 | if (newblock == NULL && final_n > 0) /* allocation failed? */ | ||
| 87 | return block; /* keep old block */ | ||
| 88 | else { | ||
| 89 | g->GCdebt += newsize - oldsize; | ||
| 90 | *size = final_n; | ||
| 91 | return newblock; | ||
| 92 | } | ||
| 93 | } | ||
| 94 | |||
| 95 | |||
| 68 | l_noret luaM_toobig (lua_State *L) { | 96 | l_noret luaM_toobig (lua_State *L) { |
| 69 | luaG_runerror(L, "memory allocation error: block too big"); | 97 | luaG_runerror(L, "memory allocation error: block too big"); |
| 70 | } | 98 | } |
| 71 | 99 | ||
| 72 | 100 | ||
| 101 | /* | ||
| 102 | ** Free memory | ||
| 103 | */ | ||
| 104 | void luaM_free_ (lua_State *L, void *block, size_t osize) { | ||
| 105 | global_State *g = G(L); | ||
| 106 | lua_assert((block == 0) == (block == NULL)); | ||
| 107 | (*g->frealloc)(g->ud, block, osize, 0); | ||
| 108 | g->GCdebt -= osize; | ||
| 109 | } | ||
| 110 | |||
| 111 | |||
| 73 | 112 | ||
| 74 | /* | 113 | /* |
| 75 | ** generic allocation routine. | 114 | ** generic allocation routine. |
| @@ -77,15 +116,11 @@ l_noret luaM_toobig (lua_State *L) { | |||
| 77 | void *luaM_realloc_ (lua_State *L, void *block, size_t osize, size_t nsize) { | 116 | void *luaM_realloc_ (lua_State *L, void *block, size_t osize, size_t nsize) { |
| 78 | void *newblock; | 117 | void *newblock; |
| 79 | global_State *g = G(L); | 118 | global_State *g = G(L); |
| 80 | size_t realosize = (block) ? osize : 0; | 119 | lua_assert((osize == 0) == (block == NULL)); |
| 81 | lua_assert((realosize == 0) == (block == NULL)); | 120 | hardtest(L, osize, nsize); |
| 82 | #if defined(HARDMEMTESTS) | ||
| 83 | if (nsize > realosize && g->gcrunning) | ||
| 84 | luaC_fullgc(L, 1); /* force a GC whenever possible */ | ||
| 85 | #endif | ||
| 86 | newblock = (*g->frealloc)(g->ud, block, osize, nsize); | 121 | newblock = (*g->frealloc)(g->ud, block, osize, nsize); |
| 87 | if (newblock == NULL && nsize > 0) { | 122 | if (newblock == NULL && nsize > 0) { |
| 88 | lua_assert(nsize > realosize); /* cannot fail when shrinking a block */ | 123 | lua_assert(nsize > osize); /* cannot fail when shrinking a block */ |
| 89 | if (g->version) { /* is state fully built? */ | 124 | if (g->version) { /* is state fully built? */ |
| 90 | luaC_fullgc(L, 1); /* try to free some memory... */ | 125 | luaC_fullgc(L, 1); /* try to free some memory... */ |
| 91 | newblock = (*g->frealloc)(g->ud, block, osize, nsize); /* try again */ | 126 | newblock = (*g->frealloc)(g->ud, block, osize, nsize); /* try again */ |
| @@ -94,7 +129,27 @@ void *luaM_realloc_ (lua_State *L, void *block, size_t osize, size_t nsize) { | |||
| 94 | luaD_throw(L, LUA_ERRMEM); | 129 | luaD_throw(L, LUA_ERRMEM); |
| 95 | } | 130 | } |
| 96 | lua_assert((nsize == 0) == (newblock == NULL)); | 131 | lua_assert((nsize == 0) == (newblock == NULL)); |
| 97 | g->GCdebt = (g->GCdebt + nsize) - realosize; | 132 | g->GCdebt = (g->GCdebt + nsize) - osize; |
| 98 | return newblock; | 133 | return newblock; |
| 99 | } | 134 | } |
| 100 | 135 | ||
| 136 | |||
| 137 | void *luaM_malloc (lua_State *L, size_t size, int tag) { | ||
| 138 | hardtest(L, 0, size); | ||
| 139 | if (size == 0) | ||
| 140 | return NULL; /* that's all */ | ||
| 141 | else { | ||
| 142 | global_State *g = G(L); | ||
| 143 | void *newblock = (*g->frealloc)(g->ud, NULL, tag, size); | ||
| 144 | if (newblock == NULL) { | ||
| 145 | if (g->version) { /* is state fully built? */ | ||
| 146 | luaC_fullgc(L, 1); /* try to free some memory... */ | ||
| 147 | newblock = (*g->frealloc)(g->ud, NULL, tag, size); /* try again */ | ||
| 148 | } | ||
| 149 | if (newblock == NULL) | ||
| 150 | luaD_throw(L, LUA_ERRMEM); | ||
| 151 | } | ||
| 152 | g->GCdebt += size; | ||
| 153 | return newblock; | ||
| 154 | } | ||
| 155 | } | ||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lmem.h,v 1.42 2014/12/19 13:45:40 roberto Exp roberto $ | 2 | ** $Id: lmem.h,v 1.43 2014/12/19 17:26:14 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 | */ |
| @@ -15,11 +15,9 @@ | |||
| 15 | 15 | ||
| 16 | 16 | ||
| 17 | /* | 17 | /* |
| 18 | ** This macro reallocs a vector 'b' from 'on' to 'n' elements, where | 18 | ** This macro tests whether it is safe to multiply 'n' by the size of |
| 19 | ** each element has size 'e'. In case of arithmetic overflow of the | 19 | ** type 't' without overflows. Because 'e' is always constant, it avoids |
| 20 | ** product 'n'*'e', it raises an error (calling 'luaM_toobig'). Because | 20 | ** the runtime division MAX_SIZET/(e). |
| 21 | ** 'e' is always constant, it avoids the runtime division MAX_SIZET/(e). | ||
| 22 | ** | ||
| 23 | ** (The macro is somewhat complex to avoid warnings: The 'sizeof' | 21 | ** (The macro is somewhat complex to avoid warnings: The 'sizeof' |
| 24 | ** comparison avoids a runtime comparison when overflow cannot occur. | 22 | ** comparison avoids a runtime comparison when overflow cannot occur. |
| 25 | ** The compiler should be able to optimize the real test by itself, but | 23 | ** The compiler should be able to optimize the real test by itself, but |
| @@ -27,10 +25,20 @@ | |||
| 27 | ** false due to limited range of data type"; the +1 tricks the compiler, | 25 | ** false due to limited range of data type"; the +1 tricks the compiler, |
| 28 | ** avoiding this warning but also this optimization.) | 26 | ** avoiding this warning but also this optimization.) |
| 29 | */ | 27 | */ |
| 28 | #define luaM_testsize(n,e) \ | ||
| 29 | (sizeof(n) >= sizeof(size_t) && cast(size_t, (n)) + 1 > MAX_SIZET/(e)) | ||
| 30 | |||
| 31 | #define luaM_checksize(L,n,e) \ | ||
| 32 | (luaM_testsize(n,e) ? luaM_toobig(L) : cast_void(0)) | ||
| 33 | |||
| 34 | /* | ||
| 35 | ** This macro reallocs a vector 'b' from 'on' to 'n' elements, where | ||
| 36 | ** each element has size 'e'. In case of arithmetic overflow of the | ||
| 37 | ** product 'n'*'e', it raises an error (calling 'luaM_toobig'). | ||
| 38 | */ | ||
| 30 | #define luaM_reallocv(L,b,on,n,e) \ | 39 | #define luaM_reallocv(L,b,on,n,e) \ |
| 31 | (((sizeof(n) >= sizeof(size_t) && cast(size_t, (n)) + 1 > MAX_SIZET/(e)) \ | 40 | (luaM_checksize(L,n,e), \ |
| 32 | ? luaM_toobig(L) : cast_void(0)) , \ | 41 | luaM_realloc_(L, (b), cast(size_t, on)*(e), cast(size_t, n)*(e))) |
| 33 | luaM_realloc_(L, (b), (on)*(e), (n)*(e))) | ||
| 34 | 42 | ||
| 35 | /* | 43 | /* |
| 36 | ** Arrays of chars do not need any test | 44 | ** Arrays of chars do not need any test |
| @@ -38,32 +46,37 @@ | |||
| 38 | #define luaM_reallocvchar(L,b,on,n) \ | 46 | #define luaM_reallocvchar(L,b,on,n) \ |
| 39 | cast(char *, luaM_realloc_(L, (b), (on)*sizeof(char), (n)*sizeof(char))) | 47 | cast(char *, luaM_realloc_(L, (b), (on)*sizeof(char), (n)*sizeof(char))) |
| 40 | 48 | ||
| 41 | #define luaM_freemem(L, b, s) luaM_realloc_(L, (b), (s), 0) | 49 | #define luaM_freemem(L, b, s) luaM_free_(L, (b), (s)) |
| 42 | #define luaM_free(L, b) luaM_realloc_(L, (b), sizeof(*(b)), 0) | 50 | #define luaM_free(L, b) luaM_free_(L, (b), sizeof(*(b))) |
| 43 | #define luaM_freearray(L, b, n) luaM_realloc_(L, (b), (n)*sizeof(*(b)), 0) | 51 | #define luaM_freearray(L, b, n) luaM_free_(L, (b), (n)*sizeof(*(b))) |
| 44 | 52 | ||
| 45 | #define luaM_malloc(L,s) luaM_realloc_(L, NULL, 0, (s)) | 53 | #define luaM_new(L,t) cast(t *, luaM_malloc(L, sizeof(t), 0)) |
| 46 | #define luaM_new(L,t) cast(t *, luaM_malloc(L, sizeof(t))) | ||
| 47 | #define luaM_newvector(L,n,t) \ | 54 | #define luaM_newvector(L,n,t) \ |
| 48 | cast(t *, luaM_reallocv(L, NULL, 0, n, sizeof(t))) | 55 | (luaM_checksize(L,n,sizeof(t)), cast(t *, luaM_malloc(L, (n)*sizeof(t), 0))) |
| 49 | 56 | ||
| 50 | #define luaM_newobject(L,tag,s) luaM_realloc_(L, NULL, tag, (s)) | 57 | #define luaM_newobject(L,tag,s) luaM_malloc(L, (s), tag) |
| 51 | 58 | ||
| 52 | #define luaM_growvector(L,v,nelems,size,t,limit,e) \ | 59 | #define luaM_growvector(L,v,nelems,size,t,limit,e) \ |
| 53 | if ((nelems)+1 > (size)) \ | 60 | ((v)=cast(t *, luaM_growaux_(L,v,nelems,&(size),sizeof(t),limit,e))) |
| 54 | ((v)=cast(t *, luaM_growaux_(L,v,&(size),sizeof(t),limit,e))) | ||
| 55 | 61 | ||
| 56 | #define luaM_reallocvector(L, v,oldn,n,t) \ | 62 | #define luaM_reallocvector(L, v,oldn,n,t) \ |
| 57 | ((v)=cast(t *, luaM_reallocv(L, v, oldn, n, sizeof(t)))) | 63 | ((v)=cast(t *, luaM_reallocv(L, v, oldn, n, sizeof(t)))) |
| 58 | 64 | ||
| 65 | #define luaM_shrinkvector(L,v,size,fs,t) \ | ||
| 66 | ((v)=cast(t *, luaM_shrinkvector_(L, v, &(size), fs, sizeof(t)))) | ||
| 67 | |||
| 59 | LUAI_FUNC l_noret luaM_toobig (lua_State *L); | 68 | LUAI_FUNC l_noret luaM_toobig (lua_State *L); |
| 60 | 69 | ||
| 61 | /* not to be called directly */ | 70 | /* not to be called directly */ |
| 62 | LUAI_FUNC void *luaM_realloc_ (lua_State *L, void *block, size_t oldsize, | 71 | LUAI_FUNC void *luaM_realloc_ (lua_State *L, void *block, size_t oldsize, |
| 63 | size_t size); | 72 | size_t size); |
| 64 | LUAI_FUNC void *luaM_growaux_ (lua_State *L, void *block, int *size, | 73 | LUAI_FUNC void luaM_free_ (lua_State *L, void *block, size_t osize); |
| 65 | size_t size_elem, int limit, | 74 | LUAI_FUNC void *luaM_growaux_ (lua_State *L, void *block, int nelems, |
| 75 | int *size, int size_elem, int limit, | ||
| 66 | const char *what); | 76 | const char *what); |
| 77 | LUAI_FUNC void *luaM_shrinkvector_ (lua_State *L, void *block, int *nelem, | ||
| 78 | int final_n, int size_elem); | ||
| 79 | LUAI_FUNC void *luaM_malloc (lua_State *L, size_t size, int tag); | ||
| 67 | 80 | ||
| 68 | #endif | 81 | #endif |
| 69 | 82 | ||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lparser.c,v 2.168 2017/11/23 16:35:54 roberto Exp roberto $ | 2 | ** $Id: lparser.c,v 2.169 2017/11/30 13:29:18 roberto Exp roberto $ |
| 3 | ** Lua Parser | 3 | ** Lua Parser |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -569,21 +569,14 @@ static void close_func (LexState *ls) { | |||
| 569 | luaK_ret(fs, 0, 0); /* final return */ | 569 | luaK_ret(fs, 0, 0); /* final return */ |
| 570 | leaveblock(fs); | 570 | leaveblock(fs); |
| 571 | luaK_finish(fs); | 571 | luaK_finish(fs); |
| 572 | luaM_reallocvector(L, f->code, f->sizecode, fs->pc, Instruction); | 572 | luaM_shrinkvector(L, f->code, f->sizecode, fs->pc, Instruction); |
| 573 | f->sizecode = fs->pc; | 573 | luaM_shrinkvector(L, f->lineinfo, f->sizelineinfo, fs->pc, ls_byte); |
| 574 | luaM_reallocvector(L, f->lineinfo, f->sizelineinfo, fs->pc, ls_byte); | 574 | luaM_shrinkvector(L, f->abslineinfo, f->sizeabslineinfo, |
| 575 | f->sizelineinfo = fs->pc; | 575 | fs->nabslineinfo, AbsLineInfo); |
| 576 | luaM_reallocvector(L, f->abslineinfo, f->sizeabslineinfo, | 576 | luaM_shrinkvector(L, f->k, f->sizek, fs->nk, TValue); |
| 577 | fs->nabslineinfo, AbsLineInfo); | 577 | luaM_shrinkvector(L, f->p, f->sizep, fs->np, Proto *); |
| 578 | f->sizeabslineinfo = fs->nabslineinfo; | 578 | luaM_shrinkvector(L, f->locvars, f->sizelocvars, fs->nlocvars, LocVar); |
| 579 | luaM_reallocvector(L, f->k, f->sizek, fs->nk, TValue); | 579 | luaM_shrinkvector(L, f->upvalues, f->sizeupvalues, fs->nups, Upvaldesc); |
| 580 | f->sizek = fs->nk; | ||
| 581 | luaM_reallocvector(L, f->p, f->sizep, fs->np, Proto *); | ||
| 582 | f->sizep = fs->np; | ||
| 583 | luaM_reallocvector(L, f->locvars, f->sizelocvars, fs->nlocvars, LocVar); | ||
| 584 | f->sizelocvars = fs->nlocvars; | ||
| 585 | luaM_reallocvector(L, f->upvalues, f->sizeupvalues, fs->nups, Upvaldesc); | ||
| 586 | f->sizeupvalues = fs->nups; | ||
| 587 | lua_assert(fs->bl == NULL); | 580 | lua_assert(fs->bl == NULL); |
| 588 | ls->fs = fs->prev; | 581 | ls->fs = fs->prev; |
| 589 | luaC_checkGC(L); | 582 | luaC_checkGC(L); |
