Rewrote class resolving code. Now it only resolves classes that actually need resolving, rather than iterating over the entire class table.

(This is part 1.  Part 2 will lazily resolve classes.)
This commit is contained in:
theraven 2010-03-12 22:47:10 +00:00
parent bfbd52709b
commit 8ce32fd1c9
3 changed files with 98 additions and 100 deletions

View File

@ -12,6 +12,7 @@ static struct objc_class _NSBlock;
static struct objc_class _NSBlockMeta;
void __objc_update_dispatch_table_for_class(Class);
void __objc_add_class_to_hash(Class);
extern struct sarray *__objc_uninstalled_dtable;
extern objc_mutex_t __objc_runtime_mutex;
@ -19,32 +20,20 @@ static void createNSBlockSubclass(Class superclass, Class newClass,
Class metaClass, char *name)
{
// Initialize the metaclass
metaClass->class_pointer = superclass->class_pointer;
metaClass->super_class = superclass->class_pointer;
//metaClass->class_pointer = superclass->class_pointer;
//metaClass->super_class = superclass->class_pointer;
metaClass->info = _CLS_META;
metaClass->dtable = __objc_uninstalled_dtable;
// Set up the new class
newClass->class_pointer = metaClass;
newClass->super_class = superclass;
newClass->super_class = superclass->name;
newClass->name = name;
newClass->info = _CLS_CLASS;
newClass->dtable = __objc_uninstalled_dtable;
// Initialize the dispatch table for the class and metaclass.
__objc_update_dispatch_table_for_class(metaClass);
__objc_update_dispatch_table_for_class(newClass);
CLS_SETINITIALIZED(metaClass);
CLS_SETINITIALIZED(newClass);
CLS_SETRESOLV(metaClass);
CLS_SETRESOLV(newClass);
// Add pointer from super class
objc_mutex_lock(__objc_runtime_mutex);
newClass->sibling_class = newClass->super_class->subclass_list;
newClass->super_class->subclass_list = newClass;
metaClass->sibling_class = metaClass->super_class->subclass_list;
metaClass->super_class->subclass_list = metaClass;
objc_mutex_unlock(__objc_runtime_mutex);
__objc_add_class_to_hash(newClass);
}
#define NEW_CLASS(super, sub) \

81
class.c
View File

