Commit 0bfe3fa1 by Nicola Pero Committed by Nicola Pero

In libobjc/: 2010-12-22 Nicola Pero <nicola.pero@meta-innovation.com>

In libobjc/:
2010-12-22  Nicola Pero  <nicola.pero@meta-innovation.com>

	* init.c (duplicate_classes): New.
	(__objc_exec_class): Initialize duplicate_classes.
	(__objc_create_classes_tree): Ignore classes in the
	duplicate_classes table.
	(__objc_call_load_callback): Same.
	(__objc_init_class): If a duplicate class is found, add it to
	duplicate_classes instead of aborting.  Return YES if the class is
	not a duplicate, and NO if it is.
	* objc-private/runtime.h (__objc_init_class): Updated prototype.

From-SVN: r168183
parent 9be8ba7e
2010-12-22 Nicola Pero <nicola.pero@meta-innovation.com> 2010-12-22 Nicola Pero <nicola.pero@meta-innovation.com>
* init.c (duplicate_classes): New.
(__objc_exec_class): Initialize duplicate_classes.
(__objc_create_classes_tree): Ignore classes in the
duplicate_classes table.
(__objc_call_load_callback): Same.
(__objc_init_class): If a duplicate class is found, add it to
duplicate_classes instead of aborting. Return YES if the class is
not a duplicate, and NO if it is.
* objc-private/runtime.h (__objc_init_class): Updated prototype.
2010-12-22 Nicola Pero <nicola.pero@meta-innovation.com>
* objc-private/objc-list.h: Reindented file. No code changes. * objc-private/objc-list.h: Reindented file. No code changes.
* objc-private/sarray.h: Same change. * objc-private/sarray.h: Same change.
......
...@@ -56,6 +56,16 @@ static struct objc_list *unclaimed_proto_list = 0; /* !T:MUTEX */ ...@@ -56,6 +56,16 @@ static struct objc_list *unclaimed_proto_list = 0; /* !T:MUTEX */
/* List of unresolved static instances. */ /* List of unresolved static instances. */
static struct objc_list *uninitialized_statics = 0; /* !T:MUTEX */ static struct objc_list *uninitialized_statics = 0; /* !T:MUTEX */
/* List of duplicated classes found while loading modules. If we find
a class twice, we ignore it the second time. On some platforms,
where the order in which modules are loaded is well defined, this
allows you to replace a class in a shared library by linking in a
new implementation which is loaded in in the right order, and which
overrides the existing one.
Protected by __objc_runtime_mutex. */
static cache_ptr duplicate_classes = NULL;
/* Global runtime "write" mutex. Having a single mutex prevents /* Global runtime "write" mutex. Having a single mutex prevents
deadlocks, but reduces concurrency. To improve concurrency, some deadlocks, but reduces concurrency. To improve concurrency, some
groups of functions in the runtime have their own separate mutex groups of functions in the runtime have their own separate mutex
...@@ -87,7 +97,7 @@ static void __objc_class_add_protocols (Class, struct objc_protocol_list *); ...@@ -87,7 +97,7 @@ static void __objc_class_add_protocols (Class, struct objc_protocol_list *);
/* Load callback hook. */ /* Load callback hook. */
void (*_objc_load_callback) (Class class, struct objc_category *category) = 0; /* !T:SAFE */ void (*_objc_load_callback) (Class class, struct objc_category *category) = 0; /* !T:SAFE */
/* Are all categories/classes resolved? */ /* Are all categories/classes resolved ? */
BOOL __objc_dangling_categories = NO; /* !T:UNUSED */ BOOL __objc_dangling_categories = NO; /* !T:UNUSED */
/* Sends +load to all classes and categories in certain /* Sends +load to all classes and categories in certain
...@@ -110,9 +120,11 @@ static void __objc_call_load_callback (struct objc_module *module); ...@@ -110,9 +120,11 @@ static void __objc_call_load_callback (struct objc_module *module);
installed in the runtime. */ installed in the runtime. */
static BOOL class_is_subclass_of_class (Class class, Class superclass); static BOOL class_is_subclass_of_class (Class class, Class superclass);
typedef struct objc_class_tree { typedef struct objc_class_tree
{
Class class; Class class;
struct objc_list *subclasses; /* `head' is pointer to an objc_class_tree */ struct objc_list *subclasses; /* `head' is a pointer to an
objc_class_tree. */
} objc_class_tree; } objc_class_tree;
/* This is a linked list of objc_class_tree trees. The head of these /* This is a linked list of objc_class_tree trees. The head of these
...@@ -583,6 +595,9 @@ __objc_exec_class (struct objc_module *module) ...@@ -583,6 +595,9 @@ __objc_exec_class (struct objc_module *module)
__objc_init_selector_tables (); __objc_init_selector_tables ();
__objc_init_class_tables (); __objc_init_class_tables ();
__objc_init_dispatch_tables (); __objc_init_dispatch_tables ();
duplicate_classes = objc_hash_new (8,
(hash_func_type)objc_hash_ptr,
objc_compare_ptrs);
__objc_class_tree_list = list_cons (NULL, __objc_class_tree_list); __objc_class_tree_list = list_cons (NULL, __objc_class_tree_list);
__objc_load_methods = objc_hash_new (128, __objc_load_methods = objc_hash_new (128,
(hash_func_type)objc_hash_ptr, (hash_func_type)objc_hash_ptr,
...@@ -619,13 +634,14 @@ __objc_exec_class (struct objc_module *module) ...@@ -619,13 +634,14 @@ __objc_exec_class (struct objc_module *module)
isn't and this crashes the program. */ isn't and this crashes the program. */
class->subclass_list = NULL; class->subclass_list = NULL;
__objc_init_class (class); if (__objc_init_class (class))
{
/* Check to see if the superclass is known in this point. If /* Check to see if the superclass is known in this point. If
it's not add the class to the unresolved_classes list. */ it's not add the class to the unresolved_classes list. */
if (superclass && ! objc_getClass (superclass)) if (superclass && ! objc_getClass (superclass))
unresolved_classes = list_cons (class, unresolved_classes); unresolved_classes = list_cons (class, unresolved_classes);
} }
}
/* Process category information from the module. */ /* Process category information from the module. */
for (i = 0; i < symtab->cat_def_cnt; ++i) for (i = 0; i < symtab->cat_def_cnt; ++i)
...@@ -637,7 +653,6 @@ __objc_exec_class (struct objc_module *module) ...@@ -637,7 +653,6 @@ __objc_exec_class (struct objc_module *module)
methods. */ methods. */
if (class) if (class)
{ {
DEBUG_PRINTF ("processing categories from (module,object): %s, %s\n", DEBUG_PRINTF ("processing categories from (module,object): %s, %s\n",
module->name, module->name,
class->name); class->name);
...@@ -808,6 +823,7 @@ __objc_create_classes_tree (struct objc_module *module) ...@@ -808,6 +823,7 @@ __objc_create_classes_tree (struct objc_module *module)
{ {
Class class = (Class) symtab->defs[i]; Class class = (Class) symtab->defs[i];
if (!objc_hash_is_key_in_hash (duplicate_classes, class))
objc_tree_insert_class (class); objc_tree_insert_class (class);
} }
...@@ -846,9 +862,12 @@ __objc_call_load_callback (struct objc_module *module) ...@@ -846,9 +862,12 @@ __objc_call_load_callback (struct objc_module *module)
{ {
Class class = (Class) symtab->defs[i]; Class class = (Class) symtab->defs[i];
if (!objc_hash_is_key_in_hash (duplicate_classes, class))
{
/* Call the _objc_load_callback for this class. */ /* Call the _objc_load_callback for this class. */
_objc_load_callback (class, 0); _objc_load_callback (class, 0);
} }
}
/* Call the _objc_load_callback for categories. Don't register /* Call the _objc_load_callback for categories. Don't register
the instance methods as class methods for categories to root the instance methods as class methods for categories to root
...@@ -874,8 +893,11 @@ init_check_module_version (struct objc_module *module) ...@@ -874,8 +893,11 @@ init_check_module_version (struct objc_module *module)
} }
} }
/* __objc_init_class must be called with __objc_runtime_mutex already locked. */ /* __objc_init_class must be called with __objc_runtime_mutex already
void locked. Return YES if the class could be setup; return NO if the
class could not be setup because a class with the same name already
exists. */
BOOL
__objc_init_class (Class class) __objc_init_class (Class class)
{ {
/* Store the class in the class table and assign class numbers. */ /* Store the class in the class table and assign class numbers. */
...@@ -895,10 +917,16 @@ __objc_init_class (Class class) ...@@ -895,10 +917,16 @@ __objc_init_class (Class class)
if (class->protocols) if (class->protocols)
__objc_init_protocols (class->protocols); __objc_init_protocols (class->protocols);
return YES;
} }
else else
_objc_abort ("Module contains duplicate class '%s'\n", {
class->name); /* The module contains a duplicate class. Remember it so that
we will ignore it later. */
objc_hash_add (&duplicate_classes, class, class);
return NO;
}
} }
/* __objc_init_protocol must be called with __objc_runtime_mutex /* __objc_init_protocol must be called with __objc_runtime_mutex
......
...@@ -57,7 +57,7 @@ extern void __objc_update_dispatch_table_for_class (Class);/* (objc-msg.c) */ ...@@ -57,7 +57,7 @@ extern void __objc_update_dispatch_table_for_class (Class);/* (objc-msg.c) */
extern int __objc_init_thread_system (void); /* thread.c */ extern int __objc_init_thread_system (void); /* thread.c */
extern int __objc_fini_thread_system (void); /* thread.c */ extern int __objc_fini_thread_system (void); /* thread.c */
extern void __objc_init_class (Class class); /* init.c */ extern BOOL __objc_init_class (Class class); /* init.c */
extern void class_add_method_list (Class, struct objc_method_list *); extern void class_add_method_list (Class, struct objc_method_list *);
/* Registering instance methods as class methods for root classes */ /* Registering instance methods as class methods for root classes */
......
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