From c75534d1e6e8b62ea4dabf58c2deff1ac09796a7 Mon Sep 17 00:00:00 2001
From: Nicola Pero <nicola.pero@meta-innovation.com>
Date: Tue, 21 Dec 2010 13:44:04 +0000
Subject: [PATCH] In libobjc/: 2010-12-21 Nicola Pero
 <nicola.pero@meta-innovation.com>

In libobjc/:
2010-12-21  Nicola Pero  <nicola.pero@meta-innovation.com>

	PR libobjc/45953
	* selector.c (__sel_register_typed_name): When registering a new
	selector with the same name as an existing one, reuse the existing
	name string.  Also updated types, casts and comments in the whole
	function.

In gcc/testsuite/:
2010-12-21  Nicola Pero  <nicola.pero@meta-innovation.com>

	PR libobjc/45953
	* objc.dg/libobjc-selector-1.m: New test.

From-SVN: r168115
---
 gcc/testsuite/ChangeLog                    |  5 ++
 gcc/testsuite/objc.dg/libobjc-selector-1.m | 39 +++++++++
 libobjc/ChangeLog                          |  8 ++
 libobjc/selector.c                         | 96 +++++++++++++---------
 4 files changed, 108 insertions(+), 40 deletions(-)
 create mode 100644 gcc/testsuite/objc.dg/libobjc-selector-1.m

diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 7b97962ddfe3..50cfa32e38c4 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2010-12-21  Nicola Pero  <nicola.pero@meta-innovation.com>
+
+	PR libobjc/45953
+	* objc.dg/libobjc-selector-1.m: New test.
+
 2010-12-21  Jakub Jelinek  <jakub@redhat.com>
 
 	PR middle-end/45852
diff --git a/gcc/testsuite/objc.dg/libobjc-selector-1.m b/gcc/testsuite/objc.dg/libobjc-selector-1.m
new file mode 100644
index 000000000000..49947d7b8722
--- /dev/null
+++ b/gcc/testsuite/objc.dg/libobjc-selector-1.m
@@ -0,0 +1,39 @@
+/* Test a little inefficiency that was fixed in libobjc when dealing
+   with selectors (PR libobjc/45953).  */
+
+/* { dg-do run } */
+/* { dg-skip-if "" { *-*-* } { "-fnext-runtime" } { "" } } */
+
+/* To get the modern GNU Objective-C Runtime API, you include
+   objc/runtime.h.  */
+#include <objc/runtime.h>
+#include <stdlib.h>
+
+/* Test that registering a new selector, with the same name but a
+   different type than the previous one, does not change the original
+   name string.  It is actually fine to change it (there is no
+   guarantee that it won't change), except for runtime performance /
+   memory consumption, since changing it means that the runtime is
+   doing an unneeded objc_malloc()/strcpy(), which is inefficient.  */
+
+int main (void)
+{
+  SEL selector_1;
+  SEL selector_2;
+  const char *name_1;
+  const char *name_2;
+
+  /* These method type strings may well be invalid.  Please don't use
+     them as examples.  They are irrelevant for this test; any string
+     will do.  */
+  selector_1 = sel_registerTypedName ("method", "v@:");
+  name_1 = sel_getName (selector_1);
+
+  selector_2 = sel_registerTypedName ("method", "i@:");
+  name_2 = sel_getName (selector_1);
+
+  if (name_1 != name_2)
+    abort ();
+
+  return 0;
+}
diff --git a/libobjc/ChangeLog b/libobjc/ChangeLog
index 6935ac79213d..83387eef6796 100644
--- a/libobjc/ChangeLog
+++ b/libobjc/ChangeLog
@@ -1,3 +1,11 @@
+2010-12-21  Nicola Pero  <nicola.pero@meta-innovation.com>
+
+	PR libobjc/45953
+	* selector.c (__sel_register_typed_name): When registering a new
+	selector with the same name as an existing one, reuse the existing
+	name string.  Also updated types, casts and comments in the whole
+	function.
+
 2010-12-21  Nicola Pero  <nicola.pero@meta-innovation.com>
 
 	* objc-private/module-abi-8.h (struct objc_symtab): Declare 'refs'
