#! /bin/sh -e

# DP: libobjc update taken from the 3.4.1 release.

dir=
if [ $# -eq 3 -a "$2" = '-d' ]; then
    pdir="-d $3"
    dir="$3/"
elif [ $# -ne 1 ]; then
    echo >&2 "`basename $0`: script expects -patch|-unpatch as argument"
    exit 1
fi
case "$1" in
    -patch)
        patch $pdir -f --no-backup-if-mismatch -p1 < $0
        ;;
    -unpatch)
        patch $pdir -f --no-backup-if-mismatch -R -p1 < $0
        ;;
    *)
        echo >&2 "`basename $0`: script expects -patch|-unpatch as argument"
        exit 1
esac
exit 0

libobjc:
2004-03-01  Michael Matz  <matz@suse.de>

	* Makefile.in (ALL_CFLAGS): Add -fno-strict-aliasing.

2004-01-14  Adam Fedor  <fedor@gnu.org>

	PR libobjc/12155
	* selector.c (__objc_register_instance_methods_to_class): Free
	new_list if not used.

2004-01-09  Andrew Ruder  <aeruder@ksu.edu>

	PR libobjc/11904
	* sarray.c (sarray_free): Free array->is_copy_of latter.
 
2003-10-24  Rainer Orth  <ro@TechFak.Uni-Bielefeld.DE>
 
	* Makefile.in (runtime-info.h): Remove -Wp.
 
2003-10-21  Rainer Orth  <ro@TechFak.Uni-Bielefeld.DE>
 
	* Makefile.in (CC1OBJ): Remove.
	(runtime-info.h): Invoke $(CC) so all MULTIFLAGS are handled
	correctly.
	Use .m extension for temporary file.
	Remove assembler temp file.

2003-10-20  Joseph S. Myers  <jsm@polyomino.org.uk>

	* objc/hash.h (hash_string): Don't use a cast as an lvalue.
 
2003-10-17  Rainer Orth  <ro@TechFak.Uni-Bielefeld.DE>

	* Makefile.in (runtime-info.h): Use MULTIFLAGS.

Thu Jul 10 10:27:43 2003  Nicola Pero  <n.pero@mi.flashnet.it>

	libobjc/9969
	* sendmsg.c (get_imp): Fixed rare threading problem.
	(__objc_responds_to): Similar fixes.
	(objc_msg_lookup): Similar fixes.
	(__objc_init_install_dtable): Lock the runtime before checking if the
	table is installed.

Tue May 13 14:56:03 2003  Richard Frith-Macdonald <rfm@gnu.org>
			  Nicola Pero  <n.pero@mi.flashnet.it>

	libobjc/10742
	* init.c (class_superclass_of_class): New function.
	(create_tree_of_subclasses_inherited_from): Use it.
	(__objc_tree_insert_class): Likewise.
	(class_is_subclass_of_class): Likewise.

2003-04-11  David Chad  <davidc@freebsd.org>
	    Loren J. Rittle  <ljrittle@acm.org>

	libobjc/8562
	* objc/hash.h (hash_string): Constify correctly.
	(compare_ptrs): Use direct compare.
	* objc/objc-list.h (list_nth): Rename index to indx to avoid shadow.
	* objc/sarray.h: Global rename index to indx to avoid shadow.
 

diff -ur --exclude=CVS gcc-3.3/libobjc/Makefile.in gcc-3.4/libobjc/Makefile.in
--- gcc-3.3/libobjc/Makefile.in	2003-01-26 12:29:56.000000000 +0100
+++ gcc-3.4/libobjc/Makefile.in	2004-03-02 00:28:01.000000000 +0100
@@ -70,7 +71,7 @@
 WARN_CFLAGS = -W -Wall -Wwrite-strings -Wstrict-prototypes
 GTHREAD_FLAGS=@GTHREAD_FLAGS@
 ALL_CFLAGS = -I. -I$(srcdir) $(CPPFLAGS) $(DEFS) $(CFLAGS) $(WARN_CFLAGS) \
