1 /* mm/cacao-gc/heap.c - GC module for heap management
3 Copyright (C) 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
33 #if defined(ENABLE_THREADS)
34 # include "threads/native/lock.h"
36 # include "threads/none/lock.h"
43 #include "mm/memory.h"
44 #include "src/native/include/java_lang_String.h" /* TODO: fix me! */
45 #include "toolbox/logging.h"
46 #include "vm/global.h"
47 #include "vmcore/rt-timing.h"
50 /* Global Variables ***********************************************************/
52 s4 heap_current_size; /* current size of the heap */
53 s4 heap_maximal_size; /* maximal size of the heap */
54 regioninfo_t *heap_region_sys;
55 regioninfo_t *heap_region_main;
58 /* Helper Macros **************************************************************/
60 #define GC_ALIGN_SIZE SIZEOF_VOID_P
61 #define GC_ALIGN(length,size) ((((length) + (size) - 1) / (size)) * (size))
65 void heap_init_objectheader(java_objectheader *o, u4 bytelength)
69 /* initialize the header flags */
75 /* calculate the wordcount as stored in the header */
76 /* TODO: improve this to save wordcount and without header bytes */
77 if ((bytelength & 0x03) == 0) {
78 GC_ASSERT((bytelength & 0x03) == 0);
79 wordcount = (bytelength >> 2);
80 GC_ASSERT(wordcount != 0);
82 wordcount = GC_SIZE_DUMMY;
85 /* set the wordcount in the header */
86 if (wordcount >= GC_SIZE_DUMMY) {
87 GC_SET_SIZE(o, GC_SIZE_DUMMY);
89 GC_SET_SIZE(o, wordcount);
95 s4 heap_increase_size() {
100 /* TODO: locking for threads!!! */
102 /* only a quick sanity check */
103 GC_ASSERT(heap_current_size <= heap_maximal_size);
105 /* check if we are allowed to enlarge the heap */
106 if (heap_current_size == heap_maximal_size)
107 exceptions_throw_outofmemory_exit();
109 /* TODO: find out how much to increase the heap??? */
110 increasesize = heap_maximal_size - heap_current_size;
111 GC_LOG( dolog("GC: Increasing Heap Size by %d", increasesize); );
113 /* allocate new heap from the system */
114 newsize = heap_current_size + increasesize;
117 /* check if the newly allocated heap exists */
119 exceptions_throw_outofmemory_exit();
121 /* TODO: copy the old content to the new heap */
122 /* TODO: find a complete rootset and update it to the new position */
123 /* TODO: free the old heap */
125 /* set the new values */
126 /*heap_ptr = p + (heap_ptr - heap_base);
128 heap_current_size = newsize;
130 GC_LOG( dolog("GC: Increasing Heap Size was successful");
131 heap_println_usage(); );
133 /* only a quick sanity check */
134 GC_ASSERT(heap_current_size <= heap_maximal_size);
140 s4 heap_get_hashcode(java_objectheader *o)
147 /* TODO: we need to lock the object here i think!!! */
149 /* check if there is a hash attached to this object */
150 if (GC_TEST_FLAGS(o, HDRFLAG_HASH_ATTACHED)) {
152 hashcode = *( (s4 *) ( ((u1 *) o) + get_object_size(o) - SIZEOF_VOID_P ) ); /* TODO: clean this up!!! */
153 GC_LOG2( dolog("GC: Hash re-taken: %d (0x%08x)", hashcode, hashcode); );
157 GC_SET_FLAGS(o, HDRFLAG_HASH_TAKEN);
159 hashcode = (s4) (ptrint) o;
160 GC_LOG2( dolog("GC: Hash taken: %d (0x%08x)", hashcode, hashcode); );
168 static java_objectheader *heap_alloc_intern(u4 bytelength, regioninfo_t *region)
170 java_objectheader *p;
172 /* only a quick sanity check */
174 GC_ASSERT(bytelength >= sizeof(java_objectheader));
176 /* align objects in memory */
177 bytelength = GC_ALIGN(bytelength, GC_ALIGN_SIZE);
179 /* lock the region */
180 LOCK_MONITOR_ENTER(region);
182 /* check for sufficient free space */
183 if (bytelength > region->free) {
184 dolog("GC: Region out of memory!");
189 /* allocate the object in this region */
190 p = (java_objectheader *) region->ptr;
191 region->ptr += bytelength;
192 region->free -= bytelength;
194 /* unlock the region */
195 LOCK_MONITOR_EXIT(region);
196 GC_LOG( region = NULL; );
198 /* clear allocated memory region */
200 MSET(p, 0, u1, bytelength);
202 /* set the header information */
203 heap_init_objectheader(p, bytelength);
209 /* heap_allocate ***************************************************************
211 Allocates memory on the Java heap.
213 *******************************************************************************/
215 void *heap_allocate(u4 bytelength, u4 references, methodinfo *finalizer)
217 java_objectheader *p;
218 #if defined(ENABLE_RT_TIMING)
219 struct timespec time_start, time_end;
222 RT_TIMING_GET_TIME(time_start);
224 p = heap_alloc_intern(bytelength, heap_region_main);
229 #if defined(GCCONF_HDRFLAG_REFERENCING)
230 /* We can't use a bool here for references, as it's passed as a
231 bitmask in builtin_new. Thus we check for != 0. */
232 if (references != 0) {
233 GC_SET_FLAGS(p, HDRFLAG_REFERENCING);
237 /* take care of finalization stuff */
238 if (finalizer != NULL) {
240 /* set the header bit */
241 /* TODO: do we really need this??? */
242 /* TODO: can this be overwritten by cloning??? */
243 GC_SET_FLAGS(p, GC_FLAG_FINALIZER);
245 /* register the finalizer for this object */
246 final_register(p, finalizer);
249 RT_TIMING_GET_TIME(time_end);
250 RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_GC_ALLOC);
256 void *heap_alloc_uncollectable(u4 bytelength)
258 java_objectheader *p;
260 /* loader.c does this a lot for classes with fieldscount equal zero */
264 p = heap_alloc_intern(bytelength, heap_region_sys);
269 /* TODO: can this be overwritten by cloning??? */
270 /* remember this object as uncollectable */
271 GC_SET_FLAGS(p, HDRFLAG_UNCOLLECTABLE);
277 void heap_free(void *p)
279 GC_LOG( dolog("GC: Free %p", p); );
284 /* Debugging ******************************************************************/
287 void heap_println_usage()
289 printf("Current Heap Usage: Size=%d Free=%d\n",
290 heap_current_size, heap_region_main->free);
292 GC_ASSERT(heap_current_size == heap_region_main->size);
298 void heap_print_object_flags(java_objectheader *o)
300 printf("0x%02x [%s%s%s%s%s]",
302 GC_TEST_FLAGS(o, GC_FLAG_FINALIZER) ? "F" : " ",
303 GC_TEST_FLAGS(o, HDRFLAG_HASH_ATTACHED) ? "A" : " ",
304 GC_TEST_FLAGS(o, HDRFLAG_HASH_TAKEN) ? "T" : " ",
305 GC_TEST_FLAGS(o, HDRFLAG_UNCOLLECTABLE) ? "U" : " ",
306 GC_TEST_FLAGS(o, GC_FLAG_MARKED) ? "M" : " ");
312 void heap_print_object(java_objectheader *o)
317 /* check for null pointers */
323 /* print general information */
324 #if SIZEOF_VOID_P == 8
327 printf("0x%08x: ", (void *) o);
329 heap_print_object_flags(o);
333 /* maybe this is not really an object */
334 if (/*IS_CLASS*/ o->vftbl->class == class_java_lang_Class) {
336 /* get the class information */
339 /* print the class information */
343 } else if (/*IS_ARRAY*/ o->vftbl->arraydesc != NULL) {
345 /* get the array information */
346 a = (java_arrayheader *) o;
349 /* print the array information */
352 utf_display_printable_ascii_classname(c->name);
353 printf(" (size=%d)", a->size);
355 } else /*IS_OBJECT*/ {
357 /* get the object class */
360 /* print the object information */
363 utf_display_printable_ascii_classname(c->name);
364 if (c == class_java_lang_String) {
365 printf(" (string=\"");
366 utf_display_printable_ascii(
367 javastring_toutf((java_lang_String *) o, false));
376 void heap_dump_region(regioninfo_t *region, bool marked_only)
378 java_objectheader *o;
381 /* some basic sanity checks */
382 GC_ASSERT(region->base < region->ptr);
384 printf("Heap-Dump:\n");
386 /* walk the region in a linear style */
387 o = (java_objectheader *) region->base;
388 while (o < region->ptr) {
390 if (!marked_only || GC_IS_MARKED(o)) {
392 heap_print_object(o);
396 /* get size of object */
397 o_size = get_object_size(o);
399 /* walk to next object */
400 GC_ASSERT(o_size != 0);
401 o = ((u1 *) o) + o_size;
404 printf("Heap-Dump finished.\n");
409 s4 get_object_size(java_objectheader *o)
415 /* we can assume someone initialized the header */
416 GC_ASSERT(o->hdrflags != 0);
418 /* get the wordcount from the header */
419 o_size = GC_GET_SIZE(o);
421 /* maybe we need to calculate the size by hand */
422 if (o_size != GC_SIZE_DUMMY) {
423 GC_ASSERT(o_size != 0);
424 o_size = o_size << 2;
428 /* maybe this is not really an object */
429 if (/*IS_CLASS*/ o->vftbl->class == class_java_lang_Class) {
430 /* we know the size of a classinfo */
431 o_size = sizeof(classinfo);
433 } else if (/*IS_ARRAY*/ o->vftbl->arraydesc != NULL) {
434 /* compute size of this array */
435 a = (java_arrayheader *) o;
437 o_size = c->vftbl->arraydesc->dataoffset +
438 a->size * c->vftbl->arraydesc->componentsize;
440 } else /*IS_OBJECT*/ {
441 /* get the object size */
443 o_size = c->instancesize;
444 GC_LOG( dolog("Got size (from Class): %d bytes", o_size); );
450 o_size = GC_ALIGN(o_size, GC_ALIGN_SIZE);
452 /* the hashcode attached to this object might increase the size */
453 if (GC_TEST_FLAGS(o, HDRFLAG_HASH_ATTACHED))
454 o_size += SIZEOF_VOID_P;
461 * These are local overrides for various environment variables in Emacs.
462 * Please do not remove this and leave it at the end of the file, where
463 * Emacs will automagically detect them.
464 * ---------------------------------------------------------------------
467 * indent-tabs-mode: t
471 * vim:noexpandtab:sw=4:ts=4: