Rewrote some of the class table code to be slightly cleaner.

main
theraven 16 years ago
parent 3672f04ea3
commit 7f6f798074

@ -24,20 +24,25 @@ libobjc_C_FILES = \
encoding.c\
hash_table.c\
exception.c\
gc.c\
hash.c\
hooks.c\
ivar.c\
init.c\
misc.c\
nil_method.c\
objects.c\
protocol.c\
runtime.c\
sarray2.c\
selector.c\
selector_table.c\
sendmsg.c\
sendmsg.c
ifneq ($(enable_legacy), no)
libobjc_C_FILES += \
gc.c\
objects.c\
thr.c
endif
libobjc_HEADER_FILES_DIR = objc
libobjc_HEADER_FILES_INSTALL_DIR = objc

@ -118,11 +118,6 @@ Class class_table_next (void **e);
** Objective-C runtime functions
**/
/* This is a hook which is called by objc_get_class and
objc_lookup_class if the runtime is not able to find the class.
This may e.g. try to load in the class using dynamic loading. */
Class (*_objc_lookup_class) (const char *name) = 0; /* !T:SAFE */
Class class_table_get_safe(const char*);
/* This function adds a class to the class hash table, and assigns the
@ -154,79 +149,3 @@ __objc_add_class_to_hash (Class class)
UNLOCK(__objc_runtime_mutex);
}
/* Get the class object for the class named NAME. If NAME does not
identify a known class, the hook _objc_lookup_class is called. If
this fails, nil is returned. */
Class
objc_lookup_class (const char *name)
{
Class class;
class = class_table_get_safe (name);
if (class)
return class;
if (_objc_lookup_class)
return (*_objc_lookup_class) (name);
else
return 0;
}
/* Get the class object for the class named NAME. If NAME does not
identify a known class, the hook _objc_lookup_class is called. If
this fails, an error message is issued and the system aborts. */
Class
objc_get_class (const char *name)
{
Class class;
class = class_table_get_safe (name);
if (class)
return class;
if (_objc_lookup_class)
class = (*_objc_lookup_class) (name);
if (class)
return class;
objc_error (nil, OBJC_ERR_BAD_CLASS,
"objc runtime: cannot find class %s\n", name);
return 0;
}
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)
{
Class class;
class = class_table_next ( enum_state);
return class;
}
Class
class_pose_as (Class impostor, Class super_class)
{
fprintf(stderr, "Class posing is no longer supported.\n");
fprintf(stderr, "Please use class_replaceMethod() instead.\n");
abort();
}

