(class_add_methods_if_not_there): Only put method implementation in

dtable if the dtable is already installed, otherwise, just add it to
the class's methods list and let
__objc_install_dispatch_table_for_class put it in.  Also, change
arguments.  All callers updated.
(check_class_methods): New function.


git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@284 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
Andrew McCallum 1995-04-05 20:13:39 +00:00
parent 25b5e6b3be
commit dd4444884d
2 changed files with 172 additions and 32 deletions

View file

@ -38,6 +38,11 @@
If you add several behaviors to a class, be aware that the order of
the additions is significant.
McCallum talking to himself:
"Yipes. Be careful with [super ...] calls.
BEHAVIOR methods running in CLASS will now have a different super class.
No; wrong. See objc-api.h; typedef struct objc_super."
*/
#include <objc/objc.h>
@ -56,7 +61,12 @@ static void __objc_class_add_protocols (Class class,
struct objc_protocol_list* protos);
#endif
static BOOL class_is_kind_of(Class self, Class class);
void class_add_methods_if_not_there(Class class, MethodList_t mlist);
static void check_class_methods(Class class);
void class_add_methods_if_not_there(Class class, Class behavior);
/* The uninstalled dispatch table, declared in gcc/objc/sendmsg.c. */
extern struct sarray* __objc_uninstalled_dtable;
/* xxx consider using sendmsg.c:__objc_update_dispatch_table_for_class,
but, I think it will be slower than the current method. */
@ -89,12 +99,21 @@ class_add_behavior (Class class, Class behavior)
#endif
/* Add instance methods */
class_add_methods_if_not_there(class,
behavior->methods);
if (behavior_debug)
{
fprintf(stderr, "Adding instance methods from %s\n",
behavior->name);
}
class_add_methods_if_not_there(class, behavior);
/* Add class methods */
if (behavior_debug)
{
fprintf(stderr, "Adding class methods from %s\n",
behavior->class_pointer->name);
}
class_add_methods_if_not_there(class->class_pointer,
behavior->class_pointer->methods);
behavior->class_pointer);
/* Add behavior's superclass, if not already there. */
{
@ -106,15 +125,16 @@ class_add_behavior (Class class, Class behavior)
}
void
class_add_methods_if_not_there(Class class, MethodList_t mlist)
class_add_methods_if_not_there(Class class, Class behavior)
{
static SEL initialize_sel = 0;
MethodList_t mlist;
if (!initialize_sel)
initialize_sel = sel_register_name ("initialize");
/* Add methods to class->dtable and class->methods */
for ( ; mlist; mlist = mlist->method_next)
for (mlist = behavior->methods; mlist; mlist = mlist->method_next)
{
int counter;
MethodList_t new_list;
@ -125,7 +145,7 @@ class_add_methods_if_not_there(Class class, MethodList_t mlist)
all methods will go in here. */
new_list = (MethodList_t)
(*objc_malloc)
(sizeof(MethodList) + sizeof(struct objc_method[counter]));
(sizeof(MethodList) + sizeof(struct objc_method[counter+1]));
new_list->method_count = 0;
while (counter >= 0)
@ -133,7 +153,7 @@ class_add_methods_if_not_there(Class class, MethodList_t mlist)
Method_t method = &(mlist->method_list[counter]);
if (behavior_debug)
fprintf(stderr, "processing method %s\n",
fprintf(stderr, " processing method [%s]\n",
sel_get_name(method->method_name));
if (!search_for_method_in_list(class->methods, method->method_name)
@ -142,19 +162,38 @@ class_add_methods_if_not_there(Class class, MethodList_t mlist)
/* As long as the method isn't defined in the CLASS,
put the BEHAVIOR method in there. Thus, behavior
methods override the superclasses' methods. */
sarray_at_put_safe (class->dtable,
(sidx) method->method_name->sel_id,
method->method_imp);
/* If dtable is already installed, go ahead and put it in
the dtable sarray, but if it isn't, let
__objc_install_dispatch_table_for_class do it. */
if (class->dtable != __objc_uninstalled_dtable)
{
sarray_at_put_safe (class->dtable,
(sidx) method->method_name->sel_id,
method->method_imp);
if (behavior_debug)
fprintf(stderr, "\tinstalled method\n");
}
else
{
if (behavior_debug)
fprintf(stderr, "\tappended method\n");
}
new_list->method_list[new_list->method_count] = *method;
(new_list->method_count)++;
if (behavior_debug)
fprintf(stderr, "added method %s\n",
sel_get_name(method->method_name));
}
counter -= 1;
}
new_list->method_next = class->methods;
class->methods = new_list;
if (new_list->method_count)
{
new_list->method_next = class->methods;
class->methods = new_list;
}
else
{
OBJC_FREE(new_list);
}
}
}
@ -354,3 +393,34 @@ static BOOL class_is_kind_of(Class self, Class aClassObject)
return YES;
return NO;
}
void
check_class_methods(Class class)
{
int counter;
MethodList_t mlist;
if (class->dtable == __objc_uninstalled_dtable)
return;
for (mlist = class->methods; mlist; mlist = mlist->method_next)
{
counter = mlist->method_count - 1;
while (counter >= 0)
{
Method_t method = &(mlist->method_list[counter]);
IMP imp = sarray_get(class->dtable,
(size_t)method->method_name->sel_id);
assert((imp == method->method_imp));
sarray_at_put_safe (class->dtable,
(sidx) method->method_name->sel_id,
method->method_imp);
counter -= 1;
}
}
if (class->super_class)
check_class_methods(class->super_class);
(void) &check_class_methods; /* to prevent compiler warning about unused */
}

View file

@ -38,6 +38,11 @@
If you add several behaviors to a class, be aware that the order of
the additions is significant.
McCallum talking to himself:
"Yipes. Be careful with [super ...] calls.
BEHAVIOR methods running in CLASS will now have a different super class.
No; wrong. See objc-api.h; typedef struct objc_super."
*/
#include <objc/objc.h>
@ -56,7 +61,12 @@ static void __objc_class_add_protocols (Class class,
struct objc_protocol_list* protos);
#endif
static BOOL class_is_kind_of(Class self, Class class);
void class_add_methods_if_not_there(Class class, MethodList_t mlist);
static void check_class_methods(Class class);
void class_add_methods_if_not_there(Class class, Class behavior);
/* The uninstalled dispatch table, declared in gcc/objc/sendmsg.c. */
extern struct sarray* __objc_uninstalled_dtable;
/* xxx consider using sendmsg.c:__objc_update_dispatch_table_for_class,
but, I think it will be slower than the current method. */
@ -89,12 +99,21 @@ class_add_behavior (Class class, Class behavior)
#endif
/* Add instance methods */
class_add_methods_if_not_there(class,
behavior->methods);
if (behavior_debug)
{
fprintf(stderr, "Adding instance methods from %s\n",
behavior->name);
}
class_add_methods_if_not_there(class, behavior);
/* Add class methods */
if (behavior_debug)
{
fprintf(stderr, "Adding class methods from %s\n",
behavior->class_pointer->name);
}
class_add_methods_if_not_there(class->class_pointer,
behavior->class_pointer->methods);
behavior->class_pointer);
/* Add behavior's superclass, if not already there. */
{
@ -106,15 +125,16 @@ class_add_behavior (Class class, Class behavior)
}
void
class_add_methods_if_not_there(Class class, MethodList_t mlist)
class_add_methods_if_not_there(Class class, Class behavior)
{
static SEL initialize_sel = 0;
MethodList_t mlist;
if (!initialize_sel)
initialize_sel = sel_register_name ("initialize");
/* Add methods to class->dtable and class->methods */
for ( ; mlist; mlist = mlist->method_next)
for (mlist = behavior->methods; mlist; mlist = mlist->method_next)
{
int counter;
MethodList_t new_list;
@ -125,7 +145,7 @@ class_add_methods_if_not_there(Class class, MethodList_t mlist)
all methods will go in here. */
new_list = (MethodList_t)
(*objc_malloc)
(sizeof(MethodList) + sizeof(struct objc_method[counter]));
(sizeof(MethodList) + sizeof(struct objc_method[counter+1]));
new_list->method_count = 0;
while (counter >= 0)
@ -133,7 +153,7 @@ class_add_methods_if_not_there(Class class, MethodList_t mlist)
Method_t method = &(mlist->method_list[counter]);
if (behavior_debug)
fprintf(stderr, "processing method %s\n",
fprintf(stderr, " processing method [%s]\n",
sel_get_name(method->method_name));
if (!search_for_method_in_list(class->methods, method->method_name)
@ -142,19 +162,38 @@ class_add_methods_if_not_there(Class class, MethodList_t mlist)
/* As long as the method isn't defined in the CLASS,
put the BEHAVIOR method in there. Thus, behavior
methods override the superclasses' methods. */
sarray_at_put_safe (class->dtable,
(sidx) method->method_name->sel_id,
method->method_imp);
/* If dtable is already installed, go ahead and put it in
the dtable sarray, but if it isn't, let
__objc_install_dispatch_table_for_class do it. */
if (class->dtable != __objc_uninstalled_dtable)
{
sarray_at_put_safe (class->dtable,
(sidx) method->method_name->sel_id,
method->method_imp);
if (behavior_debug)
fprintf(stderr, "\tinstalled method\n");
}
else
{
if (behavior_debug)
fprintf(stderr, "\tappended method\n");
}
new_list->method_list[new_list->method_count] = *method;
(new_list->method_count)++;
if (behavior_debug)
fprintf(stderr, "added method %s\n",
sel_get_name(method->method_name));
}
counter -= 1;
}
new_list->method_next = class->methods;
class->methods = new_list;
if (new_list->method_count)
{
new_list->method_next = class->methods;
class->methods = new_list;
}
else
{
OBJC_FREE(new_list);
}
}
}
@ -354,3 +393,34 @@ static BOOL class_is_kind_of(Class self, Class aClassObject)
return YES;
return NO;
}
void
check_class_methods(Class class)
{
int counter;
MethodList_t mlist;
if (class->dtable == __objc_uninstalled_dtable)
return;
for (mlist = class->methods; mlist; mlist = mlist->method_next)
{
counter = mlist->method_count - 1;
while (counter >= 0)
{
Method_t method = &(mlist->method_list[counter]);
IMP imp = sarray_get(class->dtable,
(size_t)method->method_name->sel_id);
assert((imp == method->method_imp));
sarray_at_put_safe (class->dtable,
(sidx) method->method_name->sel_id,
method->method_imp);
counter -= 1;
}
}
if (class->super_class)
check_class_methods(class->super_class);
(void) &check_class_methods; /* to prevent compiler warning about unused */
}