aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lmem.c77
-rw-r--r--lmem.h53
-rw-r--r--lparser.c25
3 files changed, 108 insertions, 47 deletions
diff --git a/lmem.c b/lmem.c
index 83a9082c..ebbfb56a 100644
--- a/lmem.c
+++ b/lmem.c
@@ -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
48void *luaM_growaux_ (lua_State *L, void *block, int *size, size_t size_elems, 56void *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
78void *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
68l_noret luaM_toobig (lua_State *L) { 96l_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*/
104void 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) {
77void *luaM_realloc_ (lua_State *L, void *block, size_t osize, size_t nsize) { 116void *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
137void *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}
diff --git a/lmem.h b/lmem.h
index 7af316f0..4ccb88ab 100644
--- a/lmem.h
+++ b/lmem.h
@@ -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
59LUAI_FUNC l_noret luaM_toobig (lua_State *L); 68LUAI_FUNC l_noret luaM_toobig (lua_State *L);
60 69
61/* not to be called directly */ 70/* not to be called directly */
62LUAI_FUNC void *luaM_realloc_ (lua_State *L, void *block, size_t oldsize, 71LUAI_FUNC void *luaM_realloc_ (lua_State *L, void *block, size_t oldsize,
63 size_t size); 72 size_t size);
64LUAI_FUNC void *luaM_growaux_ (lua_State *L, void *block, int *size, 73LUAI_FUNC void luaM_free_ (lua_State *L, void *block, size_t osize);
65 size_t size_elem, int limit, 74LUAI_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);
77LUAI_FUNC void *luaM_shrinkvector_ (lua_State *L, void *block, int *nelem,
78 int final_n, int size_elem);
79LUAI_FUNC void *luaM_malloc (lua_State *L, size_t size, int tag);
67 80
68#endif 81#endif
69 82
diff --git a/lparser.c b/lparser.c
index 1d46c6f2..6155a851 100644
--- a/lparser.c
+++ b/lparser.c
@@ -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);