@ -224,87 +224,6 @@ objc_next_class (void **enum_state)
return class;
}
/* Resolve super/subclass links for all classes. The only thing we
can be sure of is that the class_pointer for class objects point to
the right meta class objects. */
void
__objc_resolve_class_links (void)
{
void *es = NULL;
Class object_class = objc_get_class (ROOT_OBJECT_CLASS_NAME);
Class class1;
assert (object_class);
LOCK(__objc_runtime_mutex);
/* Assign subclass links. */
while ((class1 = class_table_next (&es)))
{
/* Make sure we have what we think we have. */
assert (CLS_ISCLASS (class1));
assert (CLS_ISMETA (class1->class_pointer));
/* The class_pointer of all meta classes point to Object's meta
class. */
class1->class_pointer->class_pointer = object_class->class_pointer;
if (! CLS_ISRESOLV (class1))
{
CLS_SETRESOLV (class1);
CLS_SETRESOLV (class1->class_pointer);
if (class1->super_class)
{
Class a_super_class
= objc_get_class ((char *) class1->super_class);
assert (a_super_class);
DEBUG_PRINTF ("making class connections for: %s\n",
class1->name);
/* Assign subclass links for superclass. */
class1->sibling_class = a_super_class->subclass_list;
a_super_class->subclass_list = class1;
/* Assign subclass links for meta class of superclass. */
if (a_super_class->class_pointer)
{
class1->class_pointer->sibling_class
= a_super_class->class_pointer->subclass_list;
a_super_class->class_pointer->subclass_list
= class1->class_pointer;
}
}
else /* A root class, make its meta object be a subclass of
Object. */
{
class1->class_pointer->sibling_class
= object_class->subclass_list;
object_class->subclass_list = class1->class_pointer;
}
}
}
/* Assign superclass links. */
es = NULL;
while ((class1 = class_table_next (&es)))
{
Class sub_class;
for (sub_class = class1->subclass_list; sub_class;
sub_class = sub_class->sibling_class)
{
sub_class->super_class = class1;
if (CLS_ISCLASS (sub_class))
sub_class->class_pointer->super_class = class1->class_pointer;
}
}
UNLOCK(__objc_runtime_mutex);
}
Class
class_pose_as (Class impostor, Class super_class)
{

View File

@ -1,6 +1,8 @@
#include "magic_objects.h"
#include "objc/objc-api.h"
#include "lock.h"
#include <stdlib.h>
#include <assert.h>
// Get the functions for string hashing
#include "string_hash.h"
@ -26,8 +28,25 @@ static int class_hash(const Class class)
static class_table_internal_table *class_table;
#define unresolved_class_next subclass_list
#define unresolved_class_prev sibling_class
/**
* Linked list using the subclass_list pointer in unresolved classes.
*/
static Class unresolved_class_list;
void class_table_insert(Class class)
{
if (!CLS_ISRESOLV(class))
{
if (Nil != unresolved_class_list)
{
unresolved_class_list->unresolved_class_prev = class;
}
class->unresolved_class_next = unresolved_class_list;
unresolved_class_list = class;
}
class_table_internal_insert(class_table, class);
}
@ -36,8 +55,7 @@ Class class_table_get_safe(const char *class_name)
return class_table_internal_table_get(class_table, class_name);
}
Class
class_table_next (void **e)
Class class_table_next(void **e)
{
return class_table_internal_next(class_table,
(struct class_table_internal_table_enumerator**)e);
@ -47,3 +65,75 @@ void __objc_init_class_tables(void)
{
class_table = class_table_internal_create(16);
}
static void objc_resolve_class(Class cls)
{
// Skip this if the class is already resolved.
if (CLS_ISRESOLV(cls)) { return; }
// Remove the class from the unresolved class list
if (Nil == cls->unresolved_class_prev)
{
unresolved_class_list = cls->unresolved_class_next;
}
else
{
cls->unresolved_class_prev->unresolved_class_next =
cls->unresolved_class_next;
}
if (Nil != cls->unresolved_class_next)
{
cls->unresolved_class_next->unresolved_class_prev =
cls->unresolved_class_prev;
}
cls->unresolved_class_prev = Nil;
cls->unresolved_class_next = Nil;
static Class root_class = Nil;
if (Nil == root_class)
{
root_class = objc_get_class(ROOT_OBJECT_CLASS_NAME);
if (!CLS_ISRESOLV(root_class))
{
objc_resolve_class(root_class);
}
assert(root_class);
}
// Resolve the superclass pointer
// If this class has no superclass, use [NS]Object
Class super = root_class;
Class superMeta = root_class;
if (NULL != cls->super_class)
{
// Resolve the superclass if it isn't already resolved
super = objc_get_class((char*)cls->super_class);
if (!CLS_ISRESOLV(super))
{
objc_resolve_class(super);
}
superMeta = super->class_pointer;
// Set the superclass pointer for the class and the superclass
cls->super_class = super;
cls->class_pointer->super_class = super->class_pointer;
}
// Set up the class links
cls->sibling_class = super->subclass_list;
super->subclass_list = cls;
// Set up the metaclass links
cls->class_pointer->sibling_class = superMeta->subclass_list;
superMeta->subclass_list = cls->class_pointer;
// Mark this class (and its metaclass) as resolved
CLS_SETRESOLV(cls);
CLS_SETRESOLV(cls->class_pointer);
}
void __objc_resolve_class_links(void)
{
LOCK(__objc_runtime_mutex);
Class class;
while ((class = unresolved_class_list))
{
objc_resolve_class(class);
}
}