CACAO
heap.c
Go to the documentation of this file.
1 /* mm/cacao-gc/heap.c - GC module for heap management
2 
3  Copyright (C) 1996-2013
4  CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
5 
6  This file is part of CACAO.
7 
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.
12 
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.
17 
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
21  02110-1301, USA.
22 
23 */
24 
25 
26 #include "config.h"
27 #include "vm/types.hpp"
28 
29 #include "threads/lock.hpp"
30 
31 #include "gc.h"
32 #include "final.h"
33 #include "heap.h"
34 #include "mark.h"
35 #include "region.h"
36 #include "mm/memory.hpp"
37 #include "native/include/java_lang_String.h"
38 #include "native/llni.hpp"
39 #include "toolbox/logging.hpp"
40 
41 #include "vm/global.hpp"
42 #include "vm/options.hpp"
43 #include "vm/rt-timing.hpp"
44 #include "vm/string.hpp"
45 #include "vm/vm.hpp"
46 
47 
48 /* Global Variables ***********************************************************/
49 
50 s4 heap_current_size; /* current size of the heap */
51 s4 heap_maximal_size; /* maximal size of the heap */
54 
55 
57 {
58  u4 wordcount;
59 
60  /* initialize the header flags */
61  o->hdrflags = 0;
62 
63  /* align the size */
64  /* TODO */
65 
66  /* calculate the wordcount as stored in the header */
67  /* TODO: improve this to save wordcount and without header bytes */
68  if ((bytelength & 0x03) == 0) {
69  GC_ASSERT((bytelength & 0x03) == 0);
70  wordcount = (bytelength >> 2);
71  GC_ASSERT(wordcount != 0);
72  } else {
73  wordcount = GC_SIZE_DUMMY;
74  }
75 
76  /* set the wordcount in the header */
77  if (wordcount >= GC_SIZE_DUMMY) {
79  } else {
80  GC_SET_SIZE(o, wordcount);
81  }
82 
83 }
84 
85 
86 void heap_update_references(rootset_t *rs, regioninfo_t *region, u4 offset)
87 {
88  java_object_t *o;
89  java_object_t *ref;
90  java_object_t **refptr;
91  u1* start;
92  u1* end;
93  int i;
94 
95  GC_LOG( dolog("GC: Updating all references (offset=%x) ...", offset); );
96 
97  start = region->base - offset;
98  end = region->ptr - offset;
99  GC_LOG( printf("Region previously was [ %p ; %p]\n", start, end); );
100 
101  GC_LOG2( printf("updating in root-sets ..."); );
102 
103  /* walk through all rootsets */
104  while (rs) {
105 
106  /* walk through the references of this rootset */
107  for (i = 0; i < rs->refcount; i++) {
108 
109  /* load the reference */
110  refptr = rs->refs[i].ref;
111  ref = *( refptr );
112 
113  GC_LOG2( printf("\troot pointer to %p\n", (void *) ref); );
114 
115  /* update the references */
116  if (POINTS_INTO(ref, start, end))
117  *refptr = ((u1 *) ref) + offset;
118 
119  }
120 
121  /* skip to next rootset in chain */
122  rs = rs->next;
123 
124  }
125 
126 
127  o = region->base;
128  while (o < region->ptr) {
129 
130  GC_LOG2( printf("updating in %p ...\n", (void *) o); );
131 
132  if (IS_ARRAY(o)) {
133 
134  /* walk through the references of an Array */
135  FOREACH_ARRAY_REF(o,ref,refptr,
136 
137  GC_LOG2( printf("\tarray-entry %p -> %p\n", (void *) ref, ((u1 *) ref) + offset); );
138 
139  if (POINTS_INTO(ref, start, end))
140  *refptr = ((u1 *) ref) + offset;
141 
142  );
143 
144  } else {
145 
146  /* walk through the references of an Object */
147  FOREACH_OBJECT_REF(o,ref,refptr,
148 
149  GC_LOG2( printf("\tobject-field %p -> %p\n", (void *) ref, ((u1 *) ref) + offset); );
150 
151  if (POINTS_INTO(ref, start, end))
152  *refptr = ((u1 *) ref) + offset;
153 
154  );
155 
156  }
157 
158  /* skip to next object */
159  o = ((u1 *) o) + get_object_size(o);
160 
161  }
162 
163 }
164 
165 
167 {
168  s4 newsize;
169  s4 resize_offset;
170 
171  /* only a quick sanity check */
173 
174  /* check if we are allowed to enlarge the heap */
176  vm_abort("heap_increase_size: reached maximal heap size: out of memory");
177 
178  /* find out how much to increase the heap??? */
179  newsize = 2 * heap_current_size; /* XXX TODO: better heuristic here */
180  dolog("GC: Increasing Heap Size to %d bytes", newsize); /* XXX remove me */
181  GC_LOG( dolog("GC: Increasing Heap Size to %d bytes", newsize); );
182 
183  /* resize the main heap region */
184  resize_offset = region_resize(heap_region_main, newsize);
185 
186  /* update all references if necesarry */
187  if (resize_offset != 0)
188  heap_update_references(rs, heap_region_main, resize_offset);
189  else
190  dolog("GC WARNING: References are not updated after heap resizing!");
191 
192  /* set the new values */
193  heap_current_size = newsize;
194 
195  GC_LOG( dolog("GC: Increasing Heap Size was successful");
196  heap_println_usage(); );
197 
198  /* only a quick sanity check */
200 
201 }
202 
203 
205 {
206  s4 hashcode;
207 
208  if (!o)
209  return 0;
210 
211  /* TODO: we need to lock the object here i think!!! */
212 
213  /* check if there is a hash attached to this object */
215 
216  hashcode = *( (s4 *) ( ((u1 *) o) + get_object_size(o) - SIZEOF_VOID_P ) ); /* TODO: clean this up!!! */
217  GC_LOG2( dolog("GC: Hash re-taken: %d (0x%08x)", hashcode, hashcode); );
218 
219  } else {
220 
222 
223  hashcode = (s4) (ptrint) o;
224  GC_LOG2( dolog("GC: Hash taken: %d (0x%08x)", hashcode, hashcode); );
225 
226  }
227 
228  return hashcode;
229 }
230 
231 
232 static java_object_t *heap_alloc_intern(u4 bytelength, regioninfo_t *region, bool collect)
233 {
234  java_object_t *p;
235 
236  /* only a quick sanity check */
237  GC_ASSERT(region);
238  GC_ASSERT(bytelength >= sizeof(java_object_t));
239 
240 #if !defined(NDEBUG) && defined(ENABLE_THREADS)
241  /* check the current VM state for sanity */
242  GC_ASSERT(!THREADOBJECT->gc_critical);
244 #endif
245 
246  /* align objects in memory */
247  bytelength = GC_ALIGN(bytelength, GC_ALIGN_SIZE);
248 
249  /* lock the region */
250  LOCK_MONITOR_ENTER(region);
251 
252 #if !defined(NDEBUG)
253  /* heavy stress test */
254  if (opt_GCStress && collect)
255  gc_collect(0);
256 #endif
257 
258  /* check for sufficient free space */
259  if (bytelength > region->free) {
260  dolog("GC: Region out of memory! (collect=%d)", collect);
261 
262  if (collect) {
263  gc_collect(0);
264 #if 0
265  GC_ASSERT(region->free >= bytelength);
266 #else
267  if (region->free < bytelength) {
268  dolog("GC: OOM OOM OOM OOM OOM OOM OOM OOM OOM OOM");
270  return NULL;
271  }
272 #endif
273  } else
274  return NULL;
275  }
276 
277  /* allocate the object in this region */
278  p = (java_object_t *) region->ptr;
279  region->ptr += bytelength;
280  region->free -= bytelength;
281 
282  /* unlock the region */
283  LOCK_MONITOR_EXIT(region);
284 
285  /* clear allocated memory region */
286  GC_ASSERT(p);
287  MSET(p, 0, u1, bytelength);
288 
289  /* set the header information */
290  heap_init_objectheader(p, bytelength);
291 
292  return p;
293 }
294 
295 
296 /* heap_alloc ******************************************************************
297 
298  Allocates memory on the Java heap.
299 
300 *******************************************************************************/
301 
302 void *heap_alloc(u4 size, u4 references, methodinfo *finalizer, bool collect)
303 {
304  java_object_t *p;
305  java_handle_t *h;
306 /* TODO port to new rt timing */
307 #if 0
308 #if defined(ENABLE_RT_TIMING)
309  struct timespec time_start, time_end;
310 #endif
311 
312  RT_TIMING_GET_TIME(time_start);
313 #endif
314 
315  p = heap_alloc_intern(size, heap_region_main, collect);
316 
317  if (p == NULL)
318  return NULL;
319 
320 #if defined(GCCONF_HDRFLAG_REFERENCING)
321  /* We can't use a bool here for references, as it's passed as a
322  bitmask in builtin_new. Thus we check for != 0. */
323  if (references != 0) {
325  }
326 #endif
327 
328  /* register the finalizer for this object */
329  if (finalizer != NULL) {
330  final_register(p, finalizer);
331  }
332 
333  h = LLNI_WRAP(p);
334 
335 /* TODO port to new rt timing */
336 #if 0
337  RT_TIMING_GET_TIME(time_end);
338  RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_GC_ALLOC);
339 #endif
340 
341  return h;
342 }
343 
344 
346 {
347  java_object_t *p;
348 
349  /* loader.c does this a lot for classes with fieldscount equal zero */
350  if (size == 0)
351  return NULL;
352 
353  p = heap_alloc_intern(size, heap_region_sys, false);
354 
355  if (p == NULL)
356  return NULL;
357 
358  /* TODO: can this be overwritten by cloning??? */
359  /* remember this object as uncollectable */
361 
362  return p;
363 }
364 
365 
366 void heap_free(void *p)
367 {
368  GC_LOG( dolog("GC: Free %p", p); );
369  GC_ASSERT(0);
370 }
371 
372 
373 /* Debugging ******************************************************************/
374 
375 #if !defined(NDEBUG)
377 {
378  printf("Current Heap Usage: Size=%d Free=%d\n",
379  heap_current_size, heap_region_main->free);
380 
381  GC_ASSERT(heap_current_size == heap_region_main->size);
382 }
383 #endif
384 
385 
386 #if !defined(NDEBUG)
388 {
389  printf("0x%02x [%s%s%s%s]",
390  GC_GET_SIZE(o),
391  GC_TEST_FLAGS(o, HDRFLAG_HASH_ATTACHED) ? "A" : " ",
392  GC_TEST_FLAGS(o, HDRFLAG_HASH_TAKEN) ? "T" : " ",
393  GC_TEST_FLAGS(o, HDRFLAG_UNCOLLECTABLE) ? "U" : " ",
394  GC_TEST_FLAGS(o, GC_FLAG_MARKED) ? "M" : " ");
395 }
396 #endif
397 
398 
399 #if !defined(NDEBUG)
401 {
402  java_array_t *a;
403  classinfo *c;
404 
405  /* check for null pointers */
406  if (o == NULL) {
407  printf("(NULL)");
408  return;
409  }
410 
411  /* print general information */
412 #if SIZEOF_VOID_P == 8
413  printf("0x%016llx: ", (unsigned long long) o);
414 #else
415  printf("0x%08lx: ", (unsigned long) o);
416 #endif
417 
418  /* check for invalid heap references */
419  if (!POINTS_INTO(o, heap_region_main->base, heap_region_main->end) &&
420  !POINTS_INTO(o, heap_region_sys->base, heap_region_sys->end))
421  {
422  printf("<<< No Heap Reference >>>");
423  return;
424  }
425 
426  /* print object flags */
428  printf(" ");
429 
430  GC_ASSERT(o->vftbl);
431 
432  /* TODO */
433  /* maybe this is not really an object */
434  if (/*IS_CLASS*/ o->vftbl->class == class_java_lang_Class) {
435 
436  /* get the class information */
437  c = (classinfo *) o;
438 
439  /* print the class information */
440  printf("CLS ");
441  class_print(c);
442 
443  } else if (/*IS_ARRAY*/ o->vftbl->arraydesc != NULL) {
444 
445  /* get the array information */
446  a = (java_array_t *) o;
447  c = o->vftbl->class;
448 
449  /* print the array information */
450  printf("ARR ");
451  /*class_print(c);*/
453  printf(" (size=%d)", a->size);
454 
455  } else /*IS_OBJECT*/ {
456 
457  /* get the object class */
458  c = o->vftbl->class;
459 
460  /* print the object information */
461  printf("OBJ ");
462  /*class_print(c);*/
464  if (c == class_java_lang_String) {
465  printf(" (string=\"");
467  JavaString((java_lang_String*) o).to_utf8();
468  printf("\")");
469  }
470 
471  }
472 }
473 #endif
474 
475 #if !defined(NDEBUG)
476 void heap_dump_region(regioninfo_t *region, bool marked_only)
477 {
478  java_object_t *o;
479  u4 o_size;
480 
481  /* some basic sanity checks */
482  GC_ASSERT(region->base <= region->ptr);
483 
484  printf("Heap-Dump:\n");
485 
486  /* walk the region in a linear style */
487  o = (java_object_t *) region->base;
488  while (o < region->ptr) {
489 
490  if (!marked_only || GC_IS_MARKED(o)) {
491  printf("\t");
493  printf("\n");
494  }
495 
496  /* get size of object */
497  o_size = get_object_size(o);
498 
499  /* walk to next object */
500  GC_ASSERT(o_size != 0);
501  o = ((u1 *) o) + o_size;
502  }
503 
504  printf("Heap-Dump finished.\n");
505 }
506 #endif
507 
508 
510 {
511  java_array_t *a;
512  classinfo *c;
513  s4 o_size;
514 
515  /* we can assume someone initialized the header */
516  GC_ASSERT(o->hdrflags != 0);
517 
518  /* get the wordcount from the header */
519  o_size = GC_GET_SIZE(o);
520 
521  /* maybe we need to calculate the size by hand */
522  if (o_size != GC_SIZE_DUMMY) {
523  GC_ASSERT(o_size != 0);
524  o_size = o_size << 2;
525  } else {
526 
527  /* TODO */
528  /* maybe this is not really an object */
529  if (/*IS_CLASS*/ o->vftbl->class == class_java_lang_Class) {
530  /* we know the size of a classinfo */
531  o_size = sizeof(classinfo);
532 
533  } else if (/*IS_ARRAY*/ o->vftbl->arraydesc != NULL) {
534  /* compute size of this array */
535  a = (java_array_t *) o;
536  c = o->vftbl->class;
537  o_size = c->vftbl->arraydesc->dataoffset +
538  a->size * c->vftbl->arraydesc->componentsize;
539 
540  } else /*IS_OBJECT*/ {
541  /* get the object size */
542  c = o->vftbl->class;
543  o_size = c->instancesize;
544  GC_LOG( dolog("Got size (from Class): %d bytes", o_size); );
545  }
546 
547  }
548 
549  /* align the size */
550  o_size = GC_ALIGN(o_size, GC_ALIGN_SIZE);
551 
552  /* the hashcode attached to this object might increase the size */
554  o_size += SIZEOF_VOID_P;
555 
556  return o_size;
557 }
558 
559 
560 /*
561  * These are local overrides for various environment variables in Emacs.
562  * Please do not remove this and leave it at the end of the file, where
563  * Emacs will automagically detect them.
564  * ---------------------------------------------------------------------
565  * Local variables:
566  * mode: c
567  * indent-tabs-mode: t
568  * c-basic-offset: 4
569  * tab-width: 4
570  * End:
571  * vim:noexpandtab:sw=4:ts=4:
572  */
#define dolog
Definition: logging.hpp:171
#define GC_IS_MARKED(obj)
Definition: mark.h:42
#define IS_ARRAY(o)
Definition: heap.h:65
rootset_t * next
Definition: rootset.h:60
void gc_collect(s4 level)
Definition: gc.c:233
rootset_entry_t refs[ROOTSET_INITIAL_CAPACITY]
Definition: rootset.h:64
void class_print(classinfo *c)
Definition: class.cpp:2231
void utf_display_printable_ascii_classname(Utf8String u)
Definition: utf8.cpp:552
#define LOCK_MONITOR_EXIT(o)
Definition: lock.hpp:94
void heap_free(void *p)
Definition: heap.c:366
static java_object_t * heap_alloc_intern(u4 bytelength, regioninfo_t *region, bool collect)
Definition: heap.c:232
#define GC_ALIGN_SIZE
Definition: gc.h:108
#define GC_LOG(code)
Definition: gc.h:58
s4 heap_get_hashcode(java_object_t *o)
Definition: heap.c:204
s4 heap_maximal_size
Definition: heap.c:51
s4 instancesize
Definition: class.hpp:118
#define POINTS_INTO(ptr, ptr_start, ptr_end)
Definition: gc.h:105
uint8_t u1
Definition: types.hpp:40
void final_register(java_object_t *o, methodinfo *finalizer)
Definition: final.c:47
JNIEnv jthread jobject jclass jlong size
Definition: jvmti.h:387
void vm_abort(const char *text,...)
Definition: vm.cpp:2586
void * heap_alloc(u4 size, u4 references, methodinfo *finalizer, bool collect)
Definition: heap.c:302
void heap_println_usage()
Definition: heap.c:376
#define FOREACH_OBJECT_REF(o, ref, refptr, code)
Definition: heap.h:85
#define GC_GET_SIZE(obj)
Definition: heap.h:41
void * heap_alloc_uncollectable(u4 size)
Definition: heap.c:345
regioninfo_t * heap_region_main
Definition: heap.c:53
u1 * base
Definition: region.h:48
#define GC_ASSERT(assertion)
Definition: gc.h:59
java_object_t ** ref
Definition: rootset.h:51
#define GC_LOG2(code)
Definition: gc.h:68
#define LLNI_WRAP(obj)
Definition: llni.hpp:51
u1 * end
Definition: region.h:49
#define GC_FLAG_MARKED
Definition: mark.h:40
Utf8String name
Definition: class.hpp:91
s4 get_object_size(java_object_t *o)
Definition: heap.c:509
u1 * ptr
Definition: region.h:50
classinfo * class_java_lang_Class
Definition: globals.cpp:35
#define GC_SET_FLAGS(obj, flags)
Definition: gc.h:101
#define GC_ALIGN(val, size)
Definition: gc.h:109
MIIterator i
regioninfo_t * heap_region_sys
Definition: heap.c:52
int32_t s4
Definition: types.hpp:45
#define GC_TEST_FLAGS(obj, flags)
Definition: gc.h:103
void heap_print_object(java_object_t *o)
Definition: heap.c:400
arraydescriptor * arraydesc
Definition: vftbl.hpp:101
This file contains the real-time timing utilities.
void utf_display_printable_ascii(Utf8String u)
Definition: utf8.cpp:532
uint32_t u4
Definition: types.hpp:46
vftbl_t * vftbl
Definition: class.hpp:121
classinfo * class_java_lang_String
Definition: globals.cpp:39
GNU Classpath java/lang/String.
#define GC_SIZE_DUMMY
Definition: heap.h:38
#define MSET(ptr, byte, type, num)
Definition: memory.hpp:104
#define FOREACH_ARRAY_REF(o, ref, refptr, code)
Definition: heap.h:66
void heap_init_objectheader(java_object_t *o, u4 bytelength)
Definition: heap.c:56
#define LOCK_MONITOR_ENTER(o)
Definition: lock.hpp:93
void heap_update_references(rootset_t *rs, regioninfo_t *region, u4 offset)
Definition: heap.c:86
s4 componentsize
Definition: array.hpp:78
s4 heap_current_size
Definition: heap.c:50
void heap_print_object_flags(java_object_t *o)
Definition: heap.c:387
#define GC_SET_SIZE(obj, size)
Definition: heap.h:42
s4 refcount
Definition: rootset.h:63
uintptr_t ptrint
Definition: types.hpp:54
void heap_dump_region(regioninfo_t *region, bool marked_only)
Definition: heap.c:476
vftbl_t * vftbl
Definition: global.hpp:264
#define printf(...)
Definition: ssa2.cpp:40
#define THREADOBJECT
Definition: thread-none.hpp:47
u4 region_resize(regioninfo_t *region, u4 size)
Definition: region.c:80
void heap_increase_size(rootset_t *rs)
Definition: heap.c:166
void exceptions_throw_outofmemoryerror(void)
Definition: exceptions.cpp:914