@ -1,5 +1,7 @@
#include "magic_objects.h"
#include "objc/objc-api.h"
#include "objc/runtime.h"
#include "objc/hooks.h"
#include "class.h"
#include "lock.h"
#include <stdlib.h>
#include <assert.h>
@ -38,7 +40,7 @@ static Class unresolved_class_list;
void class_table_insert(Class class)
{
if (!CLS_ISRESOLV(class))
if (!objc_test_class_flag(class, objc_class_flag_resolved))
{
if (Nil != unresolved_class_list)
{
@ -69,7 +71,7 @@ void __objc_init_class_tables(void)
void objc_resolve_class(Class cls)
{
// Skip this if the class is already resolved.
if (CLS_ISRESOLV(cls)) { return; }
if (objc_test_class_flag(cls, objc_class_flag_resolved)) { return; }
// Remove the class from the unresolved class list
if (Nil == cls->unresolved_class_prev)
{
@ -91,8 +93,8 @@ void objc_resolve_class(Class cls)
static Class root_class = Nil;
if (Nil == root_class)
{
root_class = objc_get_class(ROOT_OBJECT_CLASS_NAME);
if (!CLS_ISRESOLV(root_class))
root_class = (Class)objc_getClass(ROOT_OBJECT_CLASS_NAME);
if (!objc_test_class_flag(root_class, objc_class_flag_resolved))
{
objc_resolve_class(root_class);
}
@ -107,15 +109,15 @@ void objc_resolve_class(Class cls)
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))
super = (Class)objc_getClass((char*)cls->super_class);
if (!objc_test_class_flag(super, objc_class_flag_resolved))
{
objc_resolve_class(super);
}
superMeta = super->class_pointer;
superMeta = super->isa;
// Set the superclass pointer for the class and the superclass
cls->super_class = super;
cls->class_pointer->super_class = super->class_pointer;
cls->isa->super_class = super->isa;
}
// Don't make the root class a subclass of itself
if (cls != super)
@ -124,25 +126,26 @@ void objc_resolve_class(Class cls)
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;
cls->isa->sibling_class = superMeta->subclass_list;
superMeta->subclass_list = cls->isa;
}
// Mark this class (and its metaclass) as resolved
CLS_SETRESOLV(cls);
CLS_SETRESOLV(cls->class_pointer);
objc_set_class_flag(cls, objc_class_flag_resolved);
objc_set_class_flag(cls->isa, objc_class_flag_resolved);
}
void __objc_resolve_class_links(void)
{
LOCK(__objc_runtime_mutex);
LOCK_UNTIL_RETURN(__objc_runtime_mutex);
Class class;
while ((class = unresolved_class_list))
{
objc_resolve_class(class);
}
UNLOCK(__objc_runtime_mutex);
}
// Public API
int objc_getClassList(Class *buffer, int bufferLen)
{
if (buffer == NULL)
@ -160,3 +163,57 @@ int objc_getClassList(Class *buffer, int bufferLen)
return count;
}
id objc_getClass(const char *name)
{
id class = (id)class_table_get_safe(name);
if (nil != class) { return class; }
if (0 != _objc_lookup_class)
{
class = (id)_objc_lookup_class(name);
}
return class;
}
id objc_lookUpClass(const char *name)
{
return (id)class_table_get_safe(name);
}
id objc_getMetaClass(const char *name)
{
Class cls = (Class)objc_getClass(name);
return cls == Nil ? nil : (id)cls->isa;
}
// Legacy interface compatibility
id objc_get_class(const char *name)
{
return objc_getClass(name);
}
id objc_lookup_class(const char *name)
{
return objc_getClass(name);
}
id objc_get_meta_class(const char *name)
{
return objc_getMetaClass(name);
}
Class objc_next_class(void **enum_state)
{
return class_table_next ( enum_state);
}
Class class_pose_as(Class impostor, Class super_class)
{
fprintf(stderr, "Class posing is no longer supported.\n");
fprintf(stderr, "Please use class_replaceMethod() instead.\n");
abort();
}

@ -20,6 +20,7 @@
#include "lock.h"
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#ifndef MAP_TABLE_NAME
# error You must define MAP_TABLE_NAME.

@ -0,0 +1,3 @@
#include <objc/runtime.h>
#define OBJC_HOOK
#include <objc/hooks.h>

@ -45,9 +45,18 @@ __attribute__((unused)) static void objc_release_lock(void *x)
mutex_t *lock = *(mutex_t**)x;
UNLOCK(lock);
}
/**
* Acquires the lock and automatically releases it at the end of the current
* scope.
*/
#define LOCK_UNTIL_RETURN(lock) \
__attribute__((cleanup(objc_release_lock)))\
__attribute__((unused)) mutex_t *lock_pointer = lock;\
LOCK(lock)
/**
* The global runtime mutex.
*/
extern void *__objc_runtime_mutex;
#endif // __LIBOBJC_LOCK_H_INCLUDED__

@ -0,0 +1,20 @@
/**
* This file includes all of the hooks that can be used to alter the behaviour
* of the runtime.
*/
#ifndef OBJC_HOOK
#define OBJC_HOOK extern
#endif
/**
* Class lookup hook. Set this to provide a mechanism for resolving classes
* that have not been registered with the runtime. This can be used for lazy
* library loading, for example. The hook takes a class name as an argument
* and returns the class. A JIT compiler could use this to allow classes to be
* compiled the first time that they are looked up. If the class is already
* registered with the runtime, this will not be called, so it can not be used
* for lazy loading of categories.
*/
OBJC_HOOK Class (*_objc_lookup_class)(const char *name);

@ -636,17 +636,6 @@ IMP method_setImplementation(Method method, IMP imp)
return old;
}
id objc_getClass(const char *name)
{
return (id)objc_get_class(name);
}
id objc_getMetaClass(const char *name)
{
Class cls = (Class)objc_getClass(name);
return cls == Nil ? nil : (id)cls->class_pointer;
}
id objc_getRequiredClass(const char *name)
{
id cls = objc_getClass(name);
@ -657,12 +646,6 @@ id objc_getRequiredClass(const char *name)
return cls;
}
id objc_lookUpClass(const char *name)
{
// TODO: Check these are the right way around.
return (id)objc_lookup_class(name);
}
static void freeMethodLists(Class aClass)
{
struct objc_method_list *methods = aClass->methods;

Loading…
Cancel
Save