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 4798 2006-04-20 19:18:43Z edwin $
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(USE_THREADS)
60 # if defined(NATIVE_THREADS)
61 # include "threads/native/threads.h"
63 # include "threads/green/threads.h"
67 #include "toolbox/logging.h"
68 #include "vm/exceptions.h"
69 #include "vm/global.h"
70 #include "vm/options.h"
71 #include "vm/statistics.h"
72 #include "vm/stringlocal.h"
75 /*******************************************************************************
77 This structure is used for dump memory allocation if cacao
80 *******************************************************************************/
82 #if !defined(USE_THREADS) || (defined(USE_THREADS) && !defined(NATIVE_THREADS))
83 static dumpinfo _no_threads_dumpinfo;
86 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
87 #define DUMPINFO &((threadobject *) THREADOBJECT)->dumpinfo
89 #define DUMPINFO &_no_threads_dumpinfo
93 /* global code memory variables ***********************************************/
95 #define DEFAULT_CODEMEM_SIZE 128 * 1024 /* defaulting to 128kB */
97 #if defined(USE_THREADS)
98 static java_objectheader *codememlock = NULL;
100 static int codememsize = 0;
101 static void *codememptr = NULL;
104 /* memory_init *****************************************************************
106 Initialize the memory subsystem.
108 *******************************************************************************/
110 bool memory_init(void)
112 #if defined(USE_THREADS)
113 codememlock = NEW(java_objectheader);
115 # if defined(NATIVE_THREADS)
116 initObjectLock(codememlock);
118 #endif /* defined(USE_THREADS) */
120 /* everything's ok */
126 /* memory_checked_alloc ********************************************************
128 Allocated zeroed-out memory and does an OOM check.
131 XXX If no memory could be allocated, this function justs *exists*.
133 *******************************************************************************/
135 static void *memory_checked_alloc(s4 size)
137 /* always allocate memory zeroed out */
139 void *p = calloc(size, 1);
142 exceptions_throw_outofmemory_exit();
148 /* memory_cnew *****************************************************************
150 Allocates memory from the heap, aligns it to architecutres PAGESIZE
151 and make the memory read-, write-, and executeable.
153 *******************************************************************************/
155 void *memory_cnew(s4 size)
160 #if defined(USE_THREADS)
161 builtin_monitorenter(codememlock);
164 size = ALIGN(size, ALIGNSIZE);
166 /* check if enough memory is available */
168 if (size > codememsize) {
169 /* set default code size */
171 codememsize = DEFAULT_CODEMEM_SIZE;
173 /* do we need more? */
175 if (size > codememsize)
178 /* get the pagesize of this architecture */
180 pagesize = getpagesize();
182 /* allocate normal heap memory */
184 if ((p = memory_checked_alloc(codememsize + pagesize - 1)) == NULL)
187 #if defined(ENABLE_STATISTICS)
189 codememusage += codememsize + pagesize - 1;
191 if (codememusage > maxcodememusage)
192 maxcodememusage = codememusage;
196 /* align the memory allocated to a multiple of PAGESIZE,
197 mprotect requires this */
199 p = (void *) (((ptrint) p + pagesize - 1) & ~(pagesize - 1));
201 /* make the memory read-, write-, and executeable */
203 if (mprotect(p, codememsize, PROT_READ | PROT_WRITE | PROT_EXEC) == -1)
204 throw_cacao_exception_exit(string_java_lang_InternalError,
207 /* set global code memory pointer */
212 /* get a memory chunk of the allocated memory */
215 codememptr = (void *) ((ptrint) codememptr + size);
218 #if defined(USE_THREADS)
219 builtin_monitorexit(codememlock);
226 void *mem_alloc(s4 size)
231 #if defined(ENABLE_STATISTICS)
235 if (memoryusage > maxmemusage)
236 maxmemusage = memoryusage;
240 return memory_checked_alloc(size);
244 void *mem_realloc(void *src, s4 len1, s4 len2)
250 log_text("reallocating memoryblock with address NULL, length != 0");
255 #if defined(ENABLE_STATISTICS)
257 memoryusage = (memoryusage - len1) + len2;
260 dst = realloc(src, len2);
263 exceptions_throw_outofmemory_exit();
269 void mem_free(void *m, s4 size)
275 log_text("returned memoryblock with address NULL, length != 0");
279 #if defined(ENABLE_STATISTICS)
288 /* dump_alloc ******************************************************************
290 Allocate memory in the dump area.
293 size.........size of block to allocate, in bytes
294 may be zero, in which case NULL is returned
297 pointer to allocated memory, or
298 NULL iff `size` was zero
301 XXX This function uses `memory_checked_alloc`, which *exits* if no
302 memory could be allocated.
305 dump_alloc is thread safe. Each thread has its own dump memory area.
307 dump_alloc is a fast allocator suitable for scratch memory that can be
308 collectively freed when the current activity (eg. compiling) is done.
310 You cannot selectively free dump memory. Before you start allocating it,
311 you remember the current size returned by `dump_size`. Later, when you no
312 longer need the memory, call `dump_release` with the remembered size and
313 all dump memory allocated since the call to `dump_size` will be freed.
315 *******************************************************************************/
317 void *dump_alloc(s4 size)
319 #if defined(DISABLE_DUMP)
321 /* use malloc memory for dump memory (for debugging only!) */
323 return mem_alloc(size);
325 #else /* !defined(DISABLE_DUMP) */
330 /* If no threads are used, the dumpinfo structure is a static structure */
331 /* defined at the top of this file. */
338 size = ALIGN(size, ALIGNSIZE);
340 if (di->useddumpsize + size > di->allocateddumpsize) {
341 dumpblock *newdumpblock;
344 /* allocate a new dumplist structure */
346 newdumpblock = memory_checked_alloc(sizeof(dumpblock));
348 /* If requested size is greater than the default, make the new dump */
349 /* block as big as the size requested. Else use the default size. */
351 if (size > DUMPBLOCKSIZE) {
352 newdumpblocksize = size;
355 newdumpblocksize = DUMPBLOCKSIZE;
358 /* allocate dumpblock memory */
360 newdumpblock->dumpmem = memory_checked_alloc(newdumpblocksize);
362 newdumpblock->prev = di->currentdumpblock;
363 newdumpblock->size = newdumpblocksize;
364 di->currentdumpblock = newdumpblock;
366 /* Used dump size is previously allocated dump size, because the */
367 /* remaining free memory of the previous dump block cannot be used. */
369 di->useddumpsize = di->allocateddumpsize;
371 /* increase the allocated dump size by the size of the new dump block */
373 di->allocateddumpsize += newdumpblocksize;
375 #if defined(ENABLE_STATISTICS)
376 /* the amount of globally allocated dump memory (thread save) */
379 globalallocateddumpsize += newdumpblocksize;
383 /* current dump block base address + the size of the current dump block - */
384 /* the size of the unused memory = new start address */
386 m = di->currentdumpblock->dumpmem + di->currentdumpblock->size -
387 (di->allocateddumpsize - di->useddumpsize);
389 /* increase used dump size by the allocated memory size */
391 di->useddumpsize += size;
393 #if defined(ENABLE_STATISTICS)
395 if (di->useddumpsize > maxdumpsize)
396 maxdumpsize = di->useddumpsize;
401 #endif /* defined(DISABLE_DUMP) */
405 /* dump_realloc ****************************************************************
407 Stupid realloc implementation for dump memory. Avoid, if possible.
409 *******************************************************************************/
411 void *dump_realloc(void *src, s4 len1, s4 len2)
413 #if defined(DISABLE_DUMP)
414 /* use malloc memory for dump memory (for debugging only!) */
416 return mem_realloc(src, len1, len2);
418 void *dst = dump_alloc(len2);
420 memcpy(dst, src, len1);
427 /* dump_release ****************************************************************
429 Release dump memory above the given size.
432 size........All dump memory above this mark will be freed. Usually
433 `size` will be the return value of a `dump_size` call
437 XXX If the given size is invalid, this function *exits* with an
442 *******************************************************************************/
444 void dump_release(s4 size)
446 #if defined(DISABLE_DUMP)
448 /* use malloc memory for dump memory (for debugging only!) */
452 #else /* !defined(DISABLE_DUMP) */
456 /* If no threads are used, the dumpinfo structure is a static structure */
457 /* defined at the top of this file. */
461 if (size < 0 || size > di->useddumpsize)
462 throw_cacao_exception_exit(string_java_lang_InternalError,
463 "Illegal dump release size %d", size);
465 /* reset the used dump size to the size specified */
467 di->useddumpsize = size;
469 while (di->currentdumpblock && di->allocateddumpsize - di->currentdumpblock->size >= di->useddumpsize) {
470 dumpblock *tmp = di->currentdumpblock;
473 /* XXX TWISTI: can someone explain this to me? */
475 /* Keep the first dumpblock if we don't free memory. Otherwise
476 * a new dumpblock is allocated each time and we run out of
479 if (!oldtop->prev) break;
483 di->allocateddumpsize -= tmp->size;
484 di->currentdumpblock = tmp->prev;
486 #if defined(ENABLE_STATISTICS)
487 /* the amount of globally allocated dump memory (thread save) */
490 globalallocateddumpsize -= tmp->size;
493 /* release the dump memory and the dumpinfo structure */
499 #endif /* defined(DISABLE_DUMP) */
503 /* dump_size *******************************************************************
505 Return the current size of the dump memory area. See `dump_alloc`.
507 *******************************************************************************/
511 #if defined(DISABLE_DUMP)
512 /* use malloc memory for dump memory (for debugging only!) */
516 #else /* !defined(DISABLE_DUMP) */
520 /* If no threads are used, the dumpinfo structure is a static structure */
521 /* defined at the top of this file. */
528 return di->useddumpsize;
530 #endif /* defined(DISABLE_DUMP) */
535 * These are local overrides for various environment variables in Emacs.
536 * Please do not remove this and leave it at the end of the file, where
537 * Emacs will automagically detect them.
538 * ---------------------------------------------------------------------
541 * indent-tabs-mode: t
545 * vim:noexpandtab:sw=4:ts=4: