aboutsummaryrefslogtreecommitdiff
path: root/libobjc/selector.c
diff options
context:
space:
mode:
Diffstat (limited to 'libobjc/selector.c')
-rw-r--r--libobjc/selector.c59
1 files changed, 46 insertions, 13 deletions
diff --git a/libobjc/selector.c b/libobjc/selector.c
index 06743b03ff4..ae16efda400 100644
--- a/libobjc/selector.c
+++ b/libobjc/selector.c
@@ -35,8 +35,6 @@ static struct sarray *__objc_selector_array = 0; /* uid -> sel !T:MUTEX */
static struct sarray *__objc_selector_names = 0; /* uid -> name !T:MUTEX */
static cache_ptr __objc_selector_hash = 0; /* name -> uid !T:MUTEX */
-static void register_selectors_from_list (MethodList_t);
-
/* Number of selectors stored in each of the above tables */
unsigned int __objc_selector_max_index = 0; /* !T:MUTEX */
@@ -60,7 +58,7 @@ __objc_register_selectors_from_class (Class class)
method_list = class->methods;
while (method_list)
{
- register_selectors_from_list (method_list);
+ __objc_register_selectors_from_list (method_list);
method_list = method_list->method_next;
}
}
@@ -70,21 +68,27 @@ __objc_register_selectors_from_class (Class class)
the record table. This is the routine that does the actual recording
work.
- This one is only called for Class objects. For categories,
- class_add_method_list is called.
+ The name and type pointers in the method list must be permanent and
+ immutable.
*/
-static void
-register_selectors_from_list (MethodList_t method_list)
+void
+__objc_register_selectors_from_list (MethodList_t method_list)
{
int i = 0;
+
+ objc_mutex_lock (__objc_runtime_mutex);
while (i < method_list->method_count)
{
Method_t method = &method_list->method_list[i];
- method->method_name
- = sel_register_typed_name ((const char *) method->method_name,
- method->method_types);
+ if (method->method_name)
+ {
+ method->method_name
+ = __sel_register_typed_name ((const char *) method->method_name,
+ method->method_types, 0, YES);
+ }
i += 1;
}
+ objc_mutex_unlock (__objc_runtime_mutex);
}
@@ -320,6 +324,35 @@ const char *sel_get_type (SEL selector)
/* The uninstalled dispatch table */
extern struct sarray *__objc_uninstalled_dtable;
+/* __sel_register_typed_name allocates lots of struct objc_selector:s
+ of 8 (16, if pointers are 64 bits) bytes at startup. To reduce the number
+ of malloc calls and memory lost to malloc overhead, we allocate
+ objc_selector:s in blocks here. This is only called from
+ __sel_register_typed_name, and __sel_register_typed_name may only be
+ called when __objc_runtime_mutex is locked.
+
+ Note that the objc_selector:s allocated from __sel_register_typed_name
+ are never freed.
+
+ 62 because 62 * sizeof (struct objc_selector) = 496 (992). This should
+ let malloc add some overhead and use a nice, round 512 (1024) byte chunk.
+ */
+#define SELECTOR_POOL_SIZE 62
+static struct objc_selector *selector_pool;
+static int selector_pool_left;
+
+static struct objc_selector *
+pool_alloc_selector(void)
+{
+ if (!selector_pool_left)
+ {
+ selector_pool = objc_malloc (sizeof (struct objc_selector)
+ * SELECTOR_POOL_SIZE);
+ selector_pool_left = SELECTOR_POOL_SIZE;
+ }
+ return &selector_pool[--selector_pool_left];
+}
+
/* Store the passed selector name in the selector record and return its
selector value (value returned by sel_get_uid).
Assumes that the calling function has locked down __objc_runtime_mutex. */
@@ -369,7 +402,7 @@ __sel_register_typed_name (const char *name, const char *types,
if (orig)
j = orig;
else
- j = objc_malloc (sizeof (struct objc_selector));
+ j = pool_alloc_selector ();
j->sel_id = (void *) i;
/* Can we use the pointer or must copy types? Don't copy if NULL */
@@ -388,7 +421,7 @@ __sel_register_typed_name (const char *name, const char *types,
if (orig)
j = orig;
else
- j = objc_malloc (sizeof (struct objc_selector));
+ j = pool_alloc_selector ();
j->sel_id = (void *) i;
/* Can we use the pointer or must copy types? Don't copy if NULL */
@@ -446,7 +479,7 @@ SEL
sel_register_typed_name (const char *name, const char *type)
{
SEL ret;
-
+
objc_mutex_lock (__objc_runtime_mutex);
/* Assume that name and type are not constant static memory and need to
be copied before put into a runtime structure. is_const == NO */