* USE_CODEMMAP: Removed.
[cacao.git] / src / mm / memory.c
1 /* src/mm/memory.c - 
2
3    Copyright (C) 1996-2005 R. Grafl, A. Krall, C. Kruegel, C. Oates,
4    R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
5    C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
6    Institut f. Computersprachen - TU Wien
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    Changes: Christian Thalinger
30
31    $Id: memory.c 3403 2005-10-12 08:17:00Z twisti $
32
33 */
34
35
36 #include <assert.h>
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <string.h>
40
41 #if defined(__DARWIN__)
42 /* If we compile with -ansi on darwin, <sys/types.h> is not included. So      */
43 /* let's do it here.                                                          */
44 # include <sys/types.h>
45 #endif
46
47 #include "config.h"
48 #include "vm/types.h"
49
50 #include "arch.h"
51
52 #include "mm/memory.h"
53 #include "native/native.h"
54
55 #if defined(USE_THREADS)
56 # if defined(NATIVE_THREADS)
57 #  include "threads/native/threads.h"
58 # else
59 #  include "threads/green/threads.h"
60 # endif
61 #endif
62
63 #include "toolbox/logging.h"
64 #include "vm/exceptions.h"
65 #include "vm/global.h"
66 #include "vm/options.h"
67 #include "vm/statistics.h"
68 #include "vm/stringlocal.h"
69
70
71 /*******************************************************************************
72
73   This structure is used for dump memory allocation if cacao
74   runswithout threads.
75
76 *******************************************************************************/
77
78 #if !defined(USE_THREADS) || (defined(USE_THREADS) && !defined(NATIVE_THREADS))
79 static dumpinfo _no_threads_dumpinfo;
80 #endif
81
82 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
83 #define DUMPINFO    &((threadobject *) THREADOBJECT)->dumpinfo
84 #else
85 #define DUMPINFO    &_no_threads_dumpinfo
86 #endif
87
88
89 static void *checked_alloc(s4 size)
90 {
91         /* always allocate memory zeroed out */
92         void *m = calloc(size, 1);
93
94         if (!m)
95                 throw_cacao_exception_exit(string_java_lang_InternalError,
96                                                                    "Out of memory");
97
98         return m;
99 }
100
101
102 void *mem_alloc(s4 size)
103 {
104         if (size == 0)
105                 return NULL;
106
107 #if defined(STATISTICS)
108         if (opt_stat) {
109                 memoryusage += size;
110
111                 if (memoryusage > maxmemusage)
112                         maxmemusage = memoryusage;
113         }
114 #endif
115
116         return checked_alloc(size);
117 }
118
119
120 void *mem_realloc(void *src, s4 len1, s4 len2)
121 {
122         void *dst;
123
124         if (!src) {
125                 if (len1 != 0) {
126                         log_text("reallocating memoryblock with address NULL, length != 0");
127                         assert(0);
128                 }
129         }
130
131 #if defined(STATISTICS)
132         if (opt_stat)
133                 memoryusage = (memoryusage - len1) + len2;
134 #endif
135
136         dst = realloc(src, len2);
137
138         if (!dst)
139                 throw_cacao_exception_exit(string_java_lang_InternalError,
140                                                                    "Out of memory");
141
142         return dst;
143 }
144
145
146 void mem_free(void *m, s4 size)
147 {
148         if (!m) {
149                 if (size == 0)
150                         return;
151
152                 log_text("returned memoryblock with address NULL, length != 0");
153                 assert(0);
154         }
155
156 #if defined(STATISTICS)
157         if (opt_stat)
158                 memoryusage -= size;
159 #endif
160
161         free(m);
162 }
163
164
165 /* dump_alloc ******************************************************************
166
167    XXX
168
169 *******************************************************************************/
170
171 void *dump_alloc(s4 size)
172 {
173 #if defined(DISABLE_DUMP)
174         /* use malloc memory for dump memory (for debugging only!) */
175
176         return mem_alloc(size);
177 #else
178         void     *m;
179         dumpinfo *di;
180
181         /* If no threads are used, the dumpinfo structure is a static structure   */
182         /* defined at the top of this file.                                       */
183
184         di = DUMPINFO;
185
186         if (size == 0)
187                 return NULL;
188
189         size = ALIGN(size, ALIGNSIZE);
190
191         if (di->useddumpsize + size > di->allocateddumpsize) {
192                 dumpblock *newdumpblock;
193                 s4         newdumpblocksize;
194
195                 /* allocate a new dumplist structure */
196
197                 newdumpblock = checked_alloc(sizeof(dumpblock));
198
199                 /* If requested size is greater than the default, make the new dump   */
200                 /* block as big as the size requested. Else use the default size.     */
201
202                 if (size > DUMPBLOCKSIZE) {
203                         newdumpblocksize = size;
204
205                 } else {
206                         newdumpblocksize = DUMPBLOCKSIZE;
207                 }
208
209                 /* allocate dumpblock memory */
210
211                 newdumpblock->dumpmem = checked_alloc(newdumpblocksize);
212
213                 newdumpblock->prev = di->currentdumpblock;
214                 newdumpblock->size = newdumpblocksize;
215                 di->currentdumpblock = newdumpblock;
216
217                 /* Used dump size is previously allocated dump size, because the      */
218                 /* remaining free memory of the previous dump block cannot be used.   */
219
220                 di->useddumpsize = di->allocateddumpsize;
221
222                 /* increase the allocated dump size by the size of the new dump block */
223
224                 di->allocateddumpsize += newdumpblocksize;
225
226 #if defined(STATISTICS)
227                 /* the amount of globally allocated dump memory (thread save) */
228
229                 if (opt_stat)
230                         globalallocateddumpsize += newdumpblocksize;
231 #endif
232         }
233
234         /* current dump block base address + the size of the current dump block - */
235         /* the size of the unused memory = new start address                      */
236
237         m = di->currentdumpblock->dumpmem + di->currentdumpblock->size -
238                 (di->allocateddumpsize - di->useddumpsize);
239
240         /* increase used dump size by the allocated memory size */
241
242         di->useddumpsize += size;
243
244 #if defined(STATISTICS)
245         if (opt_stat)
246                 if (di->useddumpsize > maxdumpsize)
247                         maxdumpsize = di->useddumpsize;
248 #endif
249                 
250         return m;
251 #endif /* defined(DISABLE_DUMP) */
252 }
253
254
255 /* dump_realloc ****************************************************************
256
257    XXX
258
259 *******************************************************************************/
260
261 void *dump_realloc(void *src, s4 len1, s4 len2)
262 {
263 #if defined(DISABLE_DUMP)
264         /* use malloc memory for dump memory (for debugging only!) */
265
266         return mem_realloc(src, len1, len2);
267 #else
268         void *dst = dump_alloc(len2);
269
270         memcpy(dst, src, len1);
271
272         return dst;
273 #endif
274 }
275
276
277 /* dump_release ****************************************************************
278
279    XXX
280
281 *******************************************************************************/
282
283 void dump_release(s4 size)
284 {
285 #if defined(DISABLE_DUMP)
286         /* use malloc memory for dump memory (for debugging only!) */
287
288         /* do nothing */
289 #else
290         dumpinfo *di;
291
292         /* If no threads are used, the dumpinfo structure is a static structure   */
293         /* defined at the top of this file.                                       */
294
295         di = DUMPINFO;
296
297         if (size < 0 || size > di->useddumpsize)
298                 throw_cacao_exception_exit(string_java_lang_InternalError,
299                                                                    "Illegal dump release size %d", size);
300
301         /* reset the used dump size to the size specified */
302
303         di->useddumpsize = size;
304
305         while (di->currentdumpblock && di->allocateddumpsize - di->currentdumpblock->size >= di->useddumpsize) {
306                 dumpblock *tmp = di->currentdumpblock;
307
308 #if 0
309                 /* XXX TWISTI: can someone explain this to me? */
310 #ifdef TRACECALLARGS
311                 /* Keep the first dumpblock if we don't free memory. Otherwise
312                  * a new dumpblock is allocated each time and we run out of
313                  * memory.
314                  */
315                 if (!oldtop->prev) break;
316 #endif
317 #endif
318
319                 di->allocateddumpsize -= tmp->size;
320                 di->currentdumpblock = tmp->prev;
321
322 #if defined(STATISTICS)
323                 /* the amount of globally allocated dump memory (thread save) */
324
325                 if (opt_stat)
326                         globalallocateddumpsize -= tmp->size;
327 #endif
328
329                 /* release the dump memory and the dumpinfo structure */
330
331                 free(tmp->dumpmem);
332                 free(tmp);
333         }
334 #endif /* defined(DISABLE_DUMP) */
335 }
336
337
338 /* dump_size *******************************************************************
339
340    XXX
341
342 *******************************************************************************/
343
344 s4 dump_size(void)
345 {
346 #if defined(DISABLE_DUMP)
347         /* use malloc memory for dump memory (for debugging only!) */
348
349         return 0;
350 #else
351         dumpinfo *di;
352
353         /* If no threads are used, the dumpinfo structure is a static structure   */
354         /* defined at the top of this file.                                       */
355
356         di = DUMPINFO;
357
358         if (!di)
359                 return 0;
360
361         return di->useddumpsize;
362 #endif /* defined(DISABLE_DUMP) */
363 }
364
365
366 /*
367  * These are local overrides for various environment variables in Emacs.
368  * Please do not remove this and leave it at the end of the file, where
369  * Emacs will automagically detect them.
370  * ---------------------------------------------------------------------
371  * Local variables:
372  * mode: c
373  * indent-tabs-mode: t
374  * c-basic-offset: 4
375  * tab-width: 4
376  * End:
377  */