This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


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

RE: Java GC descriptor vs. tree_int_cst on 64-bit platforms


I tried this patch on Itanium.  It seemed to improve matters quite a bit.  I
tried tan(atan(10**200)) in the constructive reals calculator.  Without
threads, this runs correctly in spite of many garbage collections.  The UCSD
benchmark runs as well.

I think the following steps are still needed to get gcc 3.0 mostly working
for Java on Itanium.  I'd appreciate it if someone could check in the
patches for the first two.  (Something like the first should go into both
3.0 and the trunk.  The second should go into 3.0 only.  A larger one is
waiting for the trunk.)

(I still see at least one intermittent failure.  But it seems to be
threads-dependent, and much more subtle than the previous problems.)

1) The patch below.

2) A GC patch (attached, same as what I sent to Andrew earlier).  This also
fixes some generic bugs in currently unexercised code, and removes a generic
performance bug related to stack clearing.  (The patch could be pruned
further, but this version has a bit of mileage on it, and thus is probably
safer.  It includes one or two other changes that aren't absolutely
necessary without hash synchronization, which is not going into 3.0.)

3) Either a fix for try-finally miscompilation (greatly preferred), or a
hack to remove the two uses from libjava.  (Or has this been fixed already?)

4) A fix for the system-call in tail position miscompilation problem on IA64
(essential also for C/C++), or a check on the return value from gettimeofday
in the runtime (which moves the system call out of tail call position)

5) Unoptimized compilation of java/jcf-io.c.  (This seems to apply only to
the old, but still standard, toolchain.  If gcc3.0 is used to bootstrap, I
don't think this is an issue.)

6) A trunk CVS gdb in case anything goes wrong.  (The "standard" gdb in the
distributions is really awful.  Andrew pointed out that the CVS one is FAR
better, though not perfect.)

Hans

Index: boehm.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/boehm.c,v
retrieving revision 1.9
diff -u -r1.9 boehm.c
--- boehm.c	2000/12/15 17:35:03	1.9
+++ boehm.c	2001/03/28 18:00:30
@@ -48,7 +48,7 @@
 	    (((((env) << LOG_MAX_MARK_PROCS) | (proc_index)) << DS_TAG_BITS)
\
 	    | DS_PROC)
    Here DS_PROC == 2.  */
-#define PROCEDURE_OBJECT_DESCRIPTOR integer_two_node
+#define PROCEDURE_OBJECT_DESCRIPTOR build_int_2(2,0)
 
 /* Treat two HOST_WIDE_INT's as a contiguous bitmap, with bit 0 being
    the least significant.  This function sets bit N in the bitmap.  */
@@ -228,5 +228,6 @@
   else
     value = PROCEDURE_OBJECT_DESCRIPTOR;
 
+  TREE_TYPE(value) = type_for_mode (ptr_mode, 1);
   return value;
 }


----------------------------------------------------------------------------
-----

Garbage collector patch:

Index: boehm-gc/finalize.c
===================================================================
RCS file: /cvs/gcc/gcc/boehm-gc/finalize.c,v
retrieving revision 1.5
diff -u -r1.5 finalize.c
--- finalize.c	2000/05/07 00:43:49	1.5
+++ finalize.c	2001/03/15 22:38:53
@@ -324,6 +324,7 @@
     struct finalizable_object * curr_fo, * prev_fo;
     int index;
     struct finalizable_object *new_fo;
+    hdr *hhdr;
     DCL_LOCK_STATE;
 
 #   ifdef THREADS
@@ -402,6 +403,19 @@
 #	endif
         return;
     }
+    GET_HDR(base, hhdr);
+    if (0 == hhdr) {
+      /* We won't collect it, hence finalizer wouldn't be run. */
+      /* This is changed for gcj, but it will be in version 6.0 of the	*/
+      /* standard collector distribution.  It costs virtually nothing	*/
+      /* here, but it's expensive to check in the hash synchronization	*/
+      /* code, where it matters.		-HB			*/
+#     ifdef THREADS
+          UNLOCK();
+    	  ENABLE_SIGNALS();
+#     endif
+      return;
+    }
 #   ifdef THREADS
       new_fo = (struct finalizable_object *)
     	GC_generic_malloc_inner(sizeof(struct finalizable_object),NORMAL);
@@ -413,7 +427,7 @@
         new_fo -> fo_hidden_base = (word)HIDE_POINTER(base);
 	new_fo -> fo_fn = fn;
 	new_fo -> fo_client_data = (ptr_t)cd;
-	new_fo -> fo_object_size = GC_size(base);
+	new_fo -> fo_object_size = hhdr -> hb_sz;
 	new_fo -> fo_mark_proc = mp;
 	fo_set_next(new_fo, fo_head[index]);
 	GC_fo_entries++;
Index: boehm-gc/gc_priv.h
===================================================================
RCS file: /cvs/gcc/gcc/boehm-gc/gc_priv.h,v
retrieving revision 1.14
diff -u -r1.14 gc_priv.h
--- gc_priv.h	2000/09/04 21:46:26	1.14
+++ gc_priv.h	2001/03/15 22:38:53
@@ -890,6 +890,18 @@
 #   define SMALL_OBJ(bytes) ((bytes) <= WORDS_TO_BYTES(MAXOBJSZ))
 #   define ADD_SLOP(bytes) (bytes)
 # endif
+# ifndef MIN_WORDS
+    /* MIN_WORDS is the size of the smallest allocated object.	*/
+    /* 1 and 2 are the only valid values.			*/
+    /* 2 must be used if:					*/
+    /* - GC_gcj_malloc can be used for objects of size 		*/
+    /*   smaller than 2 words, or				*/
+#   if defined(GC_GCJ_SUPPORT)
+#     define MIN_WORDS 2   	/* Smallest allocated object.	*/
+#   else
+#     define MIN_WORDS 1
+#   endif
+# endif
 
 
 /*
Index: boehm-gc/gcconfig.h
===================================================================
RCS file: /cvs/gcc/gcc/boehm-gc/gcconfig.h,v
retrieving revision 1.15
diff -u -r1.15 gcconfig.h
--- gcconfig.h	2000/12/10 22:57:37	1.15
+++ gcconfig.h	2001/03/15 22:38:54
@@ -1116,11 +1116,20 @@
 #       define CPP_WORDSZ 64
 	/* This should really be done through /proc, but that	*/
 	/* requires we run on an IA64 kernel.			*/
-#       define STACKBOTTOM ((ptr_t) 0xa000000000000000l)
+	/* The following works on NUE and older kernels:	*/
+/* #       define STACKBOTTOM ((ptr_t) 0xa000000000000000l)	*/
+	/* This does not work on NUE:				*/
+#       define LINUX_STACKBOTTOM
 	/* We also need the base address of the register stack	*/
-	/* backing store.  There is probably a better way to	*/
-	/* get that, too ...					*/
-#	define BACKING_STORE_BASE ((ptr_t) 0x9fffffff80000000l)
+	/* backing store.  There should be a better way to get	*/
+	/* this:						*/
+#	define APPROX_BS_BASE ((word)GC_stackbottom-0x80000000)
+	/* We round to the next multiple of 1 MB, to compensate	*/
+	/* for the fact that the stack base is displaced by	*/
+	/* the environment, etc.				*/
+#	define BACKING_STORE_BASE \
+		(ptr_t)((APPROX_BS_BASE + 0xfffff) & ~0xfffff)
+
 #	if 1
 #	    define SEARCH_FOR_DATA_START
 #	    define DATASTART GC_data_start
Index: boehm-gc/gcj_mlc.c
===================================================================
RCS file: /cvs/gcc/gcc/boehm-gc/gcj_mlc.c,v
retrieving revision 1.2
diff -u -r1.2 gcj_mlc.c
--- gcj_mlc.c	2000/12/23 02:23:27	1.2
+++ gcj_mlc.c	2001/03/15 22:38:54
@@ -267,7 +267,6 @@
         } else {
             *opp = obj_link(op);
             GC_words_allocd += lw;
-            FASTUNLOCK();
         }
 	*(void **)op = ptr_to_struct_containing_descr;
 	UNLOCK();
Index: boehm-gc/linux_threads.c
===================================================================
RCS file: /cvs/gcc/gcc/boehm-gc/linux_threads.c,v
retrieving revision 1.8
diff -u -r1.8 linux_threads.c
--- linux_threads.c	2000/12/30 12:18:38	1.8
+++ linux_threads.c	2001/03/15 22:38:54
@@ -611,7 +611,7 @@
 	/* Needs to be plausible, since an asynchronous stack mark	*/
 	/* should not crash.						*/
 #   else
-      me -> stack_end = (ptr_t)(((word)(&dummy) & ~(GC_page_size - 1));
+      me -> stack_end = (ptr_t)((word)(&dummy) & ~(GC_page_size - 1));
       me -> stack_ptr = me -> stack_end + 0x10;
 #   endif
     /* This is dubious, since we may be more than a page into the stack, */
Index: boehm-gc/malloc.c
===================================================================
RCS file: /cvs/gcc/gcc/boehm-gc/malloc.c,v
retrieving revision 1.4
diff -u -r1.4 malloc.c
--- malloc.c	2000/04/19 10:09:58	1.4
+++ malloc.c	2001/03/15 22:38:54
@@ -52,7 +52,7 @@
 	  lw = GC_size_map[lb];
 #	else
 	  lw = ALIGNED_WORDS(lb);
-	  if (lw == 0) lw = 1;
+	  if (lw == 0) lw = MIN_WORDS;
 #       endif
 	opp = &(kind -> ok_freelist[lw]);
         if( (op = *opp) == 0 ) {
Index: boehm-gc/misc.c
===================================================================
RCS file: /cvs/gcc/gcc/boehm-gc/misc.c,v
retrieving revision 1.12
diff -u -r1.12 misc.c
--- misc.c	2000/04/19 10:09:58	1.12
+++ misc.c	2001/03/15 22:38:54
@@ -107,13 +107,17 @@
     {
 	register unsigned i;
 
-	/* Map size 0 to 1.  This avoids problems at lower levels. */
-	  GC_size_map[0] = 1;
+	/* Map size 0 to something bigger.			   */
+        /* This avoids problems at lower levels. 		   */
 	/* One word objects don't have to be 2 word aligned.	   */
-	  for (i = 1; i < sizeof(word); i++) {
-	      GC_size_map[i] = 1;
+	  for (i = 0; i < sizeof(word); i++) {
+	      GC_size_map[i] = MIN_WORDS;
 	  }
-	  GC_size_map[sizeof(word)] = ROUNDED_UP_WORDS(sizeof(word));
+#	  if MIN_WORDS > 1
+	    GC_size_map[sizeof(word)] = MIN_WORDS;
+#	  else
+	    GC_size_map[sizeof(word)] = ROUNDED_UP_WORDS(sizeof(word));
+#	  endif
 	for (i = sizeof(word) + 1; i <= 8 * sizeof(word); i++) {
 #           ifdef ALIGN_DOUBLE
 	      GC_size_map[i] = (ROUNDED_UP_WORDS(i) + 1) & (~1);
@@ -202,10 +206,10 @@
  */
 word GC_stack_last_cleared = 0;	/* GC_no when we last did this */
 # ifdef THREADS
-#   define CLEAR_SIZE 2048
-# else
-#   define CLEAR_SIZE 213
+#   define BIG_CLEAR_SIZE 2048	/* Clear this much now and then.	*/
+#   define SMALL_CLEAR_SIZE 256 /* Clear this much every time.		*/
 # endif
+# define CLEAR_SIZE 213  /* Granularity for GC_clear_stack_inner */
 # define DEGRADE_RATE 50
 
 word GC_min_sp;		/* Coolest stack pointer value from which
we've */
@@ -262,10 +266,12 @@
 {
     register word sp = (word)GC_approx_sp();  /* Hotter than actual sp */
 #   ifdef THREADS
-        word dummy[CLEAR_SIZE];
-#   else
-    	register word limit;
+        word dummy[SMALL_CLEAR_SIZE];
+	unsigned random_no = 0;  /* Should be more random than it is ... */
+				 /* Used to occasionally clear a bigger	 */
+				 /* chunk.				 */
 #   endif
+    register word limit;
     
 #   define SLOP 400
 	/* Extra bytes we clear every time.  This clears our own	*/
@@ -283,7 +289,14 @@
 	/* thus more junk remains accessible, thus the heap gets	*/
 	/* larger ...							*/
 # ifdef THREADS
-    BZERO(dummy, CLEAR_SIZE*sizeof(word));
+    if (++random_no % 13 == 0) {
+	limit = sp;
+	MAKE_HOTTER(limit, BIG_CLEAR_SIZE*sizeof(word));
+	return GC_lear_stack_inner(arg, limit);
+    } else {
+	BZERO(dummy, SMALL_CLEAR_SIZE*sizeof(word));
+	return arg;
+    }
 # else
     if (GC_gc_no > GC_stack_last_cleared) {
         /* Start things over, so we clear the entire stack again */
Index: boehm-gc/os_dep.c
===================================================================
RCS file: /cvs/gcc/gcc/boehm-gc/os_dep.c,v
retrieving revision 1.14
diff -u -r1.14 os_dep.c
--- os_dep.c	2000/06/19 18:46:45	1.14
+++ os_dep.c	2001/03/15 22:38:55
@@ -144,20 +144,37 @@
 #endif
 
 #if defined(SEARCH_FOR_DATA_START)
-  /* The following doesn't work if the GC is in a dynamic library.	*/
   /* The I386 case can be handled without a search.  The Alpha case	*/
   /* used to be handled differently as well, but the rules changed	*/
   /* for recent Linux versions.  This seems to be the easiest way to	*/
   /* cover all versions.						*/
-  ptr_t GC_data_start;
+
+# ifdef LINUX
+#   pragma weak __data_start
+    extern int __data_start;
+#   pragma weak data_start
+    extern int data_start;
+# endif /* LINUX */
+  extern int _end;
 
-  extern char * GC_copyright[];  /* Any data symbol would do. */
+  ptr_t GC_data_start;
 
   void GC_init_linux_data_start()
   {
     extern ptr_t GC_find_limit();
 
-    GC_data_start = GC_find_limit((ptr_t)GC_copyright, FALSE);
+#   ifdef LINUX
+      /* Try the easy approaches first:	*/
+      if (&__data_start != 0) {
+	  GC_data_start = (ptr_t)(&__data_start);
+	  return;
+      }
+      if (&data_start != 0) {
+	  GC_data_start = (ptr_t)(&data_start);
+	  return;
+      }
+#   endif /* LINUX */
+    GC_data_start = GC_find_limit((ptr_t)(&_end), FALSE);
   }
 #endif
 
Index: boehm-gc/test.c
===================================================================
RCS file: /cvs/gcc/gcc/boehm-gc/test.c,v
retrieving revision 1.4
diff -u -r1.4 test.c
--- test.c	2000/04/19 10:09:58	1.4
+++ test.c	2001/03/15 22:38:55
@@ -958,17 +958,17 @@
 		"This test program is not designed for leak detection
mode\n");
 	(void)GC_printf0("Expect lots of problems.\n");
 #   endif
-    if (GC_size(GC_malloc(7)) != 8
+    if (GC_size(GC_malloc(7)) != 8 &&
+	GC_size(GC_malloc(7)) != MIN_WORDS * sizeof(GC_word)
 	|| GC_size(GC_malloc(15)) != 16) {
 	    (void)GC_printf0("GC_size produced unexpected results\n");
 	    FAIL;
     }
-    if (GC_size(GC_malloc(0)) != 4 && GC_size(GC_malloc(0)) != 8) {
+    if (GC_size(GC_malloc(0)) != MIN_WORDS * sizeof(GC_word)) {
     	(void)GC_printf0("GC_malloc(0) failed\n");
 	    FAIL;
     }
-    if (GC_size(GC_malloc_uncollectable(0)) != 4
-        && GC_size(GC_malloc_uncollectable(0)) != 8) {
+    if (GC_size(GC_malloc_uncollectable(0)) != MIN_WORDS * sizeof(GC_word))
{
     	(void)GC_printf0("GC_malloc_uncollectable(0) failed\n");
 	    FAIL;
     }


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