diff options
author | nicola <nicola@138bc75d-0d04-0410-961f-82ee72b054a4> | 2010-10-16 21:26:59 +0000 |
---|---|---|
committer | nicola <nicola@138bc75d-0d04-0410-961f-82ee72b054a4> | 2010-10-16 21:26:59 +0000 |
commit | 0e0a5cbd6de5aad3bb15589511e5f13062be51d5 (patch) | |
tree | 3920a8a13cd2db3193c61dca0c4a3e93ab0c05f5 /libobjc/class.c | |
parent | 12997918b221d19591bfa841e98da89aa552a87f (diff) | |
download | gcc-0e0a5cbd6de5aad3bb15589511e5f13062be51d5.tar.gz |
In libobjc/:
2010-10-16 Nicola Pero <nicola.pero@meta-innovation.com>
* objc/runtime.h: Updated comments.
(class_addMethod): New.
(class_addIvar): New.
(class_replaceMethod): New.
(objc_allocateClassPair): New.
(objc_registerClassPair): New.
(objc_disposeClassPair): New.
* class.c (objc_allocateClassPair): New.
(objc_registerClassPair): New.
(objc_disposeClassPair): New.
(class_getSuperclass): Return Nil if a class is in construction.
* init.c (__objc_exec_class): Call __objc_init_class.
(__objc_init_class): New.
* ivars.c (class_copyIvarList): Return NULL if class is in
construction. Do not lock the runtime mutex.
(class_getInstanceVariable): Return NULL if class is in
construction. Do not lock the runtime mutex.
(class_addIvar): New.
* sendmsg.c (class_addMethod): New.
(class_replaceMethod): New.
* objc-private/module-abi-8.h (__CLS_SETNOTINFO): New.
(_CLS_IN_CONSTRUCTION): New.
(CLS_IS_IN_CONSTRUCTION): New.
(CLS_SET_IN_CONSTRUCTION): New.
(CLS_SET_NOT_IN_CONSTRUCTION): New.
* objc-private/runtime.h (__objc_init_class): New.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@165563 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'libobjc/class.c')
-rw-r--r-- | libobjc/class.c | 198 |
1 files changed, 198 insertions, 0 deletions
diff --git a/libobjc/class.c b/libobjc/class.c index 71483457e25..ade5a71f453 100644 --- a/libobjc/class.c +++ b/libobjc/class.c @@ -570,6 +570,199 @@ objc_getClassList (Class *returnValue, int maxNumberOfClassesToReturn) return count; } +Class +objc_allocateClassPair (Class super_class, const char *class_name, size_t extraBytes) +{ + Class new_class; + Class new_meta_class; + + if (class_name == NULL) + return Nil; + + if (objc_getClass (class_name)) + return Nil; + + if (super_class) + { + /* If you want to build a hierarchy of classes, you need to + build and register them one at a time. The risk is that you + are able to cause confusion by registering a subclass before + the superclass or similar. */ + if (CLS_IS_IN_CONSTRUCTION (super_class)) + return Nil; + } + + /* Technically, we should create the metaclass first, then use + class_createInstance() to create the class. That complication + would be relevant if we had class variables, but we don't, so we + just ignore it and create everything directly and assume all + classes have the same size. */ + new_class = objc_calloc (1, sizeof (struct objc_class) + extraBytes); + new_meta_class = objc_calloc (1, sizeof (struct objc_class) + extraBytes); + + /* We create an unresolved class, similar to one generated by the + compiler. It will be resolved later when we register it. + + Note how the metaclass details are not that important; when the + class is resolved, the ones that matter will be fixed up. */ + new_class->class_pointer = new_meta_class; + new_meta_class->class_pointer = 0; + + if (super_class) + { + /* Force the name of the superclass in place of the link to the + actual superclass, which will be put there when the class is + resolved. */ + const char *super_class_name = class_getName (super_class); + new_class->super_class = (void *)super_class_name; + new_meta_class->super_class = (void *)super_class_name; + } + else + { + new_class->super_class = (void *)0; + new_meta_class->super_class = (void *)0; + } + + new_class->name = objc_malloc (strlen (class_name) + 1); + strcpy ((char*)new_class->name, class_name); + new_meta_class->name = new_class->name; + + new_class->version = 0; + new_meta_class->version = 0; + + new_class->info = _CLS_CLASS | _CLS_IN_CONSTRUCTION; + new_meta_class->info = _CLS_META | _CLS_IN_CONSTRUCTION; + + if (super_class) + new_class->instance_size = super_class->instance_size; + else + new_class->instance_size = 0; + new_meta_class->instance_size = sizeof (struct objc_class); + + return new_class; +} + +void +objc_registerClassPair (Class class_) +{ + if (class_ == Nil) + return; + + if ((! CLS_ISCLASS (class_)) || (! CLS_IS_IN_CONSTRUCTION (class_))) + return; + + if ((! CLS_ISMETA (class_->class_pointer)) || (! CLS_IS_IN_CONSTRUCTION (class_->class_pointer))) + return; + + objc_mutex_lock (__objc_runtime_mutex); + + if (objc_getClass (class_->name)) + { + objc_mutex_unlock (__objc_runtime_mutex); + return; + } + + CLS_SET_NOT_IN_CONSTRUCTION (class_); + CLS_SET_NOT_IN_CONSTRUCTION (class_->class_pointer); + + __objc_init_class (class_); + + /* Resolve class links immediately. No point in waiting. */ + __objc_resolve_class_links (); + + objc_mutex_unlock (__objc_runtime_mutex); +} + +void +objc_disposeClassPair (Class class_) +{ + if (class_ == Nil) + return; + + if ((! CLS_ISCLASS (class_)) || (! CLS_IS_IN_CONSTRUCTION (class_))) + return; + + if ((! CLS_ISMETA (class_->class_pointer)) || (! CLS_IS_IN_CONSTRUCTION (class_->class_pointer))) + return; + + /* Undo any class_addIvar(). */ + if (class_->ivars) + { + int i; + for (i = 0; i < class_->ivars->ivar_count; i++) + { + struct objc_ivar *ivar = &(class_->ivars->ivar_list[i]); + + objc_free ((char *)ivar->ivar_name); + objc_free ((char *)ivar->ivar_type); + } + + objc_free (class_->ivars); + } + + /* Undo any class_addMethod(). */ + if (class_->methods) + { + struct objc_method_list *list = class_->methods; + while (list) + { + int i; + struct objc_method_list *next = list->method_next; + + for (i = 0; i < list->method_count; i++) + { + struct objc_method *method = &(list->method_list[i]); + + objc_free ((char *)method->method_name); + objc_free ((char *)method->method_types); + } + + objc_free (list); + list = next; + } + } + + /* Undo any class_addProtocol(). */ + if (class_->protocols) + { + struct objc_protocol_list *list = class_->protocols; + while (list) + { + struct objc_protocol_list *next = list->next; + + objc_free (list); + list = next; + } + } + + /* Undo any class_addMethod() on the meta-class. */ + if (class_->class_pointer->methods) + { + struct objc_method_list *list = class_->class_pointer->methods; + while (list) + { + int i; + struct objc_method_list *next = list->method_next; + + for (i = 0; i < list->method_count; i++) + { + struct objc_method *method = &(list->method_list[i]); + + objc_free ((char *)method->method_name); + objc_free ((char *)method->method_types); + } + + objc_free (list); + list = next; + } + } + + /* Undo objc_allocateClassPair(). */ + objc_free ((char *)(class_->name)); + objc_free (class_->class_pointer); + objc_free (class_); +} + /* Traditional GNU Objective-C Runtime API. */ /* 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 @@ -807,6 +1000,11 @@ class_getSuperclass (Class class_) if (class_ == Nil) return Nil; + /* Classes that are in construction are not resolved and can not be + resolved! */ + if (CLS_IS_IN_CONSTRUCTION (class_)) + return Nil; + /* If the class is not resolved yet, super_class would point to a string (the name of the super class) as opposed to the actual super class. In that case, we need to resolve the class links |