This is the mail archive of the java-patches@sources.redhat.com mailing list for the Java project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Patch: Bitmap marking


I've cleaned up, tested, and written ChangeLog entries for the Boehm
GC bitmap descriptor marking patch. This is basically the same as Hans'
version of the patch, but with formatting fixes, and a fix for an
off-by-one error in the vtable copying code in _Jv_FindArrayClass. The
patch is working well with the current tree.

I've attached both the compiler patch and the runtime patch here.
Alex/Tom:  ok to commit?

regards

  [ bryce ]

2000-08-07  Hans Boehm  <boehm@acm.org>

	* boehm.c (mark_reference_fields): Set marking bits for all words in
	a multiple-word record.
	(get_boehm_type_descriptor): Use the procedure marking descriptor for
	java.lang.Class.
	
Index: boehm.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/java/boehm.c,v
retrieving revision 1.7
diff -u -r1.7 boehm.c
--- boehm.c	2000/05/05 04:23:22	1.7
+++ boehm.c	2000/08/08 08:37:07
@@ -95,17 +95,21 @@
   for (; field != NULL_TREE; field = TREE_CHAIN (field))
     {
       HOST_WIDE_INT offset;
+      HOST_WIDE_INT size_bytes;
 
       if (FIELD_STATIC (field))
 	continue;
 
       offset = int_byte_position (field);
+      size_bytes = int_size_in_bytes (TREE_TYPE (field));
       if (JREFERENCE_TYPE_P (TREE_TYPE (field))
 	  /* An `object' of type gnu.gcj.RawData is actually non-Java
 	     data.  */
 	  && TREE_TYPE (field) != rawdata_ptr_type_node)
 	{
 	  unsigned int count;
+	  unsigned int size_words;
+	  unsigned int i;
 
 	  /* If this reference slot appears to overlay a slot we think
 	     we already covered, then we are doomed.  */
@@ -113,11 +117,18 @@
 	    abort ();
 
 	  count = offset * BITS_PER_UNIT / POINTER_SIZE;
+	  size_words = size_bytes * BITS_PER_UNIT / POINTER_SIZE;
 
 	  *last_set_index = count;
-	  /* First word in object corresponds to most significant byte
-	     of bitmap.  */
-	  set_bit (low, high, ubit - count - 1);
+	     
+	  /* First word in object corresponds to most significant byte of 
+	     bitmap. For correctness, we set pointer bits for all words in the 
+	     record. This is conservative, but the size_words != 1 case is 
+	     impossible in java code, and we no longer use this code on 
+	     ClassClass. */
+	  for (i = 0; i < size_words; ++i)
+	    set_bit (low, high, ubit - count - i - 1);
+
 	  if (count > ubit - 2)
 	    *pointer_after_end = 1;
 
@@ -172,6 +183,9 @@
 
   /* Warning avoidance.  */
   ubit = (unsigned int) bit;
+
+  if (type == class_type_node)
+    return PROCEDURE_OBJECT_DESCRIPTOR;
 
   field = TYPE_FIELDS (type);
   mark_reference_fields (field, &low, &high, ubit,
2000-08-08  Hans Boehm  <boehm@acm.org>
	    Bryce McKinlay  <bryce@albatross.co.nz>
	    
	Implement bitmap descriptor based marking for Boehm GC.

	* configure.in: Define JC1GCSPEC. Set it if boehm-gc is used.
	* configure: Rebuilt.
	* libgcj.spec.in: Pass JC1GCSPEC to jc1.
	* include/jvm.h (struct _Jv_VTable): New field `gc_descr'. New inline
	method get_finalizer().
	(struct _Jv_ArrayVTable): Ditto. Declare method array with 
	NUM_OBJECT_METHODS elements instead of NUM_OBJECT_METHODS + 1.
	(_Jv_AllocObj): Add new jclass parameter.
	(_Jv_AllocArray): Ditto.
	(_Jv_BuildGCDescr): New prototype.
	* prims.cc (_Jv_AllocObject): Rename parameter `c' to `klass'. Pass
	`klass' to _Jv_AllocObj. Don't set the new object's vtable. Use
	get_finalizer() instead of direct finalizer vtable offset.
	(_Jv_NewObjectArray): Rename parameter `clas' to `klass'. Pass
	`klass' to _Jv_AllocArray. Don't set the new array's vtable.
	(_Jv_NewPrimArray): Call _Jv_FindArrayClass before _Jv_AllocObj. Pass
	`klass' to _Jv_AllocObj. Don't set the new array's vtable.
	* resolve.cc (METHOD_NOT_THERE, METHOD_INACCESSIBLE): New #defines.
	(_Jv_ResolvePoolEntry): Use METHOD_NOT_THERE and METHOD_INACCESSIBLE.
	(_Jv_DetermineVTableIndex): Ditto.
	(_Jv_PrepareClass): Ditto. Remove offset-by-one adjustments from vtable 
	calculations to account for new gc_descr field.
	* boehm.cc: #include gc_gcj.h.
	(obj_kind_x, obj_free_list): `#if 0'-ed away.
	(_Jv_MarkObj): Check that vtable doesn't point to a cleared object.
	New commentary from HB. Mark the classes vtable.
	(_Jv_MarkArray): Check that vtable doesn't point to a cleared object.
	(GC_DEFAULT_DESCR): New #define.
	(_Jv_BuildGCDescr): New function. Use GC_DEFAULT_DESCR, for now.	
	(_Jv_AllocObj): New parameter `klass'. Use GC_GCJ_MALLOC ().
	(_Jv_AllocArray): New parameter `klass'. Allocate with GC_MALLOC and
	scan conservativly if size is less than min_heap_addr. Set vtable 
	pointer of new object before returning.
	(_Jv_AllocBytes): Use GC_MALLOC_ATOMIC, not GC_GENERIC_MALLOC.
	(_Jv_InitGC): Call GC_init_gcj_malloc(). Don't set up marking and
	allocation for obj_kind_x.
	* nogc.cc (_Jv_BuildGCDescr): New function. Return 0.
	(_Jv_AllocObj): Set vtable on returned object.
	(_Jv_AllocArray): Ditto.
	* java/lang/Class.h (_Jv_NewObjectArray): No longer a friend.
	(_Jv_NewPrimArray): Ditto.
	(_Jv_AllocObj): Declare as a friend.
	(_Jv_AllocArray): Ditto.	
	* java/lang/natClassLoader.cc (_Jv_FindArrayClass): Copy gc_descr
	from &ObjectClass into new array class. Remove offset-by-one 
	adjustments from `method' size calculations to account for gc_descr 
	field.

Index: configure.in
===================================================================
RCS file: /cvs/java/libgcj/libjava/configure.in,v
retrieving revision 1.59
diff -u -r1.59 configure.in
--- configure.in	2000/05/20 20:26:51	1.59
+++ configure.in	2000/08/08 08:35:13
@@ -208,6 +208,7 @@
 GCDEPS=
 GCOBJS=
 GCSPEC=
+JC1GCSPEC=
 GCTESTSPEC=
 case "$GC" in
  boehm)
@@ -218,6 +219,7 @@
     GCLIBS="$GCDEPS -L\$(here)/../boehm-gc/$libsubdir"
     GCINCS='-I$(top_srcdir)/../boehm-gc -I$(top_builddir)/../boehm-gc'
     GCSPEC='-lgcjgc'
+    JC1GCSPEC='-fuse-boehm-gc'
     GCTESTSPEC="-L`pwd`/../boehm-gc/.libs -rpath `pwd`/../boehm-gc/.libs"
     dnl We also want to pick up some cpp flags required when including
     dnl boehm-config.h.  Yuck.
@@ -241,6 +243,7 @@
 AC_SUBST(GCDEPS)
 AC_SUBST(GCOBJS)
 AC_SUBST(GCSPEC)
+AC_SUBST(JC1GCSPEC)
 AC_SUBST(GCTESTSPEC)
 AC_LINK_FILES(include/$GCHDR, include/java-gc.h)
 
Index: libgcj.spec.in
===================================================================
RCS file: /cvs/java/libgcj/libjava/libgcj.spec.in,v
retrieving revision 1.11
diff -u -r1.11 libgcj.spec.in
--- libgcj.spec.in	2000/05/20 20:26:51	1.11
+++ libgcj.spec.in	2000/08/08 08:35:13
@@ -6,7 +6,7 @@
 %rename lib liborig
 *lib: -lgcj -lm @GCSPEC@ @THREADSPEC@ @ZLIBSPEC@ @SYSTEMSPEC@ %(liborig)
 
-*jc1:  @DIVIDESPEC@ @EXCEPTIONSPEC@ -fasynchronous-exceptions
+*jc1:  @DIVIDESPEC@ @EXCEPTIONSPEC@ @JC1GCSPEC@ -fasynchronous-exceptions
 
 #
 # libgcc should really be a shared library.  This is a design flaw
Index: boehm.cc
===================================================================
RCS file: /cvs/java/libgcj/libjava/boehm.cc,v
retrieving revision 1.20
diff -u -r1.20 boehm.cc
--- boehm.cc	2000/05/06 23:32:52	1.20
+++ boehm.cc	2000/08/08 08:35:13
@@ -28,6 +28,7 @@
 {
 #include <gc_priv.h>
 #include <gc_mark.h>
+#include <include/gc_gcj.h>
 
   // These aren't declared in any Boehm GC header.
   void GC_finalize_all (void);
@@ -58,15 +59,17 @@
 // Nonzero if this module has been initialized.
 static int initialized = 0;
 
+#if 0
 // `kind' index used when allocating Java objects.
 static int obj_kind_x;
 
-// `kind' index used when allocating Java arrays.
-static int array_kind_x;
-
 // Freelist used for Java objects.
 static ptr_t *obj_free_list;
+#endif /* 0 */
 
+// `kind' index used when allocating Java arrays.
+static int array_kind_x;
+
 // Freelist used for Java arrays.
 static ptr_t *array_free_list;
 
@@ -79,16 +82,24 @@
 // object.  We use `void *' arguments and return, and not what the
 // Boehm GC wants, to avoid pollution in our headers.
 void *
-_Jv_MarkObj (void *addr, void *msp, void *msl, void * /*env*/)
+_Jv_MarkObj (void *addr, void *msp, void *msl, void * /* env */)
 {
   mse *mark_stack_ptr = (mse *) msp;
   mse *mark_stack_limit = (mse *) msl;
   jobject obj = (jobject) addr;
 
+  // FIXME: if env is 1, this object was allocated through the debug
+  // interface, and addr points to the beginning of the debug header.
+  // In that case, we should really add the size of the header to addr.
+
   _Jv_VTable *dt = *(_Jv_VTable **) addr;
-  // We check this in case a GC occurs before the vtbl is set.  FIXME:
-  // should use allocation lock while initializing object.
-  if (__builtin_expect (! dt, false))
+  // The object might not yet have its vtable set, or it might
+  // really be an object on the freelist.  In either case, the vtable slot
+  // will either be 0, or it will point to a cleared object.
+  // This assumes Java objects have size at least 3 words,
+  // including the header.   But this should remain true, since this
+  // should only be used with debugging allocation or with large objects.
+  if (__builtin_expect (! dt || !(dt -> get_finalizer()), false))
     return mark_stack_ptr;
   jclass klass = dt->clas;
 
@@ -101,6 +112,18 @@
 
   if (__builtin_expect (klass == &ClassClass, false))
     {
+      // Currently we allocate some of the memory referenced from class objects
+      // as pointerfree memory, and then mark it more intelligently here.
+      // We ensure that the ClassClass mark descriptor forces invocation of
+      // this procedure.
+      // Correctness of this is subtle, but it looks OK to me for now.  For the incremental
+      // collector, we need to make sure that the class object is written whenever
+      // any of the subobjects are altered and may need rescanning.  This may be tricky
+      // during construction, and this may not be the right way to do this with
+      // incremental collection.
+      // If we overflow the mark stack, we will rescan the class object, so we should
+      // be OK.  The same applies if we redo the mark phase because win32 unmapped part
+      // of our root set.		- HB
       jclass c = (jclass) addr;
 
       p = (ptr_t) c->name;
@@ -121,6 +144,8 @@
 	  MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c, c5alabel);
 	  p = (ptr_t) c->constants.data;
 	  MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c, c5blabel);
+	  p = (ptr_t) c->vtable;
+	  MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c, c5clabel);
 	}
 #endif
 
@@ -272,9 +297,10 @@
   jobjectArray array = (jobjectArray) addr;
 
   _Jv_VTable *dt = *(_Jv_VTable **) addr;
-  // We check this in case a GC occurs before the vtbl is set.  FIXME:
-  // should use allocation lock while initializing object.
-  if (__builtin_expect (! dt, false))
+  // Assumes size >= 3 words.  That's currently true since arrays have
+  // a vtable, sync pointer, and size.  If the sync pointer goes away,
+  // we may need to round up the size.
+  if (__builtin_expect (! dt || !(dt -> get_finalizer()), false))
     return mark_stack_ptr;
   jclass klass = dt->clas;
 
@@ -295,29 +321,62 @@
   return mark_stack_ptr;
 }
 