-	$(GTHREAD_FLAGS) -DIN_GCC -DIN_TARGET_LIBS
+	$(GTHREAD_FLAGS) -DIN_GCC -DIN_TARGET_LIBS -fno-strict-aliasing
 
 # Libtool
 # The following strings describe the version of the obj-C library 
@@ -87,14 +88,6 @@
 LIBTOOL_CLEAN   = $(LIBTOOL) --mode=clean
 #LIBTOOL_UNINSTALL = $(LIBTOOL) --mode=uninstall
 
-#
-# Define the cc1obj in terms of the CC that is passed on from higher
-# level make. This is needed to make sure we can create runtime-info.h
-# when doing canadian cross builds where running ../../gcc/cc1obj 
-# does not make any sense.
-#
-CC1OBJ = `$(CC) -print-prog-name=cc1obj`
-
 INCLUDES = -I$(srcdir)/objc  -I$(srcdir)/$(MULTISRCTOP)../gcc \
   -I$(srcdir)/$(MULTISRCTOP)../gcc/config -I$(MULTIBUILDTOP)../../gcc \
   -I$(srcdir)/$(MULTISRCTOP)../include
@@ -160,10 +153,10 @@
 	  $(OBJC_THREAD_FILE)_gc.lo
 
 runtime-info.h: 
-	echo "" > tmp-runtime
+	echo "" > tmp-runtime.m
 	echo "/* This file is automatically generated */" > $@
-	$(CC1OBJ) -print-objc-runtime-info tmp-runtime >> $@
-	rm -f tmp-runtime
+	$(CC) $(MULTIFLAGS) -print-objc-runtime-info -S tmp-runtime.m >> $@
+	rm -f tmp-runtime.m tmp-runtime.s
 
 archive_gc.lo: archive.c
 	$(LIBTOOL_COMPILE) $(CC) -c  -o $@ $(ALL_CFLAGS) $(OBJC_GCFLAGS) \
diff -ur --exclude=CVS gcc-3.3/libobjc/init.c gcc-3.4/libobjc/init.c
--- gcc-3.3/libobjc/init.c	2002-07-02 21:42:27.000000000 +0200
+++ gcc-3.4/libobjc/init.c	2003-05-24 09:47:56.000000000 +0200
@@ -99,6 +99,50 @@
    should not be destroyed during the execution of the program.  */
 static cache_ptr __objc_load_methods = NULL;
 
+/* This function is used when building the class tree used to send
+   ordinately the +load message to all classes needing it.  The tree
+   is really needed so that superclasses will get the message before
+   subclasses.
+
+   This tree will contain classes which are being loaded (or have just
+   being loaded), and whose super_class pointers have not yet been
+   resolved.  This implies that their super_class pointers point to a
+   string with the name of the superclass; when the first message is
+   sent to the class (/an object of that class) the class links will
+   be resolved, which will replace the super_class pointers with
+   pointers to the actual superclasses.
+
+   Unfortunately, the tree might also contain classes which had been
+   loaded previously, and whose class links have already been
+   resolved.
+
+   This function returns the superclass of a class in both cases, and
+   can be used to build the determine the class relationships while
+   building the tree.
+*/
+static Class  class_superclass_of_class (Class class)
+{
+  char *super_class_name;
+
+  /* If the class links have been resolved, use the resolved
+   * links.  */
+  if (CLS_ISRESOLV (class))
+    return class->super_class;
+  
+  /* Else, 'class' has not yet been resolved.  This means that its
+   * super_class pointer is really the name of the super class (rather
+   * than a pointer to the actual superclass).  */
+  super_class_name = (char *)class->super_class;
+
+  /* Return Nil for a root class.  */
+  if (super_class_name == NULL)
+    return Nil;
+
+  /* Lookup the superclass of non-root classes.  */
+  return objc_lookup_class (super_class_name);
+}
+
+
 /* Creates a tree of classes whose topmost class is directly inherited
    from `upper' and the bottom class in this tree is
    `bottom_class'. The classes in this tree are super classes of
@@ -127,9 +171,7 @@
       tree = objc_calloc (1, sizeof (objc_class_tree));
       tree->class = superclass;
       tree->subclasses = list_cons (prev, tree->subclasses);
-      superclass = (superclass->super_class ?
-			objc_lookup_class ((char *) superclass->super_class)
-		      : Nil);
+      superclass = class_superclass_of_class (superclass);
       prev = tree;
     }
 
@@ -157,10 +199,7 @@
       DEBUG_PRINTF ("1. class %s was previously inserted\n", class->name);
       return tree;
     }
-  else if ((class->super_class ?
-		    objc_lookup_class ((char *) class->super_class)
-		  : Nil)
-	    == tree->class)
+  else if (class_superclass_of_class (class) == tree->class)
     {
       /* If class is a direct subclass of tree->class then add class to the
 	 list of subclasses. First check to see if it wasn't already
@@ -370,9 +409,7 @@
     {
       if (class == superclass)
 	return YES;
-      class = (class->super_class ?
-		  objc_lookup_class ((char *) class->super_class)
-		: Nil);
+      class = class_superclass_of_class (class);
     }
 
   return NO;
diff -ur --exclude=CVS gcc-3.3/libobjc/objc/hash.h gcc-3.4/libobjc/objc/hash.h
--- gcc-3.3/libobjc/objc/hash.h	2004-03-02 03:18:17.000000000 +0100
+++ gcc-3.4/libobjc/objc/hash.h	2003-10-20 23:53:26.000000000 +0200
@@ -187,7 +187,7 @@
 static inline int 
 compare_ptrs (const void *k1, const void *k2)
 {
-  return ! (k1 - k2);
+  return (k1 == k2);
 }
 
 
diff -ur --exclude=CVS gcc-3.3/libobjc/objc/objc-list.h gcc-3.4/libobjc/objc/objc-list.h
--- gcc-3.3/libobjc/objc/objc-list.h	2000-03-29 22:19:06.000000000 +0200
+++ gcc-3.4/libobjc/objc/objc-list.h	2003-05-24 09:47:56.000000000 +0200
@@ -64,9 +64,9 @@
    larger than the list length, NULL is returned  */
 
 static inline void*
