back out our change
[cacao.git] / toolbox / memory.c
1 /* toolbox/memory.c - 
2
3    Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
4    R. Grafl, A. Krall, C. Kruegel, C. Oates, R. Obermaisser,
5    M. Probst, S. Ring, E. Steiner, C. Thalinger, D. Thuernbeck,
6    P. Tomsich, J. Wenninger
7
8    This file is part of CACAO.
9
10    This program is free software; you can redistribute it and/or
11    modify it under the terms of the GNU General Public License as
12    published by the Free Software Foundation; either version 2, or (at
13    your option) any later version.
14
15    This program is distributed in the hope that it will be useful, but
16    WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18    General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
23    02111-1307, USA.
24
25    Contact: cacao@complang.tuwien.ac.at
26
27    Authors: Reinhard Grafl
28
29    $Id: memory.c 1335 2004-07-21 15:57:10Z twisti $
30
31 */
32
33
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <assert.h>
37 #include <string.h>
38 #include <sys/mman.h>
39 #include <unistd.h>
40
41 #include "exceptions.h"
42 #include "global.h"
43 #include "native.h"
44 #include "toolbox/logging.h"
45 #include "toolbox/memory.h"
46
47
48 /********* general types, variables and auxiliary functions *********/
49
50 #define DUMPBLOCKSIZE  (2<<21)
51 #define ALIGNSIZE           8
52
53 typedef struct dumplist {
54         struct dumplist *prev;
55         char *dumpmem;
56         int size;
57 } dumplist;
58
59
60 static int mmapcodesize = 0;
61 static void *mmapcodeptr = NULL;
62
63 long int memoryusage = 0;
64
65 long int dumpsize = 0;
66 long int dumpspace = 0;
67 dumplist *topdumpblock = NULL;
68
69 long int maxmemusage = 0;
70 long int maxdumpsize = 0;
71
72
73 static void *lit_checked_alloc(int length)
74 {
75         void *m = malloc(length);
76
77         if (!m)
78                 throw_cacao_exception_exit(string_java_lang_InternalError,
79                                                                    "Out of memory");
80
81         /* not setting to zero causes cacao to segfault (String.hashCode() is
82            completely wrong) */
83         memset(m, 0, length);
84
85         return m;
86 }
87
88
89 static void *checked_alloc(int length)
90 {
91         void *m = malloc(length);
92
93         if (!m)
94                 throw_cacao_exception_exit(string_java_lang_InternalError,
95                                                                    "Out of memory");
96
97         return m;
98 }
99
100
101 void *mem_mmap(int length)
102 {
103         void *retptr;
104
105         length = ALIGN(length, ALIGNSIZE);
106
107         if (length > mmapcodesize) {
108                 mmapcodesize = 0x10000;
109
110                 if (length > mmapcodesize)
111                         mmapcodesize = length;
112
113                 mmapcodesize = ALIGN(mmapcodesize, getpagesize());
114                 mmapcodeptr = mmap (NULL,
115                                                         (size_t) mmapcodesize,
116                                                         PROT_READ | PROT_WRITE | PROT_EXEC,
117                                                         MAP_PRIVATE | MAP_ANONYMOUS,
118                                                         -1,
119                                                         (off_t) 0);
120
121                 if (mmapcodeptr == MAP_FAILED)
122                         throw_cacao_exception_exit(string_java_lang_InternalError,
123                                                                            "Out of memory");
124         }
125
126         retptr = mmapcodeptr;
127         mmapcodeptr = (void *) ((char *) mmapcodeptr + length);
128         mmapcodesize -= length;
129
130         return retptr;
131 }
132
133
134 void *mem_alloc(int length)
135 {
136         if (length == 0)
137                 return NULL;
138
139         memoryusage += length;
140         if (memoryusage > maxmemusage)
141                 maxmemusage = memoryusage;
142         
143         return checked_alloc(length);
144 }
145
146
147 void *lit_mem_alloc(int length)
148 {
149         if (length == 0)
150                 return NULL;
151
152         memoryusage += length;
153         if (memoryusage > maxmemusage)
154                 maxmemusage = memoryusage;
155         
156         return lit_checked_alloc(length);
157 }
158
159
160 void mem_free(void *m, int length)
161 {
162         if (!m) {
163                 if (length == 0)
164                         return;
165                 panic("returned memoryblock with address NULL, length != 0");
166         }
167
168         memoryusage -= length;
169
170         free(m);
171 }
172
173
174 void lit_mem_free(void *m, int length)
175 {
176         if (!m) {
177                 if (length == 0)
178                         return;
179                 panic("returned memoryblock with address NULL, length != 0");
180         }
181
182         memoryusage -= length;
183
184         free(m);
185 }
186
187
188 void *mem_realloc(void *m1, int len1, int len2)
189 {
190         void *m2;
191
192         if (!m1) {
193                 if (len1 != 0)
194                         panic("reallocating memoryblock with address NULL, length != 0");
195         }
196                 
197         memoryusage = (memoryusage - len1) + len2;
198
199         m2 = realloc(m1, len2);
200
201         if (!m2)
202                 throw_cacao_exception_exit(string_java_lang_InternalError,
203                                                                    "Out of memory");
204
205         return m2;
206 }
207
208
209 /******* common memory manager parts ******/
210
211 long int mem_usage()
212 {
213         return memoryusage;
214 }
215
216
217 void *dump_alloc(int length)
218 {
219 #if 1
220         return checked_alloc(length);
221 #else
222         void *m;
223         int blocksize = DUMPBLOCKSIZE;
224
225         if (length == 0) return NULL;
226         
227         length = ALIGN(length, ALIGNSIZE);
228
229         if (length > DUMPBLOCKSIZE)
230                 blocksize = length;
231         assert(length > 0);
232
233         if (dumpsize + length > dumpspace) {
234                 dumplist *newdumpblock = checked_alloc(sizeof(dumplist));
235
236                 newdumpblock->prev = topdumpblock;
237                 newdumpblock->size = blocksize;
238                 topdumpblock = newdumpblock;
239
240                 newdumpblock->dumpmem = checked_alloc(blocksize);
241
242                 dumpsize = dumpspace;
243                 dumpspace += blocksize;
244         }
245         
246         m = topdumpblock->dumpmem + blocksize - (dumpspace - dumpsize);
247         dumpsize += length;
248         
249         if (dumpsize > maxdumpsize) {
250                 maxdumpsize = dumpsize;
251         }
252                 
253         return m;
254 #endif
255 }   
256
257
258 void *dump_realloc(void *ptr, int len1, int len2)
259 {
260         void *p2 = dump_alloc(len2);
261
262         memcpy(p2, ptr, len1);
263
264         return p2;
265 }
266
267
268 long int dump_size()
269 {
270         return dumpsize;
271 }
272
273
274 void dump_release(long int size)
275 {
276         return;
277         assert(size >= 0 && size <= dumpsize);
278
279         dumpsize = size;
280         
281         while (topdumpblock && (dumpspace - topdumpblock->size >= dumpsize)) {
282                 dumplist *oldtop = topdumpblock;
283
284 #ifdef TRACECALLARGS
285                 /* Keep the first dumpblock if we don't free memory. Otherwise
286                  * a new dumpblock is allocated each time and we run out of
287                  * memory.
288                  */
289                 if (!oldtop->prev) break;
290 #endif
291                 
292                 dumpspace -= oldtop->size;
293                 topdumpblock = oldtop->prev;
294                 
295                 free(oldtop->dumpmem);
296                 free(oldtop);
297         }               
298 }
299
300
301 void mem_usagelog (int givewarnings)
302 {
303         if ((memoryusage != 0) && givewarnings) {
304                 dolog("Allocated memory not returned: %d", (s4) memoryusage);
305         }
306
307         if ((dumpsize != 0) && givewarnings) {
308                 dolog("Dump memory not returned: %d", (s4) dumpsize);
309         }
310
311         dolog("Random/Dump - memory usage: %dK/%dK", 
312                   (s4) ((maxmemusage + 1023) / 1024),
313                   (s4) ((maxdumpsize + 1023) / 1024));
314 }
315
316
317 /*
318  * These are local overrides for various environment variables in Emacs.
319  * Please do not remove this and leave it at the end of the file, where
320  * Emacs will automagically detect them.
321  * ---------------------------------------------------------------------
322  * Local variables:
323  * mode: c
324  * indent-tabs-mode: t
325  * c-basic-offset: 4
326  * tab-width: 4
327  * End:
328  */