-// Allocate space for a new Java object.  FIXME: this might be the
-// wrong interface; we might prefer to pass in the object type as
-// well.  It isn't important for this collector, but it might be for
-// other collectors.
+// Return GC descriptor for interpreted class
+#ifdef INTERPRETER
+
+// We assume that the gcj mark proc has index 0.  This is a dubious assumption,
+// since another one could be registered first.  But the compiler also
+// knows this, so in that case everything else will break, too.
+#define GCJ_DEFAULT_DESCR MAKE_PROC(GCJ_RESERVED_MARK_PROC_INDEX,0)
 void *
-_Jv_AllocObj (jsize size)
+_Jv_BuildGCDescr(jclass klass)
 {
-  return GC_GENERIC_MALLOC (size, obj_kind_x);
+  /* FIXME: We should really look at the class and build the descriptor. */
+  return (void *)(GCJ_DEFAULT_DESCR);
 }
+#endif
 
-// Allocate space for a new Java array.  FIXME: again, this might be
-// the wrong interface.
+// Allocate space for a new Java object.
 void *
-_Jv_AllocArray (jsize size)
+_Jv_AllocObj (jsize size, jclass klass)
 {
-  return GC_GENERIC_MALLOC (size, array_kind_x);
+  return GC_GCJ_MALLOC (size, klass->vtable);
 }
 
