1 /* src/mm/dumpmemory.c - dump memory management
3 Copyright (C) 1996-2005, 2006, 2007, 2008
4 CACAOVM - Verein zu Foerderung der freien virtuellen Machine CACAO
6 This file is part of CACAO.
8 This program is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License as
10 published by the Free Software Foundation; either version 2, or (at
11 your option) any later version.
13 This program is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
30 #include "mm/dumpmemory.h"
31 #include "mm/memory.h"
33 #include "threads/threads-common.h"
35 #include "vmcore/options.h"
37 #if defined(ENABLE_STATISTICS)
38 # include "vmcore/statistics.h"
41 #include "vmcore/system.h"
46 /*******************************************************************************
48 This structure is used for dump memory allocation if cacao
51 *******************************************************************************/
53 #if !defined(ENABLE_THREADS)
54 static dumpinfo_t _no_threads_dumpinfo;
57 #if defined(ENABLE_THREADS)
58 #define DUMPINFO &((threadobject *) THREADOBJECT)->dumpinfo
60 #define DUMPINFO &_no_threads_dumpinfo
64 /* dump_check_canaries *********************************************************
66 Check canaries in dump memory.
69 di...........dumpinfo_t * of the dump area to check
70 bottomsize...dump size down to which the dump area should be checked
71 (specify 0 to check the whole dump area)
74 If any canary has been changed, this function aborts the VM with
77 *******************************************************************************/
79 #if defined(ENABLE_MEMCHECK)
80 static void dump_check_canaries(dumpinfo_t *di, s4 bottomsize)
82 dump_allocation_t *da;
86 /* iterate over all dump memory allocations above bottomsize */
90 while (da && da->useddumpsize >= bottomsize) {
93 pm = ((uint8_t *) da->mem) - MEMORY_CANARY_SIZE;
95 for (i = 0; i < MEMORY_CANARY_SIZE; ++i) {
96 if (pm[i] != i + MEMORY_CANARY_FIRST_BYTE) {
97 fprintf(stderr, "canary bytes:");
99 for (j = 0; j < MEMORY_CANARY_SIZE; ++j)
100 fprintf(stderr, " %02x", pm[j]);
102 fprintf(stderr,"\n");
104 vm_abort("error: dump memory bottom canary killed: "
105 "%p (%d bytes allocated at %p)\n",
106 pm + i, da->size, da->mem);
110 pm = ((uint8_t *) da->mem) + da->size;
112 for (i = 0; i < MEMORY_CANARY_SIZE; ++i) {
113 if (pm[i] != i + MEMORY_CANARY_FIRST_BYTE) {
114 fprintf(stderr, "canary bytes:");
116 for (j = 0; j < MEMORY_CANARY_SIZE; ++j)
117 fprintf(stderr, " %02x", pm[j]);
119 fprintf(stderr, "\n");
121 vm_abort("error: dump memory top canary killed: "
122 "%p (%d bytes allocated at %p)\n",
123 pm + i, da->size, da->mem);
130 #endif /* defined(ENABLE_MEMCHECK) */
133 /* dump_alloc ******************************************************************
135 Allocate memory in the dump area.
138 size.........size of block to allocate, in bytes
139 may be zero, in which case NULL is returned
142 pointer to allocated memory, or
143 NULL iff `size` was zero
146 XXX This function uses `memory_checked_alloc`, which *exits* if no
147 memory could be allocated.
150 dump_alloc is thread safe. Each thread has its own dump memory area.
152 dump_alloc is a fast allocator suitable for scratch memory that can be
153 collectively freed when the current activity (eg. compiling) is done.
155 You cannot selectively free dump memory. Before you start allocating it,
156 you remember the current size returned by `dump_size`. Later, when you no
157 longer need the memory, call `dump_release` with the remembered size and
158 all dump memory allocated since the call to `dump_size` will be freed.
160 *******************************************************************************/
162 void *dump_alloc(s4 size)
164 #if defined(DISABLE_DUMP)
166 /* use malloc memory for dump memory (for debugging only!) */
168 return mem_alloc(size);
170 #else /* !defined(DISABLE_DUMP) */
174 #if defined(ENABLE_MEMCHECK)
175 s4 origsize = size; /* needed for the canary system */
178 /* If no threads are used, the dumpinfo structure is a static structure */
179 /* defined at the top of this file. */
186 #if defined(ENABLE_MEMCHECK)
187 size += 2*MEMORY_CANARY_SIZE;
190 size = MEMORY_ALIGN(size, ALIGNSIZE);
192 if (di->useddumpsize + size > di->allocateddumpsize) {
193 dumpblock_t *newdumpblock;
196 /* allocate a new dumplist structure */
198 newdumpblock = memory_checked_alloc(sizeof(dumpblock_t));
200 /* If requested size is greater than the default, make the new dump */
201 /* block as big as the size requested. Else use the default size. */
203 if (size > DUMPBLOCKSIZE) {
204 newdumpblocksize = size;
207 newdumpblocksize = DUMPBLOCKSIZE;
210 /* allocate dumpblock memory */
212 newdumpblock->dumpmem = memory_checked_alloc(newdumpblocksize);
214 newdumpblock->prev = di->currentdumpblock;
215 newdumpblock->size = newdumpblocksize;
216 di->currentdumpblock = newdumpblock;
218 /* Used dump size is previously allocated dump size, because the */
219 /* remaining free memory of the previous dump block cannot be used. */
221 di->useddumpsize = di->allocateddumpsize;
223 /* increase the allocated dump size by the size of the new dump block */
225 di->allocateddumpsize += newdumpblocksize;
227 #if defined(ENABLE_STATISTICS)
228 /* the amount of globally allocated dump memory (thread save) */
231 globalallocateddumpsize += newdumpblocksize;
235 /* current dump block base address + the size of the current dump
236 block - the size of the unused memory = new start address */
238 p = ((uint8_t *) di->currentdumpblock->dumpmem) +
239 di->currentdumpblock->size -
240 (di->allocateddumpsize - di->useddumpsize);
242 #if defined(ENABLE_MEMCHECK)
244 dump_allocation_t *da = NEW(dump_allocation_t);
248 /* add the allocation to our linked list of allocations */
250 da->next = di->allocations;
251 da->mem = ((uint8_t *) p) + MEMORY_CANARY_SIZE;
253 da->useddumpsize = di->useddumpsize;
255 di->allocations = da;
257 /* write the canaries */
261 for (i = 0; i < MEMORY_CANARY_SIZE; ++i)
262 pm[i] = i + MEMORY_CANARY_FIRST_BYTE;
264 pm = ((uint8_t *) da->mem) + da->size;
266 for (i = 0; i < MEMORY_CANARY_SIZE; ++i)
267 pm[i] = i + MEMORY_CANARY_FIRST_BYTE;
269 /* make m point after the bottom canary */
271 p = ((uint8_t *) p) + MEMORY_CANARY_SIZE;
273 /* clear the memory */
275 (void) system_memset(p, MEMORY_CLEAR_BYTE, da->size);
277 #endif /* defined(ENABLE_MEMCHECK) */
279 /* increase used dump size by the allocated memory size */
281 di->useddumpsize += size;
283 #if defined(ENABLE_STATISTICS)
285 if (di->useddumpsize > maxdumpsize)
286 maxdumpsize = di->useddumpsize;
291 #endif /* defined(DISABLE_DUMP) */
295 /* dump_realloc ****************************************************************
297 Stupid realloc implementation for dump memory. Avoid, if possible.
299 *******************************************************************************/
301 void *dump_realloc(void *src, s4 len1, s4 len2)
303 #if defined(DISABLE_DUMP)
304 /* use malloc memory for dump memory (for debugging only!) */
306 return mem_realloc(src, len1, len2);
308 void *dst = dump_alloc(len2);
310 (void) system_memcpy(dst, src, len1);
312 #if defined(ENABLE_MEMCHECK)
313 /* destroy the source */
314 (void) system_memset(src, MEMORY_CLEAR_BYTE, len1);
322 /* dump_release ****************************************************************
324 Release dump memory above the given size.
327 size........All dump memory above this mark will be freed. Usually
328 `size` will be the return value of a `dump_size` call
332 XXX If the given size is invalid, this function *exits* with an
337 *******************************************************************************/
339 void dump_release(s4 size)
341 #if defined(DISABLE_DUMP)
343 /* use malloc memory for dump memory (for debugging only!) */
347 #else /* !defined(DISABLE_DUMP) */
351 /* If no threads are used, the dumpinfo structure is a static structure */
352 /* defined at the top of this file. */
356 if ((size < 0) || (size > di->useddumpsize))
357 vm_abort("Illegal dump release size: %d", size);
359 #if defined(ENABLE_MEMCHECK)
361 dump_allocation_t *da, *next;
365 dump_check_canaries(di, size);
367 /* iterate over all dump memory allocations about to be released */
369 da = di->allocations;
370 while (da && da->useddumpsize >= size) {
373 /* invalidate the freed memory */
375 (void) system_memset(da->mem, MEMORY_CLEAR_BYTE, da->size);
377 FREE(da, dump_allocation_t);
381 di->allocations = da;
383 #endif /* defined(ENABLE_MEMCHECK) */
385 /* reset the used dump size to the size specified */
387 di->useddumpsize = size;
389 while (di->currentdumpblock && di->allocateddumpsize - di->currentdumpblock->size >= di->useddumpsize) {
390 dumpblock_t *tmp = di->currentdumpblock;
392 di->allocateddumpsize -= tmp->size;
393 di->currentdumpblock = tmp->prev;
395 #if defined(ENABLE_STATISTICS)
396 /* the amount of globally allocated dump memory (thread save) */
399 globalallocateddumpsize -= tmp->size;
402 /* release the dump memory and the dumpinfo structure */
404 system_free(tmp->dumpmem);
408 #endif /* defined(DISABLE_DUMP) */
412 /* dump_size *******************************************************************
414 Return the current size of the dump memory area. See `dump_alloc`.
416 *******************************************************************************/
420 #if defined(DISABLE_DUMP)
421 /* use malloc memory for dump memory (for debugging only!) */
425 #else /* !defined(DISABLE_DUMP) */
429 /* If no threads are used, the dumpinfo structure is a static
430 structure defined at the top of this file. */
437 return di->useddumpsize;
439 #endif /* defined(DISABLE_DUMP) */
444 * These are local overrides for various environment variables in Emacs.
445 * Please do not remove this and leave it at the end of the file, where
446 * Emacs will automagically detect them.
447 * ---------------------------------------------------------------------
450 * indent-tabs-mode: t
454 * vim:noexpandtab:sw=4:ts=4: