This is the mail archive of the java-patches@gcc.gnu.org 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]

Re: Alignment problem with hashtable locks on PowerPC


Boehm, Hans wrote:

>That sounds basically right.  There's some argument that ALIGN_DOUBLE should
>be defined by the gcj configuration scripts, and that gcconfig.h should set it only if
>it's not already set, but required by the architecture. 
>
I agree. Unfortunatly its hard to do that reliably (I think), since the 
GC configuration is separate from libjava's, and its hard to get a value 
which is set by the libjava configure considering the GC configure can 
run first.

My hash-sync tests are running fine after that change. However the 
performance is disappointing. Here's the results of some "before and 
after" synchronization tests:

// RunTests.java (w/o hash sync) (500Mhz 7410)
Now running ping pong
The execution of ping pong took 6.387s
Now running Wait-Notify
7614
7615
The execution of Wait-Notify took 7.615s
Now running static factorial
The execution of static factorial took 11.676s
Now running synchronized factorial
The execution of synchronized factorial took 57.889s
Now running virtual factorial
The execution of virtual factorial took 8.604s
Now running interface call
The execution of interface call took 18.277s

// RunTests.java (w/ hash sync)
Now running ping pong
The execution of ping pong took 9.460s
Now running Wait-Notify
7801
7802
The execution of Wait-Notify took 7.807s
Now running static factorial
The execution of static factorial took 12.002s
Now running synchronized factorial
The execution of synchronized factorial took 68.473s
Now running virtual factorial
The execution of virtual factorial took 8.135s
Now running interface call
The execution of interface call took 18.080s

For comparison here's the same test on an x86 machine (650Mhz P3):

// P3 w/ hash sync
Now running ping pong
The execution of ping pong took 3.648s
Now running Wait-Notify
7473
7475
The execution of Wait-Notify took 7.475s
Now running static factorial
The execution of static factorial took 10.927s
Now running synchronized factorial
The execution of synchronized factorial took 57.176s
Now running virtual factorial
The execution of virtual factorial took 6.566s
Now running interface call
The execution of interface call took 12.451s


So the hash synchronization initially appears to be quite a bit slower 
for PPC, both for contended and uncontended locks. Note that other 
factors may have changed between the two runs (newwer GCC tree) which 
might have skewed the results a bit. I've heard that pthread_self() is 
pretty slow on ppc linux due to lack of provision for a thread register 
in the ABI, so that might have something to do with it - might be 
interesting to try with SLOW_PTHREAD_SELF and see if it helps things? My 
patch and the tests I used are attached.

Incidentally notice how virtual calls seem to be a lot faster than 
"normal" calls here. The gap gets even bigger with -fPIC...

regards

Bryce.


Index: gcc/java/decl.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/java/decl.c,v
retrieving revision 1.109
diff -u -r1.109 decl.c
--- decl.c	2001/09/22 18:50:09	1.109
+++ decl.c	2001/11/12 11:56:21
@@ -632,7 +632,9 @@
   set_super_info (0, class_type_node, object_type_node, 0);
   set_super_info (0, string_type_node, object_type_node, 0);
   class_ptr_type = build_pointer_type (class_type_node);
-
+  
+  TYPE_ALIGN (class_type_node) = BIGGEST_ALIGNMENT;
+  
   PUSH_FIELD (class_type_node, field, "next", class_ptr_type);
   PUSH_FIELD (class_type_node, field, "name", utf8const_ptr_type);
   PUSH_FIELD (class_type_node, field, "accflags", access_flags_type_node);
Index: boehm-gc/include/private/gc_priv.h
===================================================================
RCS file: /cvs/gcc/egcs/boehm-gc/include/private/gc_priv.h,v
retrieving revision 1.5
diff -u -r1.5 gc_priv.h
--- gc_priv.h	2001/10/23 00:28:56	1.5
+++ gc_priv.h	2001/11/12 11:56:22
@@ -205,6 +205,13 @@
    /* odd numbered words to have mark bits.				*/
 #endif
 
+#if defined(GC_GCJ_SUPPORT) && ALIGNMENT < 8 && !defined(ALIGN_DOUBLE)
+   /* GCJ's Hashtable synchronization code requires 64-bit alignment.	*/
+   /* Ideally, configure would be able to determine if hashtable 	*/
+   /* synchronization is used for this platform.			*/
+#  define ALIGN_DOUBLE
+#endif
+
 /* ALIGN_DOUBLE requires MERGE_SIZES at present. */
 # if defined(ALIGN_DOUBLE) && !defined(MERGE_SIZES)
 #   define MERGE_SIZES
Index: libjava/java/lang/natObject.cc
===================================================================
RCS file: /cvs/gcc/egcs/libjava/java/lang/natObject.cc,v
retrieving revision 1.20
diff -u -r1.20 natObject.cc
--- natObject.cc	2001/10/31 00:48:16	1.20
+++ natObject.cc	2001/11/12 11:56:22
@@ -429,6 +429,61 @@
   }
 #endif
 
+#if defined(__GNUC__) && defined(__powerpc__)
+  inline static bool
+  compare_and_swap(volatile obj_addr_t *addr,
+		  				obj_addr_t old,
+						obj_addr_t new_val) 
+  {
+    int ret;
+
+    __asm__ __volatile__ (
+	     "0:    lwarx %0,0,%1 ;"
+	     "      xor. %0,%3,%0;"
+	     "      bne 1f;"
+	     "      stwcx. %2,0,%1;"
+	     "      bne- 0b;"
+	     "1:    "
+	  : "=&r"(ret)
+	  : "r"(addr), "r"(new_val), "r"(old)
+	  : "cr0", "memory");
+    /* This version of __compare_and_swap is to be used when acquiring
+       a lock, so we don't need to worry about whether other memory
+       operations have completed, but we do need to be sure that any loads
+       after this point really occur after we have acquired the lock.  */
+    __asm__ __volatile__ ("isync" : : : "memory");
+    return ret == 0;
+  }
+
+  inline static void
+  release_set(volatile obj_addr_t *addr, obj_addr_t new_val)
+  {
+    __asm__ __volatile__ ("sync" : : : "memory");
+    *(addr) = new_val;
+  }
+
+  inline static bool
+  compare_and_swap_release(volatile obj_addr_t *addr,
+		  				       obj_addr_t old,
+						       obj_addr_t new_val)
+  {
+    int ret;
+
+    __asm__ __volatile__ ("sync" : : : "memory");
+    __asm__ __volatile__ (
+	     "0:    lwarx %0,0,%1 ;"
+	     "      xor. %0,%3,%0;"
+	     "      bne 1f;"
+	     "      stwcx. %2,0,%1;"
+	     "      bne- 0b;"
+	     "1:    "
+	  : "=&r"(ret)
+	  : "r"(addr), "r"(new_val), "r"(old)
+	  : "cr0", "memory");
+    return ret == 0;
+  }
+#endif
+
 // Try to determine whether we are on a multiprocessor, i.e. whether
 // spinning may be profitable.
 // This should really use a suitable autoconf macro.

Attachment: appeal-bench.tar.gz
Description: GNU Zip compressed data


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