+// Allocate space for a new Java array.
+// Used only for arrays of objects.
+void *
+_Jv_AllocArray (jsize size, jclass klass)
+{
+  void *obj;
+  const jsize min_heap_addr = 16*1024;
+	/* A heuristic.  If size is less than this value, the size	*/
+	/* stored in the array can't possibly be misinterpreted as	*/
+	/* a pointer.   Thus we lose nothing by scanning the object	*/
+	/* completely conservatively, since no misidentification can	*/
+	/* take place.							*/
+  
+# ifdef GC_DEBUG
+    // There isn't much to lose by scanning this conservatively.
+    // If we didn't, the mark proc would have to understand that
+    // it needed to skip the header.
+    obj = GC_MALLOC(size);
+# else
+    if (size < min_heap_addr) {
+      obj = GC_MALLOC(size);
+    } else {
+      obj = GC_GENERIC_MALLOC (size, array_kind_x);
+    }
+# endif
+  *((_Jv_VTable **) obj) = klass->vtable;
+  return obj;
+}
+
 // Allocate some space that is known to be pointer-free.
 void *
 _Jv_AllocBytes (jsize size)
 {
-  void *r = GC_GENERIC_MALLOC (size, PTRFREE);
+  void *r = GC_MALLOC_ATOMIC (size);
   // We have to explicitly zero memory here, as the GC doesn't
   // guarantee that PTRFREE allocations are zeroed.  Note that we
   // don't have to do this for other allocation types because we set
@@ -423,6 +482,56 @@
       return;
     }
   initialized = 1;
+  UNLOCK ();
+
+  // Configure the collector to use the bitmap marking descriptors that we
+  // stash in the class vtable.
+  GC_init_gcj_malloc (0, (void *) _Jv_MarkObj);  
+
+  LOCK ();
+  GC_java_finalization = 1;
+
+  // We use a different mark procedure for object arrays. This code 
+  // configures a different object `kind' for object array allocation and
+  // marking. FIXME: see above.
+  array_free_list = (ptr_t *) GC_generic_malloc_inner ((MAXOBJSZ + 1)
+						       * sizeof (ptr_t),
+						       PTRFREE);
+  memset (array_free_list, 0, (MAXOBJSZ + 1) * sizeof (ptr_t));
+
+  proc = GC_n_mark_procs++;
+  GC_mark_procs[proc] = (mark_proc) _Jv_MarkArray;
+
+  array_kind_x = GC_n_kinds++;
+  GC_obj_kinds[array_kind_x].ok_freelist = array_free_list;
+  GC_obj_kinds[array_kind_x].ok_reclaim_list = 0;
+  GC_obj_kinds[array_kind_x].ok_descriptor = MAKE_PROC (proc, 0);
+  GC_obj_kinds[array_kind_x].ok_relocate_descr = FALSE;
+  GC_obj_kinds[array_kind_x].ok_init = TRUE;
+
+  _Jv_MutexInit (&disable_gc_mutex);
+
+  UNLOCK ();
+  ENABLE_SIGNALS ();
+}
+
+#if 0
+void
+_Jv_InitGC (void)
+{
+  int proc;
+  DCL_LOCK_STATE;
+
+  DISABLE_SIGNALS ();
+  LOCK ();
+
+  if (initialized)
+   {
+     UNLOCK ();
+     ENABLE_SIGNALS ();
+     return;
+   }
+  initialized = 1;
 
   GC_java_finalization = 1;
 
@@ -464,3 +573,4 @@
   UNLOCK ();
   ENABLE_SIGNALS ();
 }
