Commit 7084b319 by Richard Kenner

(class_add_method_list): Check for the +load method when adding a methods list to a class.

(class_add_method_list): Check for the +load method when adding a
methods list to a class.
(__objc_install_methods_in_dtable): New function.
(class_add_method_list): Don't check anymore for duplicate methods.

From-SVN: r13711
parent e29e9570
...@@ -263,7 +263,8 @@ static void __objc_send_initialize(Class class) ...@@ -263,7 +263,8 @@ static void __objc_send_initialize(Class class)
for (i=0;i<method_list->method_count;i++) { for (i=0;i<method_list->method_count;i++) {
method = &(method_list->method_list[i]); method = &(method_list->method_list[i]);
if (method->method_name->sel_id == op->sel_id) { if (method->method_name
&& method->method_name->sel_id == op->sel_id) {
imp = method->method_imp; imp = method->method_imp;
break; break;
} }
...@@ -280,14 +281,39 @@ static void __objc_send_initialize(Class class) ...@@ -280,14 +281,39 @@ static void __objc_send_initialize(Class class)
} }
} }
} }
/* Walk on the methods list of class and install the methods in the reverse
order of the lists. Since methods added by categories are before the methods
of class in the methods list, this allows categories to substitute methods
declared in class. However if more than one category replace the same method
nothing is guarranteed about what method will be used.
Assumes that __objc_runtime_mutex is locked down. */
static void
__objc_install_methods_in_dtable (Class class, MethodList_t method_list)
{
int i;
if (!method_list)
return;
if (method_list->method_next)
__objc_install_methods_in_dtable (class, method_list->method_next);
for (i = 0; i < method_list->method_count; i++)
{
Method_t method = &(method_list->method_list[i]);
sarray_at_put_safe (class->dtable,
(sidx) method->method_name->sel_id,
method->method_imp);
}
}
/* Assumes that __objc_runtime_mutex is locked down. */ /* Assumes that __objc_runtime_mutex is locked down. */
static void static void
__objc_install_dispatch_table_for_class (Class class) __objc_install_dispatch_table_for_class (Class class)
{ {
Class super; Class super;
MethodList_t mlist;
int counter; int counter;
/* If the class has not yet had it's class links resolved, we must /* If the class has not yet had it's class links resolved, we must
...@@ -310,18 +336,7 @@ __objc_install_dispatch_table_for_class (Class class) ...@@ -310,18 +336,7 @@ __objc_install_dispatch_table_for_class (Class class)
else else
class->dtable = sarray_lazy_copy (super->dtable); class->dtable = sarray_lazy_copy (super->dtable);
for (mlist = class->methods; mlist; mlist = mlist->method_next) __objc_install_methods_in_dtable (class, class->methods);
{
counter = mlist->method_count - 1;
while (counter >= 0)
{
Method_t method = &(mlist->method_list[counter]);
sarray_at_put_safe (class->dtable,
(sidx) method->method_name->sel_id,
method->method_imp);
counter -= 1;
}
}
} }
void __objc_update_dispatch_table_for_class (Class class) void __objc_update_dispatch_table_for_class (Class class)
...@@ -361,10 +376,6 @@ void ...@@ -361,10 +376,6 @@ void
class_add_method_list (Class class, MethodList_t list) class_add_method_list (Class class, MethodList_t list)
{ {
int i; int i;
static SEL initialize_sel = 0; /* !T:SAFE2 */
if (!initialize_sel)
initialize_sel = sel_register_name ("initialize");
/* Passing of a linked list is not allowed. Do multiple calls. */ /* Passing of a linked list is not allowed. Do multiple calls. */
assert (!list->method_next); assert (!list->method_next);
...@@ -380,24 +391,16 @@ class_add_method_list (Class class, MethodList_t list) ...@@ -380,24 +391,16 @@ class_add_method_list (Class class, MethodList_t list)
method->method_name = method->method_name =
sel_register_typed_name ((const char*)method->method_name, sel_register_typed_name ((const char*)method->method_name,
method->method_types); method->method_types);
if (search_for_method_in_list (class->methods, method->method_name)
&& method->method_name->sel_id != initialize_sel->sel_id)
{
/* Duplication. Print a error message an change the method name
to NULL. */
fprintf (stderr, "attempt to add a existing method: %s\n",
sel_get_name(method->method_name));
method->method_name = 0;
}
} }
} }
/* Add the methods to the class's method list. */ /* Add the methods to the class's method list. */
list->method_next = class->methods; list->method_next = class->methods;
class->methods = list; class->methods = list;
}
/* Update the dispatch table of class */
__objc_update_dispatch_table_for_class (class);
}
Method_t Method_t
class_get_instance_method(Class class, SEL op) class_get_instance_method(Class class, SEL op)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment