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