+#endif /* 0 */
Index: nogc.cc
===================================================================
RCS file: /cvs/java/libgcj/libjava/nogc.cc,v
retrieving revision 1.6
diff -u -r1.6 nogc.cc
--- nogc.cc	2000/04/02 15:34:17	1.6
+++ nogc.cc	2000/08/08 08:35:13
@@ -19,18 +19,30 @@
 // Total amount of memory allocated.
 static long total = 0;
 
+#ifdef INTERPRETER
 void *
-_Jv_AllocObj (jsize size)
+_Jv_BuildGCDescr(jclass klass)
 {
+  return 0;
+}
+#endif
+
+void *
+_Jv_AllocObj (jsize size, jclass klass)
+{
   total += size;
-  return calloc (size, 1);
+  ptr_t obj = calloc (size, 1);
+  *((_Jv_VTable **) obj) = klass->vtable;
+  return obj;
 }
 
 void *
-_Jv_AllocArray (jsize size)
+_Jv_AllocArray (jsize size, jclass klass)
 {
   total += size;
-  return calloc (size, 1);
+  ptr_t obj = calloc (size, 1);
+  *((_Jv_VTable **) obj) = klass->vtable;
+  return obj;
 }
 
 void *
Index: prims.cc
===================================================================
RCS file: /cvs/java/libgcj/libjava/prims.cc,v
retrieving revision 1.33
diff -u -r1.33 prims.cc
--- prims.cc	2000/06/20 13:30:14	1.33
+++ prims.cc	2000/08/08 08:35:14
@@ -331,18 +331,17 @@
   return r;
 }
 
-// Allocate a new object of class C.  SIZE is the size of the object
+// Allocate a new object of class KLASS.  SIZE is the size of the object
 // to allocate.  You might think this is redundant, but it isn't; some
 // classes, such as String, aren't of fixed size.
 jobject
-_Jv_AllocObject (jclass c, jint size)
+_Jv_AllocObject (jclass klass, jint size)
 {
-  _Jv_InitClass (c);
+  _Jv_InitClass (klass);
 
-  jobject obj = (jobject) _Jv_AllocObj (size);
+  jobject obj = (jobject) _Jv_AllocObj (size, klass);
   if (__builtin_expect (! obj, false))
     JvThrow (no_memory);
-  *((_Jv_VTable **) obj) = c->vtable;
 
   // If this class has inherited finalize from Object, then don't
   // bother registering a finalizer.  We know that finalize() is the
@@ -351,7 +350,7 @@
   // implementation would look for Object.finalize in Object's method
   // table at startup, and then use that information to find the
   // appropriate index in the method vector.
-  if (c->vtable->method[1] != ObjectClass.vtable->method[1])
+  if (klass->vtable->get_finalizer() != ObjectClass.vtable->get_finalizer())
     _Jv_RegisterFinalizer (obj, _Jv_FinalizeObject);
 
 #ifdef ENABLE_JVMPI
@@ -364,7 +363,7 @@
       event.event_type = JVMPI_EVENT_OBJECT_ALLOC;
       event.env_id = NULL;
       event.u.obj_alloc.arena_id = 0;
-      event.u.obj_alloc.class_id = (jobjectID) c;
+      event.u.obj_alloc.class_id = (jobjectID) klass;
       event.u.obj_alloc.is_array = 0;
       event.u.obj_alloc.size = size;
       event.u.obj_alloc.obj_id = (jobjectID) obj;
@@ -401,9 +400,9 @@
   size += count * sizeof (jobject);
 
   // FIXME: second argument should be "current loader" //
-  jclass clas = _Jv_FindArrayClass (elementClass, 0);
+  jclass klass = _Jv_FindArrayClass (elementClass, 0);
 
-  obj = (jobjectArray) _Jv_AllocArray (size);
+  obj = (jobjectArray) _Jv_AllocArray (size, klass);
   if (__builtin_expect (! obj, false))
     JvThrow (no_memory);
   obj->length = count;
@@ -415,10 +414,6 @@
       while (--count >= 0)
 	*ptr++ = init;
     }
-  // Set the vtbl last to avoid problems if the GC happens during the
-  // window in this function between the allocation and this
-  // assignment.
-  *((_Jv_VTable **) obj) = clas->vtable;
   return obj;
 }
 
@@ -440,17 +435,14 @@
 			(SIZE_T_MAX - size) / elsize, false))
     JvThrow (no_memory);
 
-  __JArray *arr = (__JArray*) _Jv_AllocObj (size + elsize * count);
+  jclass klass = _Jv_FindArrayClass (eltype, 0);
+
+  __JArray *arr = (__JArray*) _Jv_AllocObj (size + elsize * count, klass);
   if (__builtin_expect (! arr, false))
     JvThrow (no_memory);
   arr->length = count;
   // Note that we assume we are given zeroed memory by the allocator.
 
-  jclass klass = _Jv_FindArrayClass (eltype, 0);
-  // Set the vtbl last to avoid problems if the GC happens during the
-  // window in this function between the allocation and this
-  // assignment.
-  *((_Jv_VTable **) arr) = klass->vtable;
   return arr;
 }
 
Index: resolve.cc
===================================================================
RCS file: /cvs/java/libgcj/libjava/resolve.cc,v
retrieving revision 1.17
diff -u -r1.17 resolve.cc
--- resolve.cc	2000/03/26 20:33:03	1.17
+++ resolve.cc	2000/08/08 08:35:14
@@ -46,6 +46,9 @@
 #define ObjectClass _CL_Q34java4lang6Object
 extern java::lang::Class ObjectClass;
 
+// Exceptional return values for _Jv_DetermineVTableIndex
+#define METHOD_NOT_THERE (-2)
+#define METHOD_INACCESSIBLE (-1)
 
 static int get_alignment_from_class (jclass);
 
@@ -299,7 +302,7 @@
 	vtable_index = _Jv_DetermineVTableIndex
 	  (found_class, method_name, method_signature);
 
-      if (vtable_index == 0)
+      if (vtable_index == METHOD_NOT_THERE)
 	throw_incompatible_class_change_error
 	  (JvNewStringLatin1 ("method not found"));
 
@@ -378,9 +381,9 @@
     things if compiled classes to know vtable offset, and _Jv_Method had
     a field for this.
 
-    Returns 0  if this class does not declare the given method.
-    Returns -1 if the given method does not appear in the vtable.
-               i.e., it is static, private, final or a constructor.
+    Returns METHOD_NOT_THERE if this class does not declare the given method.
+    Returns METHOD_INACCESSIBLE if the given method does not appear in the
+		vtable, i.e., it is static, private, final or a constructor.
     Otherwise, returns the vtable index.  */
 int 
 _Jv_DetermineVTableIndex (jclass klass,
@@ -396,7 +399,7 @@
       int prev = _Jv_DetermineVTableIndex (super_class,
 					   name,
 					   signature);
-      if (prev != 0)
+      if (prev != METHOD_NOT_THERE)
 	return prev;
     }
 
@@ -410,7 +413,7 @@
 
   /* now, if we do not declare this method, return zero */
   if (meth == NULL)
-    return 0;
+    return METHOD_NOT_THERE;
 
   /* so now, we know not only that the super class does not declare the
    * method, but we do!  So, this is a first declaration of the method. */
@@ -427,21 +430,21 @@
 			 | Modifier::FINAL)) != 0
       || (klass->accflags & Modifier::FINAL) != 0
       || _Jv_equalUtf8Consts (name, init_name))
-    return -1;
+    return METHOD_INACCESSIBLE;
 
   /* reaching this point, we know for sure, that the method in question
    * will be in the vtable.  The question is where. */
 
   /* the base offset, is where we will start assigning vtable
-   * indexes for this class.  It is 1 for base classes
-   * (vtable->method[0] is unused), and for non-base classes it is the
-   * number of entries in the super class' vtable plus 1. */
+   * indexes for this class.  It is 0 for base classes
+   * and for non-base classes it is the
+   * number of entries in the super class' vtable. */
 
   int base_offset;
   if (super_class == 0)
-    base_offset = 1;
+    base_offset = 0;
   else
-    base_offset = super_class->vtable_method_count+1;
+    base_offset = super_class->vtable_method_count;
 
   /* we will consider methods 0..this_method_index-1.  And for each one,
    * determine if it is new (i.e., if it appears in the super class),
@@ -704,6 +707,7 @@
     _Jv_AllocBytesChecked (sizeof (_Jv_VTable) 
 			   + (sizeof (void*) * (vtable_count)));
   vtable->clas = clz;
+  vtable->gc_descr = _Jv_BuildGCDescr(clz);
 
   {
     jclass effective_superclass = super_class;
@@ -713,10 +717,10 @@
     while (effective_superclass && effective_superclass->vtable == NULL)
       effective_superclass = effective_superclass->superclass;
 
-    /* copy super class' vtable entries (index 0 goes unused). */
+    /* copy super class' vtable entries. */
     if (effective_superclass && effective_superclass->vtable)