-list_nth(int index, struct objc_list* list)
+list_nth(int indx, struct objc_list* list)
 {
-  while(index-- != 0)
+  while(indx-- != 0)
     {
       if(list->tail)
 	list = list->tail;
diff -ur --exclude=CVS gcc-3.3/libobjc/objc/sarray.h gcc-3.4/libobjc/objc/sarray.h
--- gcc-3.3/libobjc/objc/sarray.h	1998-10-07 04:21:54.000000000 +0200
+++ gcc-3.4/libobjc/objc/sarray.h	2003-05-24 09:47:56.000000000 +0200
@@ -146,8 +146,8 @@
 void sarray_free(struct sarray*);
 struct sarray* sarray_lazy_copy(struct sarray*);
 void sarray_realloc(struct sarray*, int new_size);
-void sarray_at_put(struct sarray*, sidx index, void* elem);
-void sarray_at_put_safe(struct sarray*, sidx index, void* elem);
+void sarray_at_put(struct sarray*, sidx indx, void* elem);
+void sarray_at_put_safe(struct sarray*, sidx indx, void* elem);
 
 struct sarray* sarray_hard_copy(struct sarray*); /* ... like the name? */
 void sarray_remove_garbage(void);
@@ -156,10 +156,10 @@
 #ifdef PRECOMPUTE_SELECTORS
 /* Transform soffset values to ints and vica verca */
 static inline unsigned int
-soffset_decode(sidx index)
+soffset_decode(sidx indx)
 {
   union sofftype x;
-  x.idx = index;
+  x.idx = indx;
 #ifdef OBJC_SPARSE3
   return x.off.eoffset
     + (x.off.boffset*BUCKET_SIZE)
@@ -186,9 +186,9 @@
 #else /* not PRECOMPUTE_SELECTORS */
 
 static inline size_t
-soffset_decode(sidx index)
+soffset_decode(sidx indx)
 {
-  return index;
+  return indx;
 }
 
 static inline sidx
@@ -198,13 +198,13 @@
 }
 #endif /* not PRECOMPUTE_SELECTORS */
 
-/* Get element from the Sparse array `array' at offset `index' */
+/* Get element from the Sparse array `array' at offset `indx' */
 
-static inline void* sarray_get(struct sarray* array, sidx index)
+static inline void* sarray_get(struct sarray* array, sidx indx)
 {
 #ifdef PRECOMPUTE_SELECTORS
   union sofftype x;
-  x.idx = index;
+  x.idx = indx;
 #ifdef OBJC_SPARSE3
   return 
     array->
@@ -217,19 +217,19 @@
 #else /* not PRECOMPUTE_SELECTORS */
 #ifdef OBJC_SPARSE3
   return array->
-    indices[index/INDEX_CAPACITY]->
-      buckets[(index/BUCKET_SIZE)%INDEX_SIZE]->
-	elems[index%BUCKET_SIZE];
+    indices[indx/INDEX_CAPACITY]->
+      buckets[(indx/BUCKET_SIZE)%INDEX_SIZE]->
+	elems[indx%BUCKET_SIZE];
 #else /* OBJC_SPARSE2 */
-  return array->buckets[index/BUCKET_SIZE]->elems[index%BUCKET_SIZE];
+  return array->buckets[indx/BUCKET_SIZE]->elems[indx%BUCKET_SIZE];
 #endif /* not OBJC_SPARSE3 */
 #endif /* not PRECOMPUTE_SELECTORS */
 }
 
-static inline void* sarray_get_safe(struct sarray* array, sidx index)
+static inline void* sarray_get_safe(struct sarray* array, sidx indx)
 {
-  if(soffset_decode(index) < array->capacity)
-    return sarray_get(array, index);
+  if(soffset_decode(indx) < array->capacity)
+    return sarray_get(array, indx);
   else
     return (array->empty_bucket->elems[0]);
 }
diff -ur --exclude=CVS gcc-3.3/libobjc/sarray.c gcc-3.4/libobjc/sarray.c
--- gcc-3.3/libobjc/sarray.c	2002-07-02 21:42:44.000000000 +0200
+++ gcc-3.4/libobjc/sarray.c	2004-01-10 09:09:36.000000000 +0100
@@ -402,9 +402,6 @@
 #else
   old_buckets = array->buckets;
 #endif
-  
-  if ((array->is_copy_of) && ((array->is_copy_of->ref_count - 1) == 0))
-    sarray_free (array->is_copy_of);
 
   /* Free all entries that do not point to empty_bucket */
   for (counter = 0; counter <= old_max_index; counter++ ) {
@@ -462,6 +459,10 @@
 
 #endif
   
+  /* If this is a copy, go ahead and decrement/deallocate the original */
+  if (array->is_copy_of)
+    sarray_free (array->is_copy_of);
+
   /* free array */
   sarray_free_garbage (array);
 }
diff -ur --exclude=CVS gcc-3.3/libobjc/selector.c gcc-3.4/libobjc/selector.c
--- gcc-3.3/libobjc/selector.c	2002-07-02 21:42:44.000000000 +0200
+++ gcc-3.4/libobjc/selector.c	2004-01-15 17:22:01.000000000 +0100
@@ -148,6 +148,8 @@
       new_list->method_next = class->class_pointer->methods;
       class->class_pointer->methods = new_list;
     }
+  else
+    objc_free(new_list);
 
     __objc_update_dispatch_table_for_class (class->class_pointer);
 }
