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
31 $Id: memory.c 4797 2006-04-20 18:59:41Z edwin $
44 #if defined(__DARWIN__)
45 /* If we compile with -ansi on darwin, <sys/types.h> is not included. So */
46 /* let's do it here. */
47 # include <sys/types.h>
55 #include "mm/memory.h"
56 #include "native/native.h"
58 #if defined(USE_THREADS)
59 # if defined(NATIVE_THREADS)
60 # include "threads/native/threads.h"
62 # include "threads/green/threads.h"
66 #include "toolbox/logging.h"
67 #include "vm/exceptions.h"
68 #include "vm/global.h"
69 #include "vm/options.h"
70 #include "vm/statistics.h"
71 #include "vm/stringlocal.h"
74 /*******************************************************************************
76 This structure is used for dump memory allocation if cacao
79 *******************************************************************************/
81 #if !defined(USE_THREADS) || (defined(USE_THREADS) && !defined(NATIVE_THREADS))
82 static dumpinfo _no_threads_dumpinfo;
85 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
86 #define DUMPINFO &((threadobject *) THREADOBJECT)->dumpinfo
88 #define DUMPINFO &_no_threads_dumpinfo
92 /* global code memory variables ***********************************************/
94 #define DEFAULT_CODEMEM_SIZE 128 * 1024 /* defaulting to 128kB */
96 #if defined(USE_THREADS)
97 static java_objectheader *codememlock = NULL;
99 static int codememsize = 0;
100 static void *codememptr = NULL;
103 /* memory_init *****************************************************************
105 Initialize the memory subsystem.
107 *******************************************************************************/
109 bool memory_init(void)
111 #if defined(USE_THREADS)
112 codememlock = NEW(java_objectheader);
114 # if defined(NATIVE_THREADS)
115 initObjectLock(codememlock);
117 #endif /* defined(USE_THREADS) */
119 /* everything's ok */
125 /* memory_checked_alloc ********************************************************
127 Allocated zeroed-out memory and does an OOM check.
130 XXX If no memory could be allocated, this function justs *exists*.
132 *******************************************************************************/
134 static void *memory_checked_alloc(s4 size)
136 /* always allocate memory zeroed out */
138 void *p = calloc(size, 1);
141 exceptions_throw_outofmemory_exit();
147 /* memory_cnew *****************************************************************
149 Allocates memory from the heap, aligns it to architecutres PAGESIZE
150 and make the memory read-, write-, and executeable.
152 *******************************************************************************/
154 void *memory_cnew(s4 size)
159 #if defined(USE_THREADS)
160 builtin_monitorenter(codememlock);
163 size = ALIGN(size, ALIGNSIZE);
165 /* check if enough memory is available */
167 if (size > codememsize) {
168 /* set default code size */
170 codememsize = DEFAULT_CODEMEM_SIZE;
172 /* do we need more? */
174 if (size > codememsize)
177 /* get the pagesize of this architecture */
179 pagesize = getpagesize();
181 /* allocate normal heap memory */
183 if ((p = memory_checked_alloc(codememsize + pagesize - 1)) == NULL)
186 #if defined(ENABLE_STATISTICS)
188 codememusage += codememsize + pagesize - 1;
190 if (codememusage > maxcodememusage)
191 maxcodememusage = codememusage;
195 /* align the memory allocated to a multiple of PAGESIZE,
196 mprotect requires this */
198 p = (void *) (((ptrint) p + pagesize - 1) & ~(pagesize - 1));
200 /* make the memory read-, write-, and executeable */
202 if (mprotect(p, codememsize, PROT_READ | PROT_WRITE | PROT_EXEC) == -1)
203 throw_cacao_exception_exit(string_java_lang_InternalError,
206 /* set global code memory pointer */
211 /* get a memory chunk of the allocated memory */
214 codememptr = (void *) ((ptrint) codememptr + size);
217 #if defined(USE_THREADS)
218 builtin_monitorexit(codememlock);
225 void *mem_alloc(s4 size)
230 #if defined(ENABLE_STATISTICS)
234 if (memoryusage > maxmemusage)
235 maxmemusage = memoryusage;
239 return memory_checked_alloc(size);
243 void *mem_realloc(void *src, s4 len1, s4 len2)
249 log_text("reallocating memoryblock with address NULL, length != 0");
254 #if defined(ENABLE_STATISTICS)
256 memoryusage = (memoryusage - len1) + len2;
259 dst = realloc(src, len2);
262 exceptions_throw_outofmemory_exit();
268 void mem_free(void *m, s4 size)
274 log_text("returned memoryblock with address NULL, length != 0");
278 #if defined(ENABLE_STATISTICS)
287 /* dump_alloc ******************************************************************
289 Allocate memory in the dump area.
292 size.........size of block to allocate, in bytes
293 may be zero, in which case NULL is returned
296 pointer to allocated memory, or
297 NULL iff `size` was zero
300 XXX This function uses `memory_checked_alloc`, which *exits* if no
301 memory could be allocated.
304 dump_alloc is thread safe. Each thread has its own dump memory area.
306 dump_alloc is a fast allocator suitable for scratch memory that can be
307 collectively freed when the current activity (eg. compiling) is done.
309 You cannot selectively free dump memory. Before you start allocating it,
310 you remember the current size returned by `dump_size`. Later, when you no
311 longer need the memory, call `dump_release` with the remembered size and
312 all dump memory allocated since the call to `dump_size` will be freed.
314 *******************************************************************************/
316 void *dump_alloc(s4 size)
318 #if defined(DISABLE_DUMP)
320 /* use malloc memory for dump memory (for debugging only!) */
322 return mem_alloc(size);
324 #else /* !defined(DISABLE_DUMP) */
329 /* If no threads are used, the dumpinfo structure is a static structure */
330 /* defined at the top of this file. */
337 size = ALIGN(size, ALIGNSIZE);
339 if (di->useddumpsize + size > di->allocateddumpsize) {
340 dumpblock *newdumpblock;
343 /* allocate a new dumplist structure */
345 newdumpblock = memory_checked_alloc(sizeof(dumpblock));
347 /* If requested size is greater than the default, make the new dump */
348 /* block as big as the size requested. Else use the default size. */
350 if (size > DUMPBLOCKSIZE) {
351 newdumpblocksize = size;
354 newdumpblocksize = DUMPBLOCKSIZE;
357 /* allocate dumpblock memory */
359 newdumpblock->dumpmem = memory_checked_alloc(newdumpblocksize);
361 newdumpblock->prev = di->currentdumpblock;
362 newdumpblock->size = newdumpblocksize;
363 di->currentdumpblock = newdumpblock;
365 /* Used dump size is previously allocated dump size, because the */
366 /* remaining free memory of the previous dump block cannot be used. */
368 di->useddumpsize = di->allocateddumpsize;
370 /* increase the allocated dump size by the size of the new dump block */
372 di->allocateddumpsize += newdumpblocksize;
374 #if defined(ENABLE_STATISTICS)
375 /* the amount of globally allocated dump memory (thread save) */
378 globalallocateddumpsize += newdumpblocksize;
382 /* current dump block base address + the size of the current dump block - */
383 /* the size of the unused memory = new start address */
385 m = di->currentdumpblock->dumpmem + di->currentdumpblock->size -
386 (di->allocateddumpsize - di->useddumpsize);
388 /* increase used dump size by the allocated memory size */
390 di->useddumpsize += size;
392 #if defined(ENABLE_STATISTICS)
394 if (di->useddumpsize > maxdumpsize)
395 maxdumpsize = di->useddumpsize;
400 #endif /* defined(DISABLE_DUMP) */
404 /* dump_realloc ****************************************************************
406 Stupid realloc implementation for dump memory. Avoid, if possible.
408 *******************************************************************************/
410 void *dump_realloc(void *src, s4 len1, s4 len2)
412 #if defined(DISABLE_DUMP)
413 /* use malloc memory for dump memory (for debugging only!) */
415 return mem_realloc(src, len1, len2);
417 void *dst = dump_alloc(len2);
419 memcpy(dst, src, len1);
426 /* dump_release ****************************************************************
428 Release dump memory above the given size.
431 size........All dump memory above this mark will be freed. Usually
432 `size` will be the return value of a `dump_size` call
436 XXX If the given size is invalid, this function *exits* with an
441 *******************************************************************************/
443 void dump_release(s4 size)
445 #if defined(DISABLE_DUMP)
447 /* use malloc memory for dump memory (for debugging only!) */
451 #else /* !defined(DISABLE_DUMP) */
455 /* If no threads are used, the dumpinfo structure is a static structure */
456 /* defined at the top of this file. */
460 if (size < 0 || size > di->useddumpsize)
461 throw_cacao_exception_exit(string_java_lang_InternalError,
462 "Illegal dump release size %d", size);
464 /* reset the used dump size to the size specified */
466 di->useddumpsize = size;
468 while (di->currentdumpblock && di->allocateddumpsize - di->currentdumpblock->size >= di->useddumpsize) {
469 dumpblock *tmp = di->currentdumpblock;
472 /* XXX TWISTI: can someone explain this to me? */
474 /* Keep the first dumpblock if we don't free memory. Otherwise
475 * a new dumpblock is allocated each time and we run out of
478 if (!oldtop->prev) break;
482 di->allocateddumpsize -= tmp->size;
483 di->currentdumpblock = tmp->prev;
485 #if defined(ENABLE_STATISTICS)
486 /* the amount of globally allocated dump memory (thread save) */
489 globalallocateddumpsize -= tmp->size;
492 /* release the dump memory and the dumpinfo structure */
498 #endif /* defined(DISABLE_DUMP) */
502 /* dump_size *******************************************************************
504 Return the current size of the dump memory area. See `dump_alloc`.
506 *******************************************************************************/
510 #if defined(DISABLE_DUMP)
511 /* use malloc memory for dump memory (for debugging only!) */
515 #else /* !defined(DISABLE_DUMP) */
519 /* If no threads are used, the dumpinfo structure is a static structure */
520 /* defined at the top of this file. */
527 return di->useddumpsize;
529 #endif /* defined(DISABLE_DUMP) */
534 * These are local overrides for various environment variables in Emacs.
535 * Please do not remove this and leave it at the end of the file, where
536 * Emacs will automagically detect them.
537 * ---------------------------------------------------------------------
540 * indent-tabs-mode: t