-      memcpy ((void*)&vtable->method[1],
-	      (void*)&effective_superclass->vtable->method[1],
+      memcpy ((void*)&vtable->method[0],
+	      (void*)&effective_superclass->vtable->method[0],
 	      sizeof (void*) * effective_superclass->vtable_method_count);
   }
 
@@ -729,12 +733,12 @@
 					    this_meth->name,
 					    this_meth->signature);
 
-      if (index == 0)
+      if (index == METHOD_NOT_THERE)
 	throw_internal_error ("method now found in own class");
 
-      if (index != -1)
+      if (index != METHOD_INACCESSIBLE)
 	{
-	  if (index > clz->vtable_method_count+1)
+	  if (index > clz->vtable_method_count)
 	    throw_internal_error ("vtable problem...");
 
 	  if (clz->interpreted_methods[i] == 0)
Index: include/jvm.h
===================================================================
RCS file: /cvs/java/libgcj/libjava/include/jvm.h,v
retrieving revision 1.25
diff -u -r1.25 jvm.h
--- jvm.h	2000/05/31 23:50:37	1.25
+++ jvm.h	2000/08/08 08:35:14
@@ -31,7 +31,9 @@
 struct _Jv_VTable
 {
   jclass clas;
+  void *gc_descr;
   void *method[1];
+  void *get_finalizer() { return method[0]; }
 };
 
 // Number of virtual methods on object.  FIXME: it sucks that we have
@@ -42,8 +44,9 @@
 struct _Jv_ArrayVTable
 {
   jclass clas;
-  // `+1' because there is an extra slot for C++ RTTI compatibility.
-  void *method[NUM_OBJECT_METHODS + 1];
+  void *gc_descr;
+  void *method[NUM_OBJECT_METHODS];
+  void *get_finalizer() { return method[0]; }
 };
 
 union _Jv_word
@@ -106,15 +109,19 @@
 typedef void _Jv_FinalizerFunc (jobject);
 
 /* Allocate space for a new Java object.  */
-void *_Jv_AllocObj (jsize size) __attribute__((__malloc__));
+void *_Jv_AllocObj (jsize size, jclass cl) __attribute__((__malloc__));
 /* Allocate space for an array of Java objects.  */
-void *_Jv_AllocArray (jsize size) __attribute__((__malloc__));
+void *_Jv_AllocArray (jsize size, jclass cl) __attribute__((__malloc__));
 /* Allocate space that is known to be pointer-free.  */
 void *_Jv_AllocBytes (jsize size) __attribute__((__malloc__));
 /* Initialize the GC.  */
 void _Jv_InitGC (void);
 /* Register a finalizer.  */
 void _Jv_RegisterFinalizer (void *object, _Jv_FinalizerFunc *method);
+/* Compute the GC descriptor for a class */
+#ifdef INTERPRETER
+void * _Jv_BuildGCDescr(jclass);
+#endif
 
 /* Allocate some unscanned, unmoveable memory.  Return NULL if out of
    memory.  */
Index: java/lang/natClassLoader.cc
===================================================================
RCS file: /cvs/java/libgcj/libjava/java/lang/natClassLoader.cc,v
retrieving revision 1.25
diff -u -r1.25 natClassLoader.cc
--- natClassLoader.cc	2000/07/20 19:31:16	1.25
+++ natClassLoader.cc	2000/08/08 08:35:15
@@ -586,16 +586,15 @@
       array_class = _Jv_NewClass (array_name, &ObjectClass, element->loader);
 
       // Note that `vtable_method_count' doesn't include the initial
-      // NULL slot.
+      // gc_descr slot.
       JvAssert (ObjectClass.vtable_method_count == NUM_OBJECT_METHODS);
-      int dm_count = ObjectClass.vtable_method_count + 1;
+      int dm_count = ObjectClass.vtable_method_count;
 
       // Create a new vtable by copying Object's vtable (except the
       // class pointer, of course).  Note that we allocate this as
       // unscanned memory -- the vtables are handled specially by the
       // GC.
-      int size = (sizeof (_Jv_VTable) +
-		  ((dm_count - 1) * sizeof (void *)));
+      int size = (sizeof (_Jv_VTable) + ((dm_count - 1) * sizeof (void *)));
       _Jv_VTable *vtable;
       if (array_vtable)
 	vtable = array_vtable;
@@ -604,6 +603,7 @@
       vtable->clas = array_class;
       memcpy (vtable->method, ObjectClass.vtable->method,
 	      dm_count * sizeof (void *));
+      vtable->gc_descr = ObjectClass.vtable->gc_descr;
       array_class->vtable = vtable;
       array_class->vtable_method_count = ObjectClass.vtable_method_count;
 
@@ -615,6 +615,8 @@
       array_class->interfaces = interfaces;
       array_class->interface_count = sizeof interfaces / sizeof interfaces[0];
 
+      // FIXME: Shouldn't this be synchronized? _Jv_PrepareConstantTimeTables
+      // needs to be called with the mutex for array_class held.
       // Generate the interface dispatch table.
       _Jv_PrepareConstantTimeTables (array_class);
 
Index: java/lang/Class.h
===================================================================
RCS file: /cvs/java/libgcj/libjava/java/lang/Class.h,v
retrieving revision 1.24
diff -u -r1.24 Class.h
--- Class.h	2000/06/15 12:04:50	1.24
+++ Class.h	2000/08/08 08:35:15
@@ -220,8 +220,8 @@
   friend jint JvNumStaticFields (jclass);
 
   friend jobject _Jv_AllocObject (jclass, jint);
-  friend jobjectArray _Jv_NewObjectArray (jsize, jclass, jobject);
-  friend jobject _Jv_NewPrimArray (jclass, jint);
+  friend void *_Jv_AllocObj (jint, jclass);
+  friend void *_Jv_AllocArray (jint, jclass);
 
   friend jobject _Jv_JNI_ToReflectedField (_Jv_JNIEnv *, jclass, jfieldID,
 					   jboolean);


2000-08-08  Hans Boehm  <boehm@acm.org>
            Bryce McKinlay  <bryce@albatross.co.nz>

	* Makefile.am: Build gcj_mlc.c.
	* Makefile.in: Rebuilt.
	* configure.in: Define GC_GCJ_SUPPORT. Don't define NO_DEBUGGING unless
	cross-compiling.
	* configure: Rebuilt.

	
Index: Makefile.am
===================================================================
RCS file: /cvs/java/libgcj/boehm-gc/Makefile.am,v
retrieving revision 1.15
diff -u -r1.15 Makefile.am
--- Makefile.am	2000/04/19 12:47:53	1.15
+++ Makefile.am	2000/08/08 08:36:23
@@ -27,7 +27,7 @@
 EXTRA_LTLIBRARIES = libgcjgc.la
 libgcjgc_la_SOURCES = allchblk.c alloc.c blacklst.c checksums.c	\
 gcconfig.h dbg_mlc.c dyn_load.c finalize.c gc.h gc_alloc.h gc_cpp.h \
-gc_hdrs.h gc_mark.h gc_priv.h gc_private.h gc_typed.h headers.c	\
+gc_hdrs.h gc_mark.h gc_priv.h gc_private.h gc_typed.h gcj_mlc.c headers.c	\
 hpux_irix_threads.c linux_threads.c malloc.c mallocx.c mark.c mark_rts.c \
 misc.c new_hblk.c obj_map.c os_dep.c pcr_interface.c ptr_chck.c	\
 real_malloc.c reclaim.c solaris_pthreads.c solaris_threads.c \
Index: configure.in
===================================================================
RCS file: /cvs/java/libgcj/boehm-gc/configure.in,v
retrieving revision 1.18
diff -u -r1.18 configure.in
--- configure.in	2000/07/24 04:20:09	1.18
+++ configure.in	2000/08/08 08:36:24
@@ -193,8 +193,8 @@
 dnl embedded Java.
 AC_DEFINE(SILENT)
 AC_DEFINE(NO_SIGNALS)
-AC_DEFINE(NO_DEBUGGING)
 AC_DEFINE(JAVA_FINALIZATION)
+AC_DEFINE(GC_GCJ_SUPPORT)
 
 dnl This is something of a hack.  When cross-compiling we turn off
 dnl some functionality.  We also enable the "small" configuration.
@@ -203,6 +203,7 @@
    AC_DEFINE(NO_SIGSET)
    AC_DEFINE(NO_CLOCK)
    AC_DEFINE(SMALL_CONFIG)
+   AC_DEFINE(NO_DEBUGGING)
 fi
 
 AM_CONDITIONAL(USE_LIBDIR, test -z "$with_cross_host")

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]