3 Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
4 C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
5 E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
6 J. Wenninger, Institut f. Computersprachen - TU Wien
8 This file is part of CACAO.
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.
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.
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., 51 Franklin Street, Fifth Floor, Boston, MA
25 Contact: cacao@cacaojvm.org
27 Authors: Reinhard Grafl
29 Changes: Christian Thalinger
32 $Id: memory.c 4921 2006-05-15 14:24:36Z twisti $
45 #if defined(__DARWIN__)
46 /* If we compile with -ansi on darwin, <sys/types.h> is not included. So */
47 /* let's do it here. */
48 # include <sys/types.h>
56 #include "mm/memory.h"
57 #include "native/native.h"
59 #if defined(ENABLE_THREADS)
60 # include "threads/native/threads.h"
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"
71 /*******************************************************************************
73 This structure is used for dump memory allocation if cacao
76 *******************************************************************************/
78 #if !defined(ENABLE_THREADS)
79 static dumpinfo _no_threads_dumpinfo;
82 #if defined(ENABLE_THREADS)
83 #define DUMPINFO &((threadobject *) THREADOBJECT)->dumpinfo
85 #define DUMPINFO &_no_threads_dumpinfo
89 /* global code memory variables ***********************************************/
91 #define DEFAULT_CODEMEM_SIZE 128 * 1024 /* defaulting to 128kB */
93 #if defined(ENABLE_THREADS)
94 static java_objectheader *codememlock = NULL;
96 static int codememsize = 0;
97 static void *codememptr = NULL;
100 /* memory_init *****************************************************************
102 Initialize the memory subsystem.
104 *******************************************************************************/
106 bool memory_init(void)
108 #if defined(ENABLE_THREADS)
109 codememlock = NEW(java_objectheader);
111 lock_init_object_lock(codememlock);
114 /* everything's ok */
120 /* memory_checked_alloc ********************************************************
122 Allocated zeroed-out memory and does an OOM check.
125 XXX If no memory could be allocated, this function justs *exists*.
127 *******************************************************************************/
129 static void *memory_checked_alloc(s4 size)
131 /* always allocate memory zeroed out */
133 void *p = calloc(size, 1);
136 exceptions_throw_outofmemory_exit();
142 /* memory_cnew *****************************************************************
144 Allocates memory from the heap, aligns it to architecutres PAGESIZE
145 and make the memory read-, write-, and executeable.
147 *******************************************************************************/
149 void *memory_cnew(s4 size)
154 #if defined(ENABLE_THREADS)
155 builtin_monitorenter(codememlock);
158 size = ALIGN(size, ALIGNSIZE);
160 /* check if enough memory is available */
162 if (size > codememsize) {
163 /* set default code size */
165 codememsize = DEFAULT_CODEMEM_SIZE;
167 /* do we need more? */
169 if (size > codememsize)
172 /* get the pagesize of this architecture */
174 pagesize = getpagesize();
176 /* allocate normal heap memory */
178 if ((p = memory_checked_alloc(codememsize + pagesize - 1)) == NULL)
181 #if defined(ENABLE_STATISTICS)
183 codememusage += codememsize + pagesize - 1;
185 if (codememusage > maxcodememusage)
186 maxcodememusage = codememusage;
190 /* align the memory allocated to a multiple of PAGESIZE,
191 mprotect requires this */
193 p = (void *) (((ptrint) p + pagesize - 1) & ~(pagesize - 1));
195 /* make the memory read-, write-, and executeable */
197 if (mprotect(p, codememsize, PROT_READ | PROT_WRITE | PROT_EXEC) == -1)
198 throw_cacao_exception_exit(string_java_lang_InternalError,
201 /* set global code memory pointer */
206 /* get a memory chunk of the allocated memory */
209 codememptr = (void *) ((ptrint) codememptr + size);
212 #if defined(ENABLE_THREADS)
213 builtin_monitorexit(codememlock);
220 void *mem_alloc(s4 size)
225 #if defined(ENABLE_STATISTICS)
229 if (memoryusage > maxmemusage)
230 maxmemusage = memoryusage;
234 return memory_checked_alloc(size);
238 void *mem_realloc(void *src, s4 len1, s4 len2)
244 log_text("reallocating memoryblock with address NULL, length != 0");
249 #if defined(ENABLE_STATISTICS)
251 memoryusage = (memoryusage - len1) + len2;
254 dst = realloc(src, len2);
257 exceptions_throw_outofmemory_exit();
263 void mem_free(void *m, s4 size)
269 log_text("returned memoryblock with address NULL, length != 0");
273 #if defined(ENABLE_STATISTICS)
282 /* dump_alloc ******************************************************************
284 Allocate memory in the dump area.
287 size.........size of block to allocate, in bytes
288 may be zero, in which case NULL is returned
291 pointer to allocated memory, or
292 NULL iff `size` was zero
295 XXX This function uses `memory_checked_alloc`, which *exits* if no
296 memory could be allocated.
299 dump_alloc is thread safe. Each thread has its own dump memory area.
301 dump_alloc is a fast allocator suitable for scratch memory that can be
302 collectively freed when the current activity (eg. compiling) is done.
304 You cannot selectively free dump memory. Before you start allocating it,
305 you remember the current size returned by `dump_size`. Later, when you no
306 longer need the memory, call `dump_release` with the remembered size and
307 all dump memory allocated since the call to `dump_size` will be freed.
309 *******************************************************************************/
311 void *dump_alloc(s4 size)
313 #if defined(DISABLE_DUMP)
315 /* use malloc memory for dump memory (for debugging only!) */
317 return mem_alloc(size);
319 #else /* !defined(DISABLE_DUMP) */
324 /* If no threads are used, the dumpinfo structure is a static structure */
325 /* defined at the top of this file. */
332 size = ALIGN(size, ALIGNSIZE);
334 if (di->useddumpsize + size > di->allocateddumpsize) {
335 dumpblock *newdumpblock;
338 /* allocate a new dumplist structure */
340 newdumpblock = memory_checked_alloc(sizeof(dumpblock));
342 /* If requested size is greater than the default, make the new dump */
343 /* block as big as the size requested. Else use the default size. */
345 if (size > DUMPBLOCKSIZE) {
346 newdumpblocksize = size;
349 newdumpblocksize = DUMPBLOCKSIZE;
352 /* allocate dumpblock memory */
354 newdumpblock->dumpmem = memory_checked_alloc(newdumpblocksize);
356 newdumpblock->prev = di->currentdumpblock;
357 newdumpblock->size = newdumpblocksize;
358 di->currentdumpblock = newdumpblock;
360 /* Used dump size is previously allocated dump size, because the */
361 /* remaining free memory of the previous dump block cannot be used. */
363 di->useddumpsize = di->allocateddumpsize;
365 /* increase the allocated dump size by the size of the new dump block */
367 di->allocateddumpsize += newdumpblocksize;
369 #if defined(ENABLE_STATISTICS)
370 /* the amount of globally allocated dump memory (thread save) */
373 globalallocateddumpsize += newdumpblocksize;
377 /* current dump block base address + the size of the current dump block - */
378 /* the size of the unused memory = new start address */
380 m = di->currentdumpblock->dumpmem + di->currentdumpblock->size -
381 (di->allocateddumpsize - di->useddumpsize);
383 /* increase used dump size by the allocated memory size */
385 di->useddumpsize += size;
387 #if defined(ENABLE_STATISTICS)
389 if (di->useddumpsize > maxdumpsize)
390 maxdumpsize = di->useddumpsize;
395 #endif /* defined(DISABLE_DUMP) */
399 /* dump_realloc ****************************************************************
401 Stupid realloc implementation for dump memory. Avoid, if possible.
403 *******************************************************************************/
405 void *dump_realloc(void *src, s4 len1, s4 len2)
407 #if defined(DISABLE_DUMP)
408 /* use malloc memory for dump memory (for debugging only!) */
410 return mem_realloc(src, len1, len2);
412 void *dst = dump_alloc(len2);
414 memcpy(dst, src, len1);
421 /* dump_release ****************************************************************
423 Release dump memory above the given size.
426 size........All dump memory above this mark will be freed. Usually
427 `size` will be the return value of a `dump_size` call
431 XXX If the given size is invalid, this function *exits* with an
436 *******************************************************************************/
438 void dump_release(s4 size)
440 #if defined(DISABLE_DUMP)
442 /* use malloc memory for dump memory (for debugging only!) */
446 #else /* !defined(DISABLE_DUMP) */
450 /* If no threads are used, the dumpinfo structure is a static structure */
451 /* defined at the top of this file. */
455 if (size < 0 || size > di->useddumpsize)
456 throw_cacao_exception_exit(string_java_lang_InternalError,
457 "Illegal dump release size %d", size);
459 /* reset the used dump size to the size specified */
461 di->useddumpsize = size;
463 while (di->currentdumpblock && di->allocateddumpsize - di->currentdumpblock->size >= di->useddumpsize) {
464 dumpblock *tmp = di->currentdumpblock;
467 /* XXX TWISTI: can someone explain this to me? */
469 /* Keep the first dumpblock if we don't free memory. Otherwise
470 * a new dumpblock is allocated each time and we run out of
473 if (!oldtop->prev) break;
477 di->allocateddumpsize -= tmp->size;
478 di->currentdumpblock = tmp->prev;
480 #if defined(ENABLE_STATISTICS)
481 /* the amount of globally allocated dump memory (thread save) */
484 globalallocateddumpsize -= tmp->size;
487 /* release the dump memory and the dumpinfo structure */
493 #endif /* defined(DISABLE_DUMP) */
497 /* dump_size *******************************************************************
499 Return the current size of the dump memory area. See `dump_alloc`.
501 *******************************************************************************/
505 #if defined(DISABLE_DUMP)
506 /* use malloc memory for dump memory (for debugging only!) */
510 #else /* !defined(DISABLE_DUMP) */
514 /* If no threads are used, the dumpinfo structure is a static structure */
515 /* defined at the top of this file. */
522 return di->useddumpsize;
524 #endif /* defined(DISABLE_DUMP) */
529 * These are local overrides for various environment variables in Emacs.
530 * Please do not remove this and leave it at the end of the file, where
531 * Emacs will automagically detect them.
532 * ---------------------------------------------------------------------
535 * indent-tabs-mode: t
539 * vim:noexpandtab:sw=4:ts=4: