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 5868 2006-10-30 11:21:36Z edwin $
47 #if defined(__DARWIN__)
48 /* If we compile with -ansi on darwin, <sys/types.h> is not included. So */
49 /* let's do it here. */
50 # include <sys/types.h>
57 #include "mm/memory.h"
58 #include "native/native.h"
60 #if defined(ENABLE_THREADS)
61 # include "threads/native/lock.h"
62 # include "threads/native/threads.h"
64 # include "threads/none/lock.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"
76 /*******************************************************************************
78 This structure is used for dump memory allocation if cacao
81 *******************************************************************************/
83 #if !defined(ENABLE_THREADS)
84 static dumpinfo_t _no_threads_dumpinfo;
87 #if defined(ENABLE_THREADS)
88 #define DUMPINFO &((threadobject *) THREADOBJECT)->dumpinfo
90 #define DUMPINFO &_no_threads_dumpinfo
94 /* global code memory variables ***********************************************/
96 #define DEFAULT_CODE_MEMORY_SIZE 128 * 1024 /* defaulting to 128kB */
98 #if defined(ENABLE_THREADS)
99 static java_objectheader *lock_code_memory = NULL;
101 static void *code_memory = NULL;
102 static int code_memory_size = 0;
103 static int pagesize = 0;
106 /* memory_init *****************************************************************
108 Initialize the memory subsystem.
110 *******************************************************************************/
112 bool memory_init(void)
114 #if defined(ENABLE_THREADS)
115 lock_code_memory = NEW(java_objectheader);
117 lock_init_object_lock(lock_code_memory);
120 /* get the pagesize of this architecture */
122 pagesize = getpagesize();
124 /* everything's ok */
130 /* memory_checked_alloc ********************************************************
132 Allocated zeroed-out memory and does an OOM check.
135 XXX If no memory could be allocated, this function justs *exists*.
137 *******************************************************************************/
139 static void *memory_checked_alloc(s4 size)
141 /* always allocate memory zeroed out */
143 void *p = calloc(size, 1);
146 exceptions_throw_outofmemory_exit();
152 /* memory_cnew *****************************************************************
154 Allocates memory from the heap via mmap and make the memory read-,
155 write-, and executeable.
157 *******************************************************************************/
159 void *memory_cnew(s4 size)
163 LOCK_MONITOR_ENTER(lock_code_memory);
165 size = MEMORY_ALIGN(size, ALIGNSIZE);
167 /* check if enough memory is available */
169 if (size > code_memory_size) {
170 /* set default code size */
172 code_memory_size = DEFAULT_CODE_MEMORY_SIZE;
174 /* do we need more? */
176 if (size > code_memory_size)
177 code_memory_size = size;
179 /* align the size of the memory to be allocated */
181 code_memory_size = MEMORY_ALIGN(code_memory_size, pagesize);
183 #if defined(ENABLE_STATISTICS)
185 codememusage += code_memory_size;
187 if (codememusage > maxcodememusage)
188 maxcodememusage = codememusage;
192 /* allocate the memory */
194 #if defined(MAP_ANONYMOUS) || defined(MAP_ANON)
196 (size_t) code_memory_size,
197 PROT_READ | PROT_WRITE | PROT_EXEC,
199 # if defined(MAP_ANONYMOUS)
201 # elif defined(MAP_ANON)
209 # if defined(MAP_FAILED)
212 if (p == (void *) -1)
214 vm_abort("mmap failed: %s", strerror(errno));
217 /* This works a least on IRIX. */
219 p = memory_checked_alloc(code_memory_size);
222 /* set global code memory pointer */
227 /* get a memory chunk of the allocated memory */
231 code_memory = (void *) ((ptrint) code_memory + size);
232 code_memory_size -= size;
234 LOCK_MONITOR_EXIT(lock_code_memory);
240 /* memory_cfree ****************************************************************
242 Frees the code memory pointed to.
244 ATTENTION: This function currently does NOTHING! Because we don't
245 have a memory management for code memory.
247 *******************************************************************************/
249 void memory_cfree(void *p, s4 size)
255 void *mem_alloc(s4 size)
260 #if defined(ENABLE_STATISTICS)
264 if (memoryusage > maxmemusage)
265 maxmemusage = memoryusage;
269 return memory_checked_alloc(size);
273 void *mem_realloc(void *src, s4 len1, s4 len2)
279 log_text("reallocating memoryblock with address NULL, length != 0");
284 #if defined(ENABLE_STATISTICS)
286 memoryusage = (memoryusage - len1) + len2;
289 dst = realloc(src, len2);
292 exceptions_throw_outofmemory_exit();
298 void mem_free(void *m, s4 size)
304 log_text("returned memoryblock with address NULL, length != 0");
308 #if defined(ENABLE_STATISTICS)
317 /* dump_alloc ******************************************************************
319 Allocate memory in the dump area.
322 size.........size of block to allocate, in bytes
323 may be zero, in which case NULL is returned
326 pointer to allocated memory, or
327 NULL iff `size` was zero
330 XXX This function uses `memory_checked_alloc`, which *exits* if no
331 memory could be allocated.
334 dump_alloc is thread safe. Each thread has its own dump memory area.
336 dump_alloc is a fast allocator suitable for scratch memory that can be
337 collectively freed when the current activity (eg. compiling) is done.
339 You cannot selectively free dump memory. Before you start allocating it,
340 you remember the current size returned by `dump_size`. Later, when you no
341 longer need the memory, call `dump_release` with the remembered size and
342 all dump memory allocated since the call to `dump_size` will be freed.
344 *******************************************************************************/
346 void *dump_alloc(s4 size)
348 #if defined(DISABLE_DUMP)
350 /* use malloc memory for dump memory (for debugging only!) */
352 return mem_alloc(size);
354 #else /* !defined(DISABLE_DUMP) */
359 /* If no threads are used, the dumpinfo structure is a static structure */
360 /* defined at the top of this file. */
367 size = MEMORY_ALIGN(size, ALIGNSIZE);
369 if (di->useddumpsize + size > di->allocateddumpsize) {
370 dumpblock_t *newdumpblock;
373 /* allocate a new dumplist structure */
375 newdumpblock = memory_checked_alloc(sizeof(dumpblock_t));
377 /* If requested size is greater than the default, make the new dump */
378 /* block as big as the size requested. Else use the default size. */
380 if (size > DUMPBLOCKSIZE) {
381 newdumpblocksize = size;
384 newdumpblocksize = DUMPBLOCKSIZE;
387 /* allocate dumpblock memory */
389 newdumpblock->dumpmem = memory_checked_alloc(newdumpblocksize);
391 newdumpblock->prev = di->currentdumpblock;
392 newdumpblock->size = newdumpblocksize;
393 di->currentdumpblock = newdumpblock;
395 /* Used dump size is previously allocated dump size, because the */
396 /* remaining free memory of the previous dump block cannot be used. */
398 di->useddumpsize = di->allocateddumpsize;
400 /* increase the allocated dump size by the size of the new dump block */
402 di->allocateddumpsize += newdumpblocksize;
404 #if defined(ENABLE_STATISTICS)
405 /* the amount of globally allocated dump memory (thread save) */
408 globalallocateddumpsize += newdumpblocksize;
412 /* current dump block base address + the size of the current dump block - */
413 /* the size of the unused memory = new start address */
415 m = di->currentdumpblock->dumpmem + di->currentdumpblock->size -
416 (di->allocateddumpsize - di->useddumpsize);
418 /* increase used dump size by the allocated memory size */
420 di->useddumpsize += size;
422 #if defined(ENABLE_STATISTICS)
424 if (di->useddumpsize > maxdumpsize)
425 maxdumpsize = di->useddumpsize;
430 #endif /* defined(DISABLE_DUMP) */
434 /* dump_realloc ****************************************************************
436 Stupid realloc implementation for dump memory. Avoid, if possible.
438 *******************************************************************************/
440 void *dump_realloc(void *src, s4 len1, s4 len2)
442 #if defined(DISABLE_DUMP)
443 /* use malloc memory for dump memory (for debugging only!) */
445 return mem_realloc(src, len1, len2);
447 void *dst = dump_alloc(len2);
449 memcpy(dst, src, len1);
456 /* dump_release ****************************************************************
458 Release dump memory above the given size.
461 size........All dump memory above this mark will be freed. Usually
462 `size` will be the return value of a `dump_size` call
466 XXX If the given size is invalid, this function *exits* with an
471 *******************************************************************************/
473 void dump_release(s4 size)
475 #if defined(DISABLE_DUMP)
477 /* use malloc memory for dump memory (for debugging only!) */
481 #else /* !defined(DISABLE_DUMP) */
485 /* If no threads are used, the dumpinfo structure is a static structure */
486 /* defined at the top of this file. */
490 if ((size < 0) || (size > di->useddumpsize))
491 vm_abort("Illegal dump release size: %d", size);
493 /* reset the used dump size to the size specified */
495 di->useddumpsize = size;
497 while (di->currentdumpblock && di->allocateddumpsize - di->currentdumpblock->size >= di->useddumpsize) {
498 dumpblock_t *tmp = di->currentdumpblock;
500 di->allocateddumpsize -= tmp->size;
501 di->currentdumpblock = tmp->prev;
503 #if defined(ENABLE_STATISTICS)
504 /* the amount of globally allocated dump memory (thread save) */
507 globalallocateddumpsize -= tmp->size;
510 /* release the dump memory and the dumpinfo structure */
516 #endif /* defined(DISABLE_DUMP) */
520 /* dump_size *******************************************************************
522 Return the current size of the dump memory area. See `dump_alloc`.
524 *******************************************************************************/
528 #if defined(DISABLE_DUMP)
529 /* use malloc memory for dump memory (for debugging only!) */
533 #else /* !defined(DISABLE_DUMP) */
537 /* If no threads are used, the dumpinfo structure is a static structure */
538 /* defined at the top of this file. */
545 return di->useddumpsize;
547 #endif /* defined(DISABLE_DUMP) */
552 * These are local overrides for various environment variables in Emacs.
553 * Please do not remove this and leave it at the end of the file, where
554 * Emacs will automagically detect them.
555 * ---------------------------------------------------------------------
558 * indent-tabs-mode: t
562 * vim:noexpandtab:sw=4:ts=4: