--- gcc/objc/class.c 2018/04/24 18:10:15 1.1.1.1 +++ gcc/objc/class.c 2018/04/24 18:20:10 1.1.1.3 @@ -25,7 +25,7 @@ You should have received a copy of the G covered by the GNU General Public License. */ #include "runtime.h" /* the kitchen sink */ - +#include "sarray.h" /* The table of classname->class. Used for objc_lookup_class and friends */ static cache_ptr __objc_class_hash = 0; @@ -132,6 +132,33 @@ objc_get_class (const char *name) abort(); } +MetaClass* +objc_get_meta_class(const char *name) +{ + return objc_get_class(name)->class_pointer; +} + +/* This function provides a way to enumerate all the classes in the + executable. Pass *ENUM_STATE == NULL to start the enumeration. The + function will return 0 when there are no more classes. + For example: + id class; + void *es = NULL; + while ((class = objc_next_class(&es))) + ... do something with class; +*/ +Class* +objc_next_class(void **enum_state) +{ + /* make sure the table is there */ + assert(__objc_class_hash); + + *(node_ptr*)enum_state = + hash_next(__objc_class_hash, *(node_ptr*)enum_state); + if (*(node_ptr*)enum_state) + return (*(node_ptr*)enum_state)->value; + return (Class*)0; +} /* Resolve super/subclass links for all classes. The only thing we can be sure of is that the class_pointer for class objects point @@ -211,140 +238,91 @@ void __objc_resolve_class_links() } -/* This is a incomplete implementation of posing. This function does the - bulk of the work but does not initialize the class method caches. That is - a run-time specific operation. - -I implement posing by hiding SUPER_CLASS, creating new class and meta class - structures, initializing it with IMPOSTOR, and changing it such that it is - identified as SUPER_CLASS. SUPER_CLASS remains in the hierarchy but is - inaccessible by the means. The class hierarchy is then re arranged such - that all of the subclasses of SUPER_CLASS now inherit from the new class - structures -- except the impostor itself. The only dramatic effect on the - application is that subclasses of SUPER_CLASS cannot do a [ .... - super_class ] and expect their real super class. */ + +#define CLASSOF(c) ((c)->class_pointer) + Class* class_pose_as (Class* impostor, Class* super_class) { - Class* new_class = (Class*) __objc_xcalloc (1, sizeof (Class)); - MetaClass* new_meta_class = - (MetaClass*) __objc_xmalloc(sizeof (MetaClass)); - char *new_name = (char *)__objc_xmalloc ((size_t)strlen ((char*)super_class->name) + 12); - - /* We must know the state of the hierachy. Do initial setup if needed */ - if(!CLS_ISRESOLV(impostor)) - __objc_resolve_class_links(); - - assert (new_class); - assert (new_meta_class); - assert (new_name); + node_ptr node; + Class* class1; - assert (CLS_ISCLASS(impostor)); - assert (CLS_ISCLASS(super_class)); + if (!CLS_ISRESOLV (impostor)) + __objc_resolve_class_links (); + /* preconditions */ + assert (impostor); + assert (super_class); + assert (impostor->super_class == super_class); + assert (CLS_ISCLASS (impostor)); + assert (CLS_ISCLASS (super_class)); assert (impostor->instance_size == super_class->instance_size); - /* Create the impostor class. */ - new_class->class_pointer = new_meta_class; - new_class->super_class = super_class; - new_class->name = super_class->name; - new_class->version = super_class->version; - new_class->info = super_class->info; - new_class->instance_size = super_class->instance_size; - new_class->ivars = super_class->ivars; - new_class->methods = impostor->methods; - new_class->dtable = impostor->dtable; - - /* Create the impostor meta class. */ - new_meta_class->class_pointer = super_class->class_pointer->class_pointer; - new_meta_class->super_class = super_class->class_pointer->super_class; - new_meta_class->name = super_class->class_pointer->name; - new_meta_class->version = super_class->class_pointer->version; - new_meta_class->info = super_class->class_pointer->info; - new_meta_class->instance_size = super_class->class_pointer->instance_size; - new_meta_class->ivars = super_class->class_pointer->ivars; - new_meta_class->methods = impostor->class_pointer->methods; - new_meta_class->dtable = impostor->class_pointer->dtable; - - /* Now change super/subclass links of all related classes. This is rather - complex, since we have both super_class link, and subclass_list for the - involved classes. */ { - Class* *classpp; - MetaClass* *metaclasspp; + Class **subclass = &(super_class->subclass_list); - /* Remove impostor from subclass list of super_class */ - for (classpp = &(super_class->subclass_list); - *classpp; - classpp = &((*classpp)->sibling_class)) + /* move subclasses of super_class to impostor */ + while (*subclass) { - if (*classpp == impostor) - *classpp = (*classpp)->sibling_class; - if (*classpp == 0) - break; - } + Class *nextSub = (*subclass)->sibling_class; - /* Do the same for the meta classes */ + if (*subclass != impostor) + { + Class *sub = *subclass; + + /* classes */ + sub->sibling_class = impostor->subclass_list; + sub->super_class = impostor; + impostor->subclass_list = sub; + + /* It will happen that SUB is not a class object if it is + the top of the meta class hierachy chain. (root + meta-class objects inherit theit class object) If that is + the case... dont mess with the meta-meta class. */ + if (CLS_ISCLASS (sub)) + { + /* meta classes */ + CLASSOF (sub)->sibling_class = CLASSOF (impostor)->subclass_list; + CLASSOF (sub)->super_class = CLASSOF (impostor); + CLASSOF (impostor)->subclass_list = CLASSOF (sub); + } + } - for (metaclasspp = &(super_class->class_pointer->subclass_list); - *metaclasspp; - metaclasspp = &((*metaclasspp)->sibling_class)) - { - if (*metaclasspp == impostor->class_pointer) - *metaclasspp = (*metaclasspp)->sibling_class; - if (*metaclasspp == 0) - break; + *subclass = nextSub; } - /* From the loop above, classpp now points to the sibling_class entry */ - /* of the last element in the list of subclasses for super_class */ - - /* Append the subclass list of impostor to the subclass list of */ - /* superclass, and excange those two and set subclass of */ - /* super_class to be impostor only */ - - *classpp = impostor->subclass_list; - new_class->subclass_list = super_class->subclass_list; - super_class->subclass_list = new_class; - new_class->sibling_class = 0; - - /* Do the same thing for the meta classes */ - *metaclasspp = impostor->class_pointer->subclass_list; - new_meta_class->subclass_list = super_class->class_pointer->subclass_list; - super_class->class_pointer->subclass_list = new_meta_class; - new_meta_class->sibling_class = 0; - - /* Update superclass links for all subclasses of new_class */ - for (classpp = &(new_class->subclass_list); *classpp; - classpp = &((*classpp)->sibling_class)) - (*classpp)->super_class = new_class; - - for (metaclasspp = &(new_meta_class->subclass_list); *metaclasspp; - metaclasspp = &((*metaclasspp)->sibling_class)) - (*metaclasspp)->super_class = new_meta_class; - + /* set subclasses of superclass to be impostor only */ + super_class->subclass_list = impostor; + CLASSOF (super_class)->subclass_list = CLASSOF (impostor); + + /* set impostor to have no sibling classes */ + impostor->sibling_class = 0; + CLASSOF (impostor)->sibling_class = 0; } - - /* Delete the class from the hash table, change its name so that it can no - longer be found, then place it back into the hash table using its new - name. - Don't worry about the class number. It is already assigned. - memory is lost with the hash key.) */ - hash_remove (__objc_class_hash, super_class->name); - sprintf (new_name, "%s*", super_class->name); - super_class->name = new_name; - super_class->class_pointer->name = new_name; - hash_add (&__objc_class_hash, super_class->name, super_class); - - /* Place the impostor class in class hash table and assign it a class - number. */ - __objc_add_class_to_hash (new_class); - - /* Now update dispatch tables for new_class and it's subclasses */ - __objc_update_dispatch_table_for_class ((Class*) new_meta_class); - __objc_update_dispatch_table_for_class (new_class); + /* check relationship of impostor and super_class is kept. */ + assert (impostor->super_class == super_class); + assert (CLASSOF (impostor)->super_class == CLASSOF (super_class)); + + /* This is how to update the lookup table. Regardless of + what the keys of the hashtable is, change all values that are + suprecalss into impostor. */ - return new_class; + for (node = hash_next (__objc_class_hash, NULL); node; + node = hash_next (__objc_class_hash, node)) + { + class1 = (Class*)node->value; + if (class1 == super_class) + { + node->value = impostor; /* change hash table value */ + } + } + + /* next, we update the dispatch tables... */ + __objc_update_dispatch_table_for_class (CLASSOF (impostor)); + __objc_update_dispatch_table_for_class (impostor); + + return impostor; } +