diff -ur --exclude=CVS gcc-3.3/libobjc/sendmsg.c gcc-3.4/libobjc/sendmsg.c
--- gcc-3.3/libobjc/sendmsg.c	2002-09-12 19:29:58.000000000 +0200
+++ gcc-3.4/libobjc/sendmsg.c	2003-07-10 20:24:56.000000000 +0200
@@ -115,6 +119,14 @@
 IMP
 get_imp (Class class, SEL sel)
 {
+  /* In a vanilla implementation we would first check if the dispatch
+     table is installed.  Here instead, to get more speed in the
+     standard case (that the dispatch table is installed) we first try
+     to get the imp using brute force.  Only if that fails, we do what
+     we should have been doing from the very beginning, that is, check
+     if the dispatch table needs to be installed, install it if it's
+     not installed, and retrieve the imp from the table if it's
+     installed.  */
   void *res = sarray_get_safe (class->dtable, (size_t) sel->sel_id);
   if (res == 0)
     {
@@ -123,7 +135,16 @@
 	{
 	  /* The dispatch table needs to be installed. */
 	  objc_mutex_lock (__objc_runtime_mutex);
-	  __objc_install_dispatch_table_for_class (class);
+
+	   /* Double-checked locking pattern: Check
+	      __objc_uninstalled_dtable again in case another thread
+	      installed the dtable while we were waiting for the lock
+	      to be released.  */
+         if (class->dtable == __objc_uninstalled_dtable)
+           {
+             __objc_install_dispatch_table_for_class (class);
+           }
+
 	  objc_mutex_unlock (__objc_runtime_mutex);
 	  /* Call ourselves with the installed dispatch table
 	     and get the real method */
@@ -131,10 +152,22 @@
 	}
       else
 	{
-	  /* The dispatch table has been installed so the
-	     method just doesn't exist for the class.
-	     Return the forwarding implementation. */
-	  res = __objc_get_forward_imp (sel);
+	  /* The dispatch table has been installed.  */
+
+         /* Get the method from the dispatch table (we try to get it
+	    again in case another thread has installed the dtable just
+	    after we invoked sarray_get_safe, but before we checked
+	    class->dtable == __objc_uninstalled_dtable).
+         */
+	  res = sarray_get_safe (class->dtable, (size_t) sel->sel_id);
+	  if (res == 0)
+	    {
+	      /* The dispatch table has been installed, and the method
+		 is not in the dispatch table.  So the method just
+		 doesn't exist for the class.  Return the forwarding
+		 implementation. */
+	      res = __objc_get_forward_imp (sel);
+	    }
 	}
     }
   return res;
@@ -153,7 +186,10 @@
   if (object->class_pointer->dtable == __objc_uninstalled_dtable)
     {
       objc_mutex_lock (__objc_runtime_mutex);
-      __objc_install_dispatch_table_for_class (object->class_pointer);
+      if (object->class_pointer->dtable == __objc_uninstalled_dtable)
+	{
+	  __objc_install_dispatch_table_for_class (object->class_pointer);
+	}
       objc_mutex_unlock (__objc_runtime_mutex);
     }
 
@@ -188,10 +224,19 @@
 	    }
 	  else
 	    {
-	      /* The dispatch table has been installed so the
-		 method just doesn't exist for the class.
-		 Attempt to forward the method. */
-	      result = __objc_get_forward_imp (op);
+	      /* The dispatch table has been installed.  Check again
+		 if the method exists (just in case the dispatch table
+		 has been installed by another thread after we did the
+		 previous check that the method exists).
+	      */
+	      result = sarray_get_safe (receiver->class_pointer->dtable,
+					(sidx)op->sel_id);
+	      if (result == 0)
+		{
+		  /* If the method still just doesn't exist for the
+		     class, attempt to forward the method. */
+		  result = __objc_get_forward_imp (op);
+		}
 	    }
 	}
       return result;
@@ -235,13 +280,16 @@
 static void
 __objc_init_install_dtable (id receiver, SEL op __attribute__ ((__unused__)))
 {
+  objc_mutex_lock (__objc_runtime_mutex);
+  
   /* This may happen, if the programmer has taken the address of a 
      method before the dtable was initialized... too bad for him! */
   if (receiver->class_pointer->dtable != __objc_uninstalled_dtable)
-    return;
-
-  objc_mutex_lock (__objc_runtime_mutex);
-
+    {
+      objc_mutex_unlock (__objc_runtime_mutex);
+      return;
+    }
+  
   if (CLS_ISCLASS (receiver->class_pointer))
     {
       /* receiver is an ordinary object */
