diff options
Diffstat (limited to 'lmem.c')
-rw-r--r-- | lmem.c | 77 |
1 files changed, 66 insertions, 11 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 | } | ||