diff --git a/libobjc/selector.c b/libobjc/selector.c
index 699e52ee966e..4fd213ba9196 100644
--- a/libobjc/selector.c
+++ b/libobjc/selector.c
@@ -451,17 +451,19 @@ __sel_register_typed_name (const char *name, const char *types,
   i = (sidx) objc_hash_value_for_key (__objc_selector_hash, name);
   if (soffset_decode (i) != 0)
     {
-      for (l = (struct objc_list *) sarray_get_safe (__objc_selector_array, i);
+      /* There are already selectors with that name.  Examine them to
+	 see if the one we're registering already exists.  */
+      for (l = (struct objc_list *)sarray_get_safe (__objc_selector_array, i);
 	   l; l = l->tail)
 	{
-	  SEL s = (SEL) l->head;
+	  SEL s = (SEL)l->head;
 	  if (types == 0 || s->sel_types == 0)
 	    {
 	      if (s->sel_types == types)
 		{
 		  if (orig)
 		    {
-		      orig->sel_id = (void *) i;
+		      orig->sel_id = (void *)i;
 		      return orig;
 		    }
 		  else
@@ -472,79 +474,93 @@ __sel_register_typed_name (const char *name, const char *types,
 	    {
 	      if (orig)
 		{
-		  orig->sel_id = (void *) i;
+		  orig->sel_id = (void *)i;
 		  return orig;
 		}
 	      else
 		return s;
 	    }
 	}
+      /* A selector with this specific name/type combination does not
+	 exist yet.  We need to register it.  */
       if (orig)
 	j = orig;
       else
 	j = pool_alloc_selector ();
       
-      j->sel_id = (void *) i;
-      /* Can we use the pointer or must copy types?  Don't copy if
+      j->sel_id = (void *)i;
+      /* Can we use the pointer or must we copy types ?  Don't copy if
 	 NULL.  */
       if ((is_const) || (types == 0))
-	j->sel_types = (const char *) types;
+	j->sel_types = types;
       else
 	{
-	  j->sel_types = (char *) objc_malloc (strlen (types) + 1);
-	  strcpy ((char *) j->sel_types, types);
+	  j->sel_types = (char *)objc_malloc (strlen (types) + 1);
+	  strcpy ((char *)j->sel_types, types);
 	}
-      l = (struct objc_list *) sarray_get_safe (__objc_selector_array, i);
+      l = (struct objc_list *)sarray_get_safe (__objc_selector_array, i);
     }
   else
     {
+      /* There are no other selectors with this name registered in the
+	 runtime tables.  */
+      const char *new_name;
+
+      /* Determine i.  */
       __objc_selector_max_index += 1;
       i = soffset_encode (__objc_selector_max_index);
+
+      /* Prepare the selector.  */
       if (orig)
 	j = orig;
       else
 	j = pool_alloc_selector ();
       
-      j->sel_id = (void *) i;
-      /* Can we use the pointer or must copy types?  Don't copy if
+      j->sel_id = (void *)i;
+      /* Can we use the pointer or must we copy types ?  Don't copy if
 	 NULL.  */
-      if ((is_const) || (types == 0))
-	j->sel_types = (const char *) types;
+      if (is_const || (types == 0))
+	j->sel_types = types;
+      else
+	{
+	  j->sel_types = (char *)objc_malloc (strlen (types) + 1);
+	  strcpy ((char *)j->sel_types, types);
+	}
+
+      /* Since this is the first selector with this name, we need to
+	 register the correspondence between 'i' (the sel_id) and
+	 'name' (the actual string) in __objc_selector_names and
+	 __objc_selector_hash.  */
+      
+      /* Can we use the pointer or must we copy name ?  Don't copy if
+	 NULL.  (FIXME: Can the name really be NULL here ?)  */
+      if (is_const || (name == 0))
+	new_name = name;
       else
 	{
-	  j->sel_types = (char *) objc_malloc (strlen (types) + 1);
-	  strcpy ((char *) j->sel_types, types);
+	  new_name = (char *)objc_malloc (strlen (name) + 1);
+	  strcpy ((char *)new_name, name);
 	}
+      
+      /* This maps the sel_id to the name.  */
+      sarray_at_put_safe (__objc_selector_names, i, (void *)new_name);
+
+      /* This maps the name to the sel_id.  */
+      objc_hash_add (&__objc_selector_hash, (void *)new_name, (void *)i);
+
       l = 0;
     }
 
   DEBUG_PRINTF ("Record selector %s[%s] as: %ld\n", name, types, 
-		(long) soffset_decode (i));
-  
-  {
-    int is_new = (l == 0);
-    const char *new_name;
-
-    /* Can we use the pointer or must copy name?  Don't copy if
-       NULL.  */
-    if ((is_const) || (name == 0))
-      new_name = name;
-    else
-      {
-	new_name = (char *) objc_malloc (strlen (name) + 1);
-	strcpy ((char *) new_name, name);
-      }
-    
-    l = list_cons ((void *) j, l);
-    sarray_at_put_safe (__objc_selector_names, i, (void *) new_name);
-    sarray_at_put_safe (__objc_selector_array, i, (void *) l);
-    if (is_new)
-      objc_hash_add (&__objc_selector_hash, (void *) new_name, (void *) i);
-  }
-  
+		(long)soffset_decode (i));
+
+  /* Now add the selector to the list of selectors with that id.  */
+  l = list_cons ((void *)j, l);
+  sarray_at_put_safe (__objc_selector_array, i, (void *)l);
+
   sarray_realloc (__objc_uninstalled_dtable, __objc_selector_max_index + 1);
   
-  return (SEL) j;
+  return (SEL)j;
 }
 
 SEL
-- 
GitLab