diff options
author | bstarynk <bstarynk@138bc75d-0d04-0410-961f-82ee72b054a4> | 2010-10-12 19:25:01 +0000 |
---|---|---|
committer | bstarynk <bstarynk@138bc75d-0d04-0410-961f-82ee72b054a4> | 2010-10-12 19:25:01 +0000 |
commit | b4cab6749ba18cf0b3a3c1bd01085cfe94616c3b (patch) | |
tree | 2b77880a4930b3a58042e9b269e3e3e5e97d7b8f /libobjc | |
parent | 77d3568815aaad6487a295a42e0fce17c1c71b19 (diff) | |
download | gcc-b4cab6749ba18cf0b3a3c1bd01085cfe94616c3b.tar.gz |
2010-10-12 Basile Starynkevitch <basile@starynkevitch.net>
MELT branch merged with trunk rev 165392
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/melt-branch@165394 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'libobjc')
-rw-r--r-- | libobjc/ChangeLog | 120 | ||||
-rw-r--r-- | libobjc/Makefile.in | 1 | ||||
-rw-r--r-- | libobjc/archive.c | 1 | ||||
-rw-r--r-- | libobjc/class.c | 67 | ||||
-rw-r--r-- | libobjc/encoding.c | 5 | ||||
-rw-r--r-- | libobjc/error.c | 3 | ||||
-rw-r--r-- | libobjc/exception.c | 15 | ||||
-rw-r--r-- | libobjc/gc.c | 8 | ||||
-rw-r--r-- | libobjc/hash.c | 4 | ||||
-rw-r--r-- | libobjc/init.c | 23 | ||||
-rw-r--r-- | libobjc/ivars.c | 24 | ||||
-rw-r--r-- | libobjc/linking.m | 3 | ||||
-rw-r--r-- | libobjc/memory.c | 3 | ||||
-rw-r--r-- | libobjc/objc-private/hash.h | 3 | ||||
-rw-r--r-- | libobjc/objc-private/module-abi-8.h | 61 | ||||
-rw-r--r-- | libobjc/objc-private/protocols.h | 46 | ||||
-rw-r--r-- | libobjc/objc-private/runtime.h | 9 | ||||
-rw-r--r-- | libobjc/objc-sync.c | 2 | ||||
-rw-r--r-- | libobjc/objc/deprecated/hash.h | 3 | ||||
-rw-r--r-- | libobjc/objc/deprecated/struct_objc_class.h | 1 | ||||
-rw-r--r-- | libobjc/objc/objc-decls.h | 14 | ||||
-rw-r--r-- | libobjc/objc/runtime.h | 215 | ||||
-rw-r--r-- | libobjc/objects.c | 9 | ||||
-rw-r--r-- | libobjc/protocols.c | 549 | ||||
-rw-r--r-- | libobjc/sarray.c | 5 | ||||
-rw-r--r-- | libobjc/selector.c | 15 | ||||
-rw-r--r-- | libobjc/sendmsg.c | 1 | ||||
-rw-r--r-- | libobjc/thr.c | 3 |
28 files changed, 1144 insertions, 69 deletions
diff --git a/libobjc/ChangeLog b/libobjc/ChangeLog index e2d93108abf..ec0a98f3790 100644 --- a/libobjc/ChangeLog +++ b/libobjc/ChangeLog @@ -1,3 +1,123 @@ +2010-10-12 Nicola Pero <nicola.pero@meta-innovation.com> + + * class.c: Include objc/runtime.h and objc-private/module-abi-8.h + instead of objc/objc-api.h. + (objc_get_unknown_class_handler): Do not define. + (class_isMetaClass): New. + (class_getSuperclass): New. + (class_getVersion): New. + (class_setVersion): New. + (class_getInstanceSize): New. + * exceptions.c: Include objc/runtime.h instead of objc/objc-api.h. + (is_kind_of_exception_matcher): Use objc_getSuperclass instead of + objc_get_super_class. + (get_ttype_entry): Use objc_getRequiredClass instead of + objc_get_class. + * ivars.c (class_getClassVariable): New. + * objects.c: Include objc/runtime.h, objc/thr.h and + objc-private/module-abi-8.h instead of objc/objc-api.h + * objc/runtime.h (class_getClassVariable): New. + (class_isMetaClass): New. + (class_getSuperclass): New. + (class_getVersion): New. + (class_setVersion): New. + (class_getInstanceSize): New. + * objc-private/module-abi-8.h (HOST_BITS_PER_LONG): New (from + objc/objc-api.h) + (__CLS_INFO): Same. + (__CLS_ISINFO): Same. + (__CLS_SETINFO): Same. + (CLS_ISMETA): Same. + (CLS_ISCLASS): Same. + (CLS_ISRESOLV): Same. + (CLS_SETRESOLV): Same. + (CLS_ISINITIALIZED): Same. + (CLS_SETINITIALIZED): Same. + (CLS_GETNUMBER): Same. + (CLS_SETNUMBER): Same. + +2010-10-12 Nicola Pero <nicola.pero@meta-innovation.com> + + * archive.c: Do not include objc/objc.h. + * class.c: Do not include objc/objc.h. + * encoding.c: Include objc/runtime.h, ctype.h and + objc-private/module-abi-8.h instead of objc/objc-api.h and + objc/encoding.h. + * error.c: Do not include objc/objc.h. + * gc.c: Include tconfig.h and objc/encoding.h only if + OBJC_WITH_GC. + * hash.c: Include objc/runtime.h and objc/thr.h instead of + objc/objc-api.h. Do not include objc/objc.h. + * init.c: Do not include objc/objc.h. + * ivars.c: Include objc/runtime.h, objc-private/module-abi-8.h and + objc/thr.h instead of objc/objc-api.h. Do not include + objc/objc.h. + * linking.m: Tidied comment. + * memory.c: Include objc/runtime.h instead of objc/objc-api.h. + Do not include objc/objc.h. + * objects.c: Do not include objc/objc.h. + * objc-sync.c: Include objc/runtime.h instead of objc/objc-api.h. + * protocols.c: Do not include objc/objc.h. + * sarray.c: Include objc/runtime.h instead of objc/objc-api.h. Do + not include objc/objc.h. + * selector.c: Do not include objc/objc.h. + * sendmsg.c: Do not include objc/objc.h. + * thr.c: Include objc/runtime.h instead of objc/objc-api.h. + Do not include objc/objc.h. + * objc/objc-decls.h: Reindented code. + * objc/runtime.h Include objc-decls.h. Updated comments. + (objc_malloc): New. + (objc_atomic_malloc): New. + (objc_calloc): New. + (objc_realloc): New. + (objc_free): New. + * objc-private/runtime.h: Updated comments. + +2010-10-12 Nicola Pero <nicola.pero@meta-innovation.com> + + * Makefile.in (C_SOURCE_FILES): Added protocols.c. + * objc-private/protocols.h: New. + * protocols.c: New. + * init.c: Include objc-private/protocols.h. + (__objc_exec_class): Call __objc_protocols_init on startup. + (__objc_init_protocols): Call __objc_protocols_add_protocol. + * objc-private/runtime.h: Use (struct objc_method_list *) instead + of MethodList_t, and (struct objc_method *) instead of Method_t. + * objc/deprecated/struct_objc_class.h: Define + __objc_STRUCT_OBJC_CLASS_defined. + * objc-private/module-abi-8.h (struct + objc_method_description_list): New. + (struct objc_class): Only define if + __objc_STRUCT_OBJC_CLASS_defined is undefined. + * objc/runtime.h (class_getName): New. + (objc_getProtocol): New. + (objc_copyProtocolList): New. + (class_addProtocol): New. + (class_conformsToProtocol): New. + (class_copyProtocolList): New. + (protocol_conformsToProtocol): New. + (protocol_isEqual): New. + (protocol_getName): New. + (protocol_getMethodDescription): New. + (protocol_copyMethodDescriptionList): New. + (protocol_getProperty): New. + (protocol_copyPropertyList): New. + (protocol_copyProtocolList): New. + * class.c (class_getName): New. + * selector.c (sel_isEqual): New. + +2010-10-12 Nicola Pero <nicola.pero@meta-innovation.com> + + * selector.c (sel_getName): Return "<null selector>" for a NULL + argument. + (sel_get_name): Return 0 for a NULL argument. + * objc/runtime.h (sel_getName): Updated documentation. + + * objc-private/hash.h (class_hash_table): Unused declaration + removed. + (module_hash_table): Same. + * objc/deprecated/hash.h: Same changes. + 2010-10-11 Nicola Pero <nicola.pero@meta-innovation.com> * class.c (objc_getClassList): New. diff --git a/libobjc/Makefile.in b/libobjc/Makefile.in index 86f65bad844..4790f952b9d 100644 --- a/libobjc/Makefile.in +++ b/libobjc/Makefile.in @@ -177,6 +177,7 @@ C_SOURCE_FILES = \ objc-foreach.c \ objc-sync.c \ objects.c \ + protocols.c \ sarray.c \ selector.c \ sendmsg.c \ diff --git a/libobjc/archive.c b/libobjc/archive.c index f36f1b748fb..b539ca1163e 100644 --- a/libobjc/archive.c +++ b/libobjc/archive.c @@ -27,7 +27,6 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see #include "objc-private/common.h" #include "objc-private/error.h" #include "tconfig.h" -#include "objc/objc.h" #include "objc/objc-api.h" #include "objc/hash.h" #include "objc/objc-list.h" diff --git a/libobjc/class.c b/libobjc/class.c index 216d6ace0dc..4eb86761ee8 100644 --- a/libobjc/class.c +++ b/libobjc/class.c @@ -89,11 +89,11 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see #include "objc-private/common.h" #include "objc-private/error.h" -#include "objc/objc.h" -#include "objc/objc-api.h" +#include "objc/runtime.h" #include "objc/thr.h" -#include "objc-private/runtime.h" /* the kitchen sink */ -#include <string.h> /* For memset */ +#include "objc-private/module-abi-8.h" /* For CLS_ISCLASS and similar. */ +#include "objc-private/runtime.h" /* the kitchen sink */ +#include <string.h> /* For memset */ /* We use a table which maps a class name to the corresponding class * pointer. The first part of this file defines this table, and @@ -139,7 +139,8 @@ static class_node_ptr class_table_array[CLASS_TABLE_SIZE]; /* The table writing mutex - we lock on writing to avoid conflicts between different writers, but we read without locks. That is possible because we assume pointer assignment to be an atomic - operation. */ + operation. TODO: This is only true under certain circumstances, + which should be clarified. */ static objc_mutex_t __class_table_lock = NULL; /* CLASS_TABLE_HASH is how we compute the hash of a class name. It is @@ -417,11 +418,6 @@ class_table_print_histogram (void) */ Class (*_objc_lookup_class) (const char *name) = 0; /* !T:SAFE */ -/* Temporarily while we still include objc/objc-api.h instead of objc/runtime.h. */ -#ifndef __objc_runtime_INCLUDE_GNU -typedef Class (*objc_get_unknown_class_handler)(const char *class_name); -#endif - /* The handler currently in use. PS: if both __obj_get_unknown_class_handler and _objc_lookup_class are defined, __objc_get_unknown_class_handler is called first. */ @@ -591,6 +587,7 @@ objc_lookup_class (const char *name) called automatically by the compiler while messaging (if using the traditional ABI), so it is worth keeping it fast; don't make it just a wrapper around objc_getClass(). */ +/* Note that this is roughly equivalent to objc_getRequiredClass(). */ /* 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. */ @@ -730,7 +727,57 @@ __objc_resolve_class_links (void) objc_mutex_unlock (__objc_runtime_mutex); } +const char * +class_getName (Class class_) +{ + if (class_ == Nil) + return "nil"; + + return class_->name; +} + +BOOL +class_isMetaClass (Class class_) +{ + /* CLS_ISMETA includes the check for Nil class_. */ + return CLS_ISMETA (class_); +} + +Class +class_getSuperclass (Class class_) +{ + if (class_ == Nil) + return Nil; + return class_->super_class; +} + +int +class_getVersion (Class class_) +{ + if (class_ == Nil) + return 0; + + return (int)(class_->version); +} + +void +class_setVersion (Class class_, int version) +{ + if (class_ == Nil) + return; + + class_->version = version; +} + +size_t +class_getInstanceSize (Class class_) +{ + if (class_ == Nil) + return 0; + + return class_->instance_size; +} #define CLASSOF(c) ((c)->class_pointer) diff --git a/libobjc/encoding.c b/libobjc/encoding.c index d417b87396e..87517f4eaf8 100644 --- a/libobjc/encoding.c +++ b/libobjc/encoding.c @@ -36,9 +36,10 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see #include "tconfig.h" #include "coretypes.h" #include "tm.h" -#include "objc/objc-api.h" -#include "objc/encoding.h" +#include "objc/runtime.h" +#include "objc-private/module-abi-8.h" /* For struct objc_method */ #include <stdlib.h> +#include <ctype.h> #undef MAX #define MAX(X, Y) \ diff --git a/libobjc/error.c b/libobjc/error.c index 0dc8fd8dae0..7c6ba44b76f 100644 --- a/libobjc/error.c +++ b/libobjc/error.c @@ -48,8 +48,7 @@ _objc_abort (const char *fmt, ...) } /* The rest of the file is deprecated. */ -#include "objc/objc.h" -#include "objc/objc-api.h" +#include "objc/objc-api.h" /* For objc_error_handler. */ /* ** Error handler function diff --git a/libobjc/exception.c b/libobjc/exception.c index a221a3e77e3..4883448afad 100644 --- a/libobjc/exception.c +++ b/libobjc/exception.c @@ -25,7 +25,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see #include "objc-private/common.h" #include <stdlib.h> #include "config.h" -#include "objc/objc-api.h" +#include "objc/runtime.h" #include "objc/objc-exception.h" #include "unwind.h" #include "unwind-pe.h" @@ -57,7 +57,7 @@ is_kind_of_exception_matcher (Class catch_class, id exception) Class c; for (c = exception->class_pointer; c != Nil; - c = class_get_super_class (c)) + c = class_getSuperclass (c)) if (c == catch_class) return 1; } @@ -191,9 +191,11 @@ get_ttype_entry (struct lsda_header_info *info, _uleb128_t i) ptr = (_Unwind_Ptr) (info->TType - (i * 4)); ptr = _Unwind_decode_target2 (ptr); - + + /* NULL ptr means catch-all. Note that if the class is not found, + this will abort the program. */ if (ptr) - return objc_get_class ((const char *) ptr); + return objc_getRequiredClass ((const char *) ptr); else return 0; } @@ -209,9 +211,10 @@ get_ttype_entry (struct lsda_header_info *info, _Unwind_Word i) read_encoded_value_with_base (info->ttype_encoding, info->ttype_base, info->TType - i, &ptr); - /* NULL ptr means catch-all. */ + /* NULL ptr means catch-all. Note that if the class is not found, + this will abort the program. */ if (ptr) - return objc_get_class ((const char *) ptr); + return objc_getRequiredClass ((const char *) ptr); else return 0; } diff --git a/libobjc/gc.c b/libobjc/gc.c index a67ba1c9855..ed5effbb437 100644 --- a/libobjc/gc.c +++ b/libobjc/gc.c @@ -24,15 +24,15 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see <http://www.gnu.org/licenses/>. */ #include "objc-private/common.h" -#include "tconfig.h" #include "objc/objc.h" -#include "objc/encoding.h" +#if OBJC_WITH_GC + +#include "tconfig.h" #include <assert.h> #include <string.h> #include <stdlib.h> - -#if OBJC_WITH_GC +#include "objc/encoding.h" #include <gc.h> #include <limits.h> diff --git a/libobjc/hash.c b/libobjc/hash.c index 602fc84a874..3ecc54a170a 100644 --- a/libobjc/hash.c +++ b/libobjc/hash.c @@ -25,8 +25,8 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see #include "objc-private/common.h" #include <assert.h> /* For assert */ -#include "objc/objc.h" -#include "objc/objc-api.h" +#include "objc/runtime.h" /* For objc_calloc */ +#include "objc/thr.h" /* Required by objc-private/runtime.h. */ #include "objc-private/hash.h" #include "objc-private/runtime.h" /* for DEBUG_PRINTF */ diff --git a/libobjc/init.c b/libobjc/init.c index deb089d7e16..0f714c40596 100644 --- a/libobjc/init.c +++ b/libobjc/init.c @@ -26,13 +26,13 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see #include "objc-private/common.h" #include "objc-private/error.h" -#include "objc/objc.h" #include "objc/objc-api.h" #include "objc/thr.h" #include "objc-private/hash.h" #include "objc-private/objc-list.h" #include "objc-private/runtime.h" #include "objc-private/objc-sync.h" /* For __objc_sync_init() */ +#include "objc-private/protocols.h" /* For __objc_protocols_init() and __objc_protocols_add_protocol() */ /* The version number of this runtime. This must match the number defined in gcc (objc-act.c). */ @@ -48,7 +48,17 @@ static struct objc_list *unclaimed_proto_list = 0; /* !T:MUTEX */ /* List of unresolved static instances. */ static struct objc_list *uninitialized_statics = 0; /* !T:MUTEX */ -/* Global runtime "write" mutex. */ +/* Global runtime "write" mutex. Having a single mutex prevents + deadlocks, but reduces concurrency. To improve concurrency, some + groups of functions in the runtime have their own separate mutex + (eg, __class_table_lock in class.c); to avoid deadlocks, these + routines must make sure that they never acquire any other lock + while holding their own local lock. Ie, they should lock, execute + some C code that does not perform any calls to other runtime + functions which may potentially lock different locks, then unlock. + If they need to perform any calls to other runtime functions that + may potentially lock other locks, then they should use the global + __objc_runtime_mutex. */ objc_mutex_t __objc_runtime_mutex = 0; /* Number of threads that are alive. */ @@ -551,6 +561,7 @@ __objc_exec_class (Module_t module) __objc_load_methods = objc_hash_new (128, (hash_func_type)objc_hash_ptr, objc_compare_ptrs); + __objc_protocols_init (); __objc_sync_init (); previous_constructors = 1; } @@ -862,10 +873,14 @@ __objc_init_protocols (struct objc_protocol_list *protos) struct objc_protocol *aProto = protos->list[i]; if (((size_t)aProto->class_pointer) == PROTOCOL_VERSION) { - /* assign class pointer */ + /* Assign class pointer */ aProto->class_pointer = proto_class; - /* init super protocols */ + /* Register the protocol in the hashtable or protocols by + name. */ + __objc_protocols_add_protocol (aProto->protocol_name, aProto); + + /* Init super protocols */ __objc_init_protocols (aProto->protocol_list); } else if (protos->list[i]->class_pointer != proto_class) diff --git a/libobjc/ivars.c b/libobjc/ivars.c index 18c6e8af29d..52b71af1124 100644 --- a/libobjc/ivars.c +++ b/libobjc/ivars.c @@ -23,8 +23,9 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see <http://www.gnu.org/licenses/>. */ #include "objc-private/common.h" -#include "objc/objc.h" -#include "objc/objc-api.h" +#include "objc/runtime.h" +#include "objc-private/module-abi-8.h" /* For runtime structures */ +#include "objc/thr.h" #include "objc-private/runtime.h" /* the kitchen sink */ #include <string.h> /* For strcmp */ @@ -59,6 +60,25 @@ class_getInstanceVariable (Class class_, const char *name) return NULL; } +struct objc_ivar * +class_getClassVariable (Class class_, const char *name) +{ + if (class_ == Nil) + return NULL; + + /* Logically, since a class is an instance of its meta-class, and + since its class methods are the instance methods of the + meta-class, class variables should be instance variables of the + meta-class. That is different from the normal use of having + 'static' variables in the class implementation file, because + every class would have its own variables. + + Anyway, it is all speculative at this stage, but if we get class + variables in Objective-C, it is conceivable that this + implementation should work. */ + return class_getInstanceVariable (class_->class_pointer, name); +} + void * object_getIndexedIvars (id object) { diff --git a/libobjc/linking.m b/libobjc/linking.m index 6372e91df45..e94c8ea8c4b 100644 --- a/libobjc/linking.m +++ b/libobjc/linking.m @@ -28,8 +28,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see #include <objc/NXConstStr.h> /* Generate references to Object and NXConstanstString classes since they are - needed by the runtime system to run correctly. */ - + needed by the runtime system to run correctly. */ void __objc_linking (void) { diff --git a/libobjc/memory.c b/libobjc/memory.c index a0d6e130ad9..458d2566fcb 100644 --- a/libobjc/memory.c +++ b/libobjc/memory.c @@ -42,8 +42,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see #define __USE_FIXED_PROTOTYPES__ #include <stdlib.h> -#include "objc/objc.h" -#include "objc/objc-api.h" +#include "objc/runtime.h" #if OBJC_WITH_GC #include <gc.h> diff --git a/libobjc/objc-private/hash.h b/libobjc/objc-private/hash.h index 7c57a4d2589..ba4c4943438 100644 --- a/libobjc/objc-private/hash.h +++ b/libobjc/objc-private/hash.h @@ -104,9 +104,6 @@ typedef struct cache } *cache_ptr; -/* Two important hash tables. */ -extern cache_ptr module_hash_table, class_hash_table; - /* Allocate and initialize a hash table. */ cache_ptr objc_hash_new (unsigned int size, diff --git a/libobjc/objc-private/module-abi-8.h b/libobjc/objc-private/module-abi-8.h index a20e3a3ae6e..414e5e354ec 100644 --- a/libobjc/objc-private/module-abi-8.h +++ b/libobjc/objc-private/module-abi-8.h @@ -138,6 +138,24 @@ struct objc_method_list structure. */ }; +/* Currently defined in Protocol.m (that definition should go away + once we include this file). */ +struct objc_method_description_list +{ + int count; + struct objc_method_description list[1]; +}; + +/* Currently defined by objc/objc.h. */ +/* +struct objc_protocol { + struct objc_class* class_pointer; + char *protocol_name; + struct objc_protocol_list *protocol_list; + struct objc_method_description_list *instance_methods, *class_methods; +}; +*/ + struct objc_protocol_list { struct objc_protocol_list *next; @@ -155,6 +173,7 @@ struct objc_protocol_list some members change type. The compiler generates "char* const" and places a string in the following member variables: super_class. */ +#ifndef __objc_STRUCT_OBJC_CLASS_defined struct objc_class { struct objc_class* class_pointer; /* Pointer to the class's meta class. */ @@ -164,7 +183,7 @@ struct objc_class { const char* name; /* Name of the class. */ long version; /* Unknown. */ unsigned long info; /* Bit mask. See class masks - defined above. */ + defined below. */ long instance_size; /* Size in bytes of the class. The sum of the class definition and all super @@ -197,6 +216,46 @@ struct objc_class { struct objc_protocol_list *protocols; /* Protocols conformed to */ void* gc_object_type; }; +#endif /* __objc_STRUCT_OBJC_CLASS_defined */ + +/* This is used to assure consistent access to the info field of + classes. */ +#ifndef HOST_BITS_PER_LONG +# define HOST_BITS_PER_LONG (sizeof(long)*8) +#endif + +#define __CLS_INFO(cls) ((cls)->info) +#define __CLS_ISINFO(cls, mask) ((__CLS_INFO(cls)&mask)==mask) +#define __CLS_SETINFO(cls, mask) (__CLS_INFO(cls) |= mask) + +/* The structure is of type MetaClass */ +#define _CLS_META 0x2L +#define CLS_ISMETA(cls) ((cls)&&__CLS_ISINFO(cls, _CLS_META)) + +/* The structure is of type Class */ +#define _CLS_CLASS 0x1L +#define CLS_ISCLASS(cls) ((cls)&&__CLS_ISINFO(cls, _CLS_CLASS)) + +/* The class is initialized within the runtime. This means that it + has had correct super and sublinks assigned. */ +#define _CLS_RESOLV 0x8L +#define CLS_ISRESOLV(cls) __CLS_ISINFO(cls, _CLS_RESOLV) +#define CLS_SETRESOLV(cls) __CLS_SETINFO(cls, _CLS_RESOLV) + +/* The class has been send a +initialize message or a such is not + defined for this class. */ +#define _CLS_INITIALIZED 0x04L +#define CLS_ISINITIALIZED(cls) __CLS_ISINFO(cls, _CLS_INITIALIZED) +#define CLS_SETINITIALIZED(cls) __CLS_SETINFO(cls, _CLS_INITIALIZED) + +/* The class number of this class. This must be the same for both the + class and its meta class object. */ +#define CLS_GETNUMBER(cls) (__CLS_INFO(cls) >> (HOST_BITS_PER_LONG/2)) +#define CLS_SETNUMBER(cls, num) \ + ({ (cls)->info <<= (HOST_BITS_PER_LONG/2); \ + (cls)->info >>= (HOST_BITS_PER_LONG/2); \ + __CLS_SETINFO(cls, (((unsigned long)num) << (HOST_BITS_PER_LONG/2))); }) + /* The compiler generates one of these structures for each category. A class may have many categories and contain both instance and diff --git a/libobjc/objc-private/protocols.h b/libobjc/objc-private/protocols.h new file mode 100644 index 00000000000..49a2d92648f --- /dev/null +++ b/libobjc/objc-private/protocols.h @@ -0,0 +1,46 @@ +/* GNU Objective C Runtime protocols - Private functions + Copyright (C) 2010 Free Software Foundation, Inc. + Contributed by Nicola Pero <nicola.pero@meta-innovation.com> + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it under the +terms of the GNU General Public License as published by the Free Software +Foundation; either version 3, or (at your option) any later version. + +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +details. + +Under Section 7 of GPL version 3, you are granted additional +permissions described in the GCC Runtime Library Exception, version +3.1, as published by the Free Software Foundation. + +You should have received a copy of the GNU General Public License and +a copy of the GCC Runtime Library Exception along with this program; +see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +<http://www.gnu.org/licenses/>. */ + +#ifndef __objc_private_protocols_INCLUDE_GNU +#define __objc_private_protocols_INCLUDE_GNU + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* This function needs to be called at startup by init.c. */ +void +__objc_protocols_init (void); + +/* This function adds a protocol to the internal hashtable of + protocols by name, which allows objc_getProtocol(name) to be + implemented efficiently. */ +void +__objc_protocols_add_protocol (const char *name, Protocol *object); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* not __objc_private_protocols_INCLUDE_GNU */ diff --git a/libobjc/objc-private/runtime.h b/libobjc/objc-private/runtime.h index 690427ed5a3..b7e75ae4304 100644 --- a/libobjc/objc-private/runtime.h +++ b/libobjc/objc-private/runtime.h @@ -34,7 +34,8 @@ The original list was: but can almost certainly be shrinked down. -*/ +Note that you can use this file both with objc/objc-api.h and with +objc/runtime.h. */ #ifndef __objc_private_runtime_INCLUDE_GNU #define __objc_private_runtime_INCLUDE_GNU @@ -58,18 +59,18 @@ extern void __objc_init_dispatch_tables(void); /* (objc-dispatch.c) */ extern void __objc_install_premature_dtable(Class); /* (objc-dispatch.c) */ extern void __objc_resolve_class_links(void); /* (objc-class.c) */ extern void __objc_register_selectors_from_class(Class); /* (objc-sel.c) */ -extern void __objc_register_selectors_from_list (MethodList_t); /* (selector.c) */ +extern void __objc_register_selectors_from_list (struct objc_method_list *); /* (selector.c) */ extern void __objc_update_dispatch_table_for_class (Class);/* (objc-msg.c) */ extern int __objc_init_thread_system(void); /* thread.c */ extern int __objc_fini_thread_system(void); /* thread.c */ extern void __objc_print_dtable_stats(void); /* sendmsg.c */ -extern void class_add_method_list(Class, MethodList_t); +extern void class_add_method_list(Class, struct objc_method_list *); /* Registering instance methods as class methods for root classes */ extern void __objc_register_instance_methods_to_class(Class); -extern Method_t search_for_method_in_list(MethodList_t list, SEL op); +extern struct objc_method * search_for_method_in_list(struct objc_method_list * list, SEL op); /* True when class links has been resolved */ extern BOOL __objc_class_links_resolved; diff --git a/libobjc/objc-sync.c b/libobjc/objc-sync.c index 97349e64029..d01707ca659 100644 --- a/libobjc/objc-sync.c +++ b/libobjc/objc-sync.c @@ -79,7 +79,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see #include "objc-private/common.h" #include "objc/objc-sync.h" /* For objc_sync_enter(), objc_sync_exit() */ -#include "objc/objc-api.h" /* For objc_malloc() */ +#include "objc/runtime.h" /* For objc_malloc() */ #include "objc/thr.h" /* For objc_mutex_loc() and similar */ #include "objc-private/objc-sync.h" /* For __objc_sync_init() */ diff --git a/libobjc/objc/deprecated/hash.h b/libobjc/objc/deprecated/hash.h index 52ee8c31345..8b718a4417d 100644 --- a/libobjc/objc/deprecated/hash.h +++ b/libobjc/objc/deprecated/hash.h @@ -104,9 +104,6 @@ typedef struct cache } *cache_ptr; -/* Two important hash tables. */ -extern cache_ptr module_hash_table, class_hash_table; - /* Allocate and initialize a hash table. */ cache_ptr objc_hash_new (unsigned int size, diff --git a/libobjc/objc/deprecated/struct_objc_class.h b/libobjc/objc/deprecated/struct_objc_class.h index 5a4859cbd65..07927feb69d 100644 --- a/libobjc/objc/deprecated/struct_objc_class.h +++ b/libobjc/objc/deprecated/struct_objc_class.h @@ -1,4 +1,5 @@ /* This structure used to be public, but is now private to the runtime. */ +#define __objc_STRUCT_OBJC_CLASS_defined /* ** The compiler generates one of these structures for each class. diff --git a/libobjc/objc/objc-decls.h b/libobjc/objc/objc-decls.h index e5388e33c4c..b3cfb2120f2 100644 --- a/libobjc/objc/objc-decls.h +++ b/libobjc/objc/objc-decls.h @@ -28,13 +28,13 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see #if defined (_WIN32) || defined (__WIN32__) || defined (WIN32) -# ifdef DLL_EXPORT /* defined by libtool (if required) */ -# define objc_EXPORT -# define objc_DECLARE -#else -# define objc_EXPORT extern __declspec(dllimport) -# define objc_DECLARE extern __declspec(dllimport) -#endif +# ifdef DLL_EXPORT /* defined by libtool (if required) */ +# define objc_EXPORT +# define objc_DECLARE +# else +# define objc_EXPORT extern __declspec(dllimport) +# define objc_DECLARE extern __declspec(dllimport) +# endif #else diff --git a/libobjc/objc/runtime.h b/libobjc/objc/runtime.h index b15c522235d..a52c7611857 100644 --- a/libobjc/objc/runtime.h +++ b/libobjc/objc/runtime.h @@ -48,6 +48,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see /* TODO: This file is incomplete. */ #include "objc.h" +#include "objc-decls.h" /* An 'Ivar' represents an instance variable. It holds information about the name, type and offset of the instance variable. */ @@ -168,7 +169,8 @@ object_getClass (id object) /** Implementation: the following functions are in selector.c. */ -/* Return the name of a given selector. */ +/* Return the name of a given selector. If 'selector' is NULL, return + "<null selector>". */ objc_EXPORT const char *sel_getName (SEL selector); /* Return the type of a given selector. @@ -237,6 +239,14 @@ objc_EXPORT Class object_setClass (id object, Class class_); reuse the returned Ivar if you can. */ objc_EXPORT Ivar class_getInstanceVariable (Class class_, const char *name); +/* Return a class variable given the class and the class variable + name. This is an expensive function to call, so try to reuse the + returned Ivar if you can. + + This function always returns NULL since class variables are + currently unavailable in Objective-C. */ +objc_EXPORT Ivar class_getClassVariable (Class class_, const char *name); + /* If the object was created in class_createInstance() with some extraBytes, returns a pointer to them. If it was not, then the returned pointer may make no sense. */ @@ -355,6 +365,180 @@ objc_EXPORT int objc_getClassList (Class *returnValue, int maxNumberOfClassesToR the documentation is unclear on what they are supposed to do, and the GNU Objective-C Runtime currently does not provide them. */ +/* Return the name of the class 'class_', or the string "nil" if the + class_ is Nil. */ +objc_EXPORT const char * class_getName (Class class_); + +/* Return YES if 'class_' is a meta class, and NO if not. If 'class_' + is Nil, return NO. */ +objc_EXPORT BOOL class_isMetaClass (Class class_); + +/* Return the superclass of 'class_'. If 'class_' is Nil, or it is a root + class, return Nil. + + TODO: It may be worth to define this inline, since it is usually + used in loops when traversing the class hierarchy. */ +objc_EXPORT Class class_getSuperclass (Class class_); + +/* Return the 'version' number of the class, which is an integer that + can be used to track changes in the class API, methods and + variables. If class_ is Nil, return 0. If class_ is not Nil, the + version is 0 unless class_setVersion() has been called to set a + different one. + + Please note that internally the version is a long, but the API only + allows you to set and retrieve int values. */ +objc_EXPORT int class_getVersion (Class class_); + +/* Set the 'version' number of the class, which is an integer that can + be used to track changes in the class API, methods and variables. + If 'class_' is Nil, does nothing. + + This is typically used internally by "Foundation" libraries such as + GNUstep Base to support serialization / deserialization of objects + that work across changes in the classes. If you are using such a + library, you probably want to use their versioning API, which may + be based on this one, but is integrated with the rest of the + library. + + Please note that internally the version is a long, but the API only + allows you to set and retrieve int values. */ +objc_EXPORT void class_setVersion (Class class_, int version); + +/* Return the size in bytes (a byte is the size of a char) of an + instance of the class. If class_ is Nil, return 0; else it return + a non-zero number (since the 'isa' instance variable is required + for all classes). */ +objc_EXPORT size_t class_getInstanceSize (Class class_); + + +/** Implementation: the following functions are in protocols.c. */ + +/* Return the protocol with name 'name', or nil if it the protocol is + not known to the runtime. */ +objc_EXPORT Protocol *objc_getProtocol (const char *name); + +/* Return all the protocols known to the runtime. The return value of + the function is a pointer to an area, allocated with malloc(), that + contains all the protocols known to the runtime; the list is + terminated by NULL. You should free this area using free() once + you no longer need it. Optionally, if you pass a non-NULL + 'numberOfReturnedProtocols' pointer, the unsigned int that it + points to will be filled with the number of protocols returned. If + there are no protocols known to the runtime, NULL is returned. */ +objc_EXPORT Protocol **objc_copyProtocolList (unsigned int *numberOfReturnedProtocols); + +/* Add a protocol to a class, and return YES if it was done + succesfully, and NO if not. At the moment, NO should only happen + if class_ or protocol are nil, if the protocol is not a Protocol + object or if the class already conforms to the protocol. */ +objc_EXPORT BOOL class_addProtocol (Class class_, Protocol *protocol); + +/* Return YES if the class 'class_' conforms to Protocol 'protocol', + and NO if not. */ +objc_EXPORT BOOL class_conformsToProtocol (Class class_, Protocol *protocol); + +/* Return all the protocols that the class conforms to. The return + value of the function is a pointer to an area, allocated with + malloc(), that contains all the protocols formally adopted by the + class. It does not include protocols adopted by superclasses. The + list is terminated by NULL. Optionally, if you pass a non-NULL + 'numberOfReturnedProtocols' pointer, the unsigned int that it + points to will be filled with the number of protocols returned. */ +objc_EXPORT Protocol **class_copyProtocolList (Class class_, unsigned int *numberOfReturnedProtocols); + +/* Return YES if protocol 'protocol' conforms to protocol + 'anotherProtocol', and NO if not. Note that if one of the two + protocols is nil, it returns NO. */ +objc_EXPORT BOOL protocol_conformsToProtocol (Protocol *protocol, Protocol *anotherProtocol); + +/* Return YES if protocol 'protocol' is the same as protocol + 'anotherProtocol', and 'NO' if not. Note that it returns YES if + the two protocols are both nil. */ +objc_EXPORT BOOL protocol_isEqual (Protocol *protocol, Protocol *anotherProtocol); + +/* Return the name of protocol 'protocol'. If 'protocol' is nil or is + not a Protocol, return NULL. */ +objc_EXPORT const char *protocol_getName (Protocol *protocol); + +/* Return the method description for the method with selector + 'selector' in protocol 'protocol'; if 'requiredMethod' is YES, the + function searches the list of required methods; if NO, the list of + optional methods. If 'instanceMethod' is YES, the function search + for an instance method; if NO, for a class method. If there is no + matching method, an objc_method_description structure with both + name and types set to NULL is returned. This function will only + find methods that are directly declared in the protocol itself, not + in other protocols that this protocol adopts. + + Note that the traditional ABI does not store the list of optional + methods of a protocol in a compiled module, so the traditional ABI + will always return (NULL, NULL) when requiredMethod == NO. */ +objc_EXPORT struct objc_method_description protocol_getMethodDescription (Protocol *protocol, + SEL selector, + BOOL requiredMethod, + BOOL instanceMethod); + +/* Return the method descriptions of all the methods of the protocol. + The return value of the function is a pointer to an area, allocated + with malloc(), that contains all the method descriptions of the + methods of the protocol. It does not recursively include methods + of the protocols adopted by this protocol. The list is terminated + by a NULL objc_method_description (one with both fields set to + NULL). Optionally, if you pass a non-NULL + 'numberOfReturnedMethods' pointer, the unsigned int that it points + to will be filled with the number of properties returned. + + Note that the traditional ABI does not store the list of optional + methods of a protocol in a compiled module, so the traditional ABI + will always return an empty list if requiredMethod is set to + NO. */ +objc_EXPORT struct objc_method_description *protocol_copyMethodDescriptionList (Protocol *protocol, + BOOL requiredMethod, + BOOL instanceMethod, + unsigned int *numberOfReturnedMethods); + +/* Return the property with name 'propertyName' of the protocol + 'protocol'. If 'requiredProperty' is YES, the function searches + the list of required properties; if NO, the list of optional + properties. If 'instanceProperty' is YES, the function searches + the list of instance properties; if NO, the list of class + properties. At the moment, optional properties and class + properties are not part of the Objective-C language, so both + 'requiredProperty' and 'instanceProperty' should be set to YES. + This function returns NULL if the required property can not be + found. + + Note that the traditional ABI does not store the list of properties + of a protocol in a compiled module, so the traditional ABI will + always return NULL. */ +objc_EXPORT Property protocol_getProperty (Protocol *protocol, const char *propertyName, + BOOL requiredProperty, BOOL instanceProperty); + +/* Return all the properties of the protocol. The return value of the + function is a pointer to an area, allocated with malloc(), that + contains all the properties of the protocol. It does not + recursively include properties of the protocols adopted by this + protocol. The list is terminated by NULL. Optionally, if you pass + a non-NULL 'numberOfReturnedProperties' pointer, the unsigned int + that it points to will be filled with the number of properties + returned. + + Note that the traditional ABI does not store the list of properties + of a protocol in a compiled module, so the traditional ABI will + always return NULL and store 0 in numberOfReturnedProperties. */ +objc_EXPORT Property *protocol_copyPropertyList (Protocol *protocol, unsigned int *numberOfReturnedProperties); + +/* Return all the protocols that the protocol conforms to. The return + value of the function is a pointer to an area, allocated with + malloc(), that contains all the protocols formally adopted by the + protocol. It does not recursively include protocols adopted by the + protocols adopted by this protocol. The list is terminated by + NULL. Optionally, if you pass a non-NULL + 'numberOfReturnedProtocols' pointer, the unsigned int that it + points to will be filled with the number of protocols returned. */ +objc_EXPORT Protocol **protocol_copyProtocolList (Protocol *protocol, unsigned int *numberOfReturnedProtocols); + /* TODO: Add all the other functions in the API. */ @@ -410,11 +594,38 @@ struct __objcFastEnumerationState */ +/** Implementation: the following functions are in memory.c. */ + +/* Traditional GNU Objective-C Runtime functions that are used for + memory allocation and disposal. These functions are used in the + same way as you use malloc, realloc, calloc and free and make sure + that memory allocation works properly with the garbage + collector. + + Compatibility Note: these functions are not available with the + Apple/NeXT runtime. */ + +objc_EXPORT void *objc_malloc(size_t size); + +/* FIXME: Shouldn't the following be called objc_malloc_atomic ? The + GC function is GC_malloc_atomic() which makes sense. + */ +objc_EXPORT void *objc_atomic_malloc(size_t size); + +objc_EXPORT void *objc_realloc(void *mem, size_t size); + +objc_EXPORT void *objc_calloc(size_t nelem, size_t size); + +objc_EXPORT void objc_free(void *mem); + + /** Implementation: the following functions are in encoding.c. */ /* Traditional GNU Objective-C Runtime functions that are currently used to implement method forwarding. -*/ + + Compatibility Note: these functions are not available with the + Apple/NeXT runtime. */ /* Return the size of a variable which has the specified 'type' encoding. */ diff --git a/libobjc/objects.c b/libobjc/objects.c index 2562be55f24..71b09afee56 100644 --- a/libobjc/objects.c +++ b/libobjc/objects.c @@ -23,11 +23,12 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see <http://www.gnu.org/licenses/>. */ #include "objc-private/common.h" -#include "objc/objc.h" -#include "objc/objc-api.h" -#include "objc-private/runtime.h" /* the kitchen sink */ +#include "objc/runtime.h" +#include "objc/thr.h" /* Required by objc-private/runtime.h. */ +#include "objc-private/module-abi-8.h" /* For CLS_ISCLASS and similar. */ +#include "objc-private/runtime.h" /* the kitchen sink */ -#include <string.h> /* For memcpy() */ +#include <string.h> /* For memcpy() */ #if OBJC_WITH_GC # include <gc.h> diff --git a/libobjc/protocols.c b/libobjc/protocols.c new file mode 100644 index 00000000000..6d429803c8f --- /dev/null +++ b/libobjc/protocols.c @@ -0,0 +1,549 @@ +/* GNU Objective C Runtime protocol related functions. + Copyright (C) 2010 Free Software Foundation, Inc. + Contributed by Nicola Pero + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it under the +terms of the GNU General Public License as published by the Free Software +Foundation; either version 3, or (at your option) any later version. + +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +details. + +Under Section 7 of GPL version 3, you are granted additional +permissions described in the GCC Runtime Library Exception, version +3.1, as published by the Free Software Foundation. + +You should have received a copy of the GNU General Public License and +a copy of the GCC Runtime Library Exception along with this program; +see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +<http://www.gnu.org/licenses/>. */ + +#include "objc-private/common.h" +#include "objc/runtime.h" +#include "objc-private/module-abi-8.h" /* For runtime structures */ +#include "objc/thr.h" +#include "objc-private/runtime.h" /* the kitchen sink */ +#include "objc-private/hash.h" /* For the hash table of protocols. */ +#include "objc-private/protocols.h" /* For __objc_protocols_init() and __objc_protocols_add_protocol() */ + +/* This is a table that maps a name to a Protocol instance with that + name. Because there may be multiple Protocol instances with the + same name (no harm in that) the table records only one + instance. */ +static cache_ptr __protocols_hashtable; + +/* A mutex protecting the protocol_hashtable. */ +static objc_mutex_t __protocols_hashtable_lock = NULL; + +/* Called at startup by init.c. */ +void +__objc_protocols_init (void) +{ + __protocols_hashtable_lock = objc_mutex_allocate (); + + /* The keys in the table are strings, and the values are Protocol + objects. */ + __protocols_hashtable = objc_hash_new (64, (hash_func_type) objc_hash_string, + (compare_func_type) objc_compare_strings); +} + +/* Add a protocol to the hashtable. */ +void +__objc_protocols_add_protocol (const char *name, Protocol *object) +{ + objc_mutex_lock (__protocols_hashtable_lock); + + /* If we find a protocol with the same name already in the + hashtable, we do not need to add the new one, because it will be + identical to it. This in the reasonable assumption that two + protocols with the same name are identical, which is expected in + any sane program. If we are really paranoid, we would compare + the protocols and abort if they are not identical. + Unfortunately, this would slow down the startup of all + Objective-C programs while trying to catch a problem that has + never been seen in practice, so we don't do it. */ + if (! objc_hash_is_key_in_hash (__protocols_hashtable, name)) + { + objc_hash_add (&__protocols_hashtable, name, object); + } + + objc_mutex_unlock (__protocols_hashtable_lock); +} + +Protocol * +objc_getProtocol (const char *name) +{ + Protocol *protocol; + + if (name == NULL) + return NULL; + + objc_mutex_lock (__protocols_hashtable_lock); + protocol = (Protocol *)(objc_hash_value_for_key (__protocols_hashtable, name)); + objc_mutex_unlock (__protocols_hashtable_lock); + + return protocol; +} + +Protocol ** +objc_copyProtocolList (unsigned int *numberOfReturnedProtocols) +{ + unsigned int count = 0; + Protocol **returnValue = NULL; + node_ptr node; + + objc_mutex_lock (__protocols_hashtable_lock); + + /* Count how many protocols we have. */ + node = objc_hash_next (__protocols_hashtable, NULL); + while (node) + { + count++; + node = objc_hash_next (__protocols_hashtable, node); + } + + if (count != 0) + { + unsigned int i = 0; + + /* Allocate enough memory to hold them. */ + returnValue = (Protocol **)(malloc (sizeof (Protocol *) * (count + 1))); + + /* Copy the protocols. */ + node = objc_hash_next (__protocols_hashtable, NULL); + while (node) + { + returnValue[i] = node->value; + i++; + node = objc_hash_next (__protocols_hashtable, node); + } + + returnValue[i] = NULL; + } + objc_mutex_unlock (__protocols_hashtable_lock); + + if (numberOfReturnedProtocols) + *numberOfReturnedProtocols = count; + + return returnValue; +} + +BOOL +class_addProtocol (Class class_, Protocol *protocol) +{ + struct objc_protocol_list *protocols; + + if (class_ == Nil || protocol == NULL) + return NO; + + if (class_conformsToProtocol (class_, protocol)) + return NO; + + /* Check that it is a Protocol object before casting it to (struct + objc_protocol *). */ + if (protocol->class_pointer != objc_lookupClass ("Protocol")) + return NO; + + objc_mutex_lock (__objc_runtime_mutex); + + /* Create the objc_protocol_list. */ + protocols = malloc (sizeof (struct objc_protocol_list)); + protocols->count = 1; + protocols->list[0] = protocol; + + /* Attach it to the list of class protocols. */ + protocols->next = class_->protocols; + class_->protocols = protocols; + + objc_mutex_unlock (__objc_runtime_mutex); + + return YES; +} + +BOOL +class_conformsToProtocol (Class class_, Protocol *protocol) +{ + struct objc_protocol_list* proto_list; + + if (class_ == Nil || protocol == NULL) + return NO; + + /* Check that it is a Protocol object before casting it to (struct + objc_protocol *). */ + if (protocol->class_pointer != objc_lookupClass ("Protocol")) + return NO; + + /* Acquire the runtime lock because the list of protocols for a + class may be modified concurrently, for example if another thread + calls class_addProtocol(), or dynamically loads from a file a + category of the class. */ + objc_mutex_lock (__objc_runtime_mutex); + proto_list = class_->protocols; + + while (proto_list) + { + size_t i; + for (i = 0; i < proto_list->count; i++) + { + if (proto_list->list[i] == protocol + || protocol_conformsToProtocol (proto_list->list[i], + protocol)) + { + objc_mutex_unlock (__objc_runtime_mutex); + return YES; + } + } + proto_list = proto_list->next; + } + + objc_mutex_unlock (__objc_runtime_mutex); + return NO; +} + +Protocol ** +class_copyProtocolList (Class class_, unsigned int *numberOfReturnedProtocols) +{ + unsigned int count = 0; + Protocol **returnValue = NULL; + struct objc_protocol_list* proto_list; + + /* Lock the runtime mutex because the class protocols may be + concurrently modified. */ + objc_mutex_lock (__objc_runtime_mutex); + + /* Count how many protocols we have. */ + proto_list = class_->protocols; + + while (proto_list) + { + count = count + proto_list->count; + proto_list = proto_list->next; + } + + if (count != 0) + { + unsigned int i = 0; + + /* Allocate enough memory to hold them. */ + returnValue = (Protocol **)(malloc (sizeof (Protocol *) * (count + 1))); + + /* Copy the protocols. */ + proto_list = class_->protocols; + + while (proto_list) + { + size_t j; + for (j = 0; j < proto_list->count; j++) + { + returnValue[i] = proto_list->list[j]; + i++; + } + proto_list = proto_list->next; + } + + returnValue[i] = NULL; + } + objc_mutex_unlock (__objc_runtime_mutex); + + if (numberOfReturnedProtocols) + *numberOfReturnedProtocols = count; + + return returnValue; +} + +BOOL +protocol_conformsToProtocol (Protocol *protocol, Protocol *anotherProtocol) +{ + struct objc_protocol_list* proto_list; + + if (protocol == NULL || anotherProtocol == NULL) + return NO; + + if (protocol == anotherProtocol) + return YES; + + /* Check that the objects are Protocol objects before casting them + to (struct objc_protocol *). */ + if (protocol->class_pointer != anotherProtocol->class_pointer) + return NO; + + if (protocol->class_pointer != objc_lookupClass ("Protocol")) + return NO; + + if (strcmp (((struct objc_protocol *)protocol)->protocol_name, + ((struct objc_protocol *)anotherProtocol)->protocol_name) == 0) + return YES; + + /* We do not acquire any lock because protocols are currently + immutable. We can freely iterate over a protocol structure. */ + proto_list = ((struct objc_protocol *)protocol)->protocol_list; + while (proto_list) + { + size_t i; + + for (i = 0; i < proto_list->count; i++) + { + if (protocol_conformsToProtocol (proto_list->list[i], anotherProtocol)) + return YES; + } + proto_list = proto_list->next; + } + + return NO; +} + +BOOL +protocol_isEqual (Protocol *protocol, Protocol *anotherProtocol) +{ + if (protocol == anotherProtocol) + return YES; + + if (protocol == NULL || anotherProtocol == NULL) + return NO; + + /* Check that the objects are Protocol objects before casting them + to (struct objc_protocol *). */ + if (protocol->class_pointer != anotherProtocol->class_pointer) + return NO; + + if (protocol->class_pointer != objc_lookupClass ("Protocol")) + return NO; + + /* Equality between formal protocols is only formal (nothing to do + with actually checking the list of methods they have!). Two + formal Protocols are equal if and only if they have the same + name. + + Please note (for comparisons with other implementations) that + checking the names is equivalent to checking that Protocol A + conforms to Protocol B and Protocol B conforms to Protocol A, + because this happens iff they have the same name. If they have + different names, A conforms to B if and only if A includes B, but + the situation where A includes B and B includes A is a circular + dependency between Protocols which is forbidden by the compiler, + so A conforms to B and B conforms to A with A and B having + different names is an impossible case. */ + if (strcmp (((struct objc_protocol *)protocol)->protocol_name, + ((struct objc_protocol *)anotherProtocol)->protocol_name) == 0) + return YES; + + return NO; +} + +const char * +protocol_getName (Protocol *protocol) +{ + /* Check that it is a Protocol object before casting it to (struct + objc_protocol *). */ + if (protocol->class_pointer != objc_lookupClass ("Protocol")) + return NULL; + + return ((struct objc_protocol *)protocol)->protocol_name; +} + +struct objc_method_description protocol_getMethodDescription (Protocol *protocol, + SEL selector, + BOOL requiredMethod, + BOOL instanceMethod) +{ + struct objc_method_description no_result = { NULL, NULL }; + const char* selector_name; + struct objc_method_description_list *methods; + int i; + + /* TODO: New ABI. */ + /* The current ABI does not have any information on optional protocol methods. */ + if (! requiredMethod) + return no_result; + + /* Check that it is a Protocol object before casting it to (struct + objc_protocol *). */ + if (protocol->class_pointer != objc_lookupClass ("Protocol")) + return no_result; + + selector_name = sel_getName (selector); + + if (instanceMethod) + methods = ((struct objc_protocol *)protocol)->instance_methods; + else + methods = ((struct objc_protocol *)protocol)->class_methods; + + if (methods) + { + for (i = 0; i < methods->count; i++) + { + if (strcmp ((char*)(methods->list[i].name), selector_name) == 0) + return methods->list[i]; + } + } + + return no_result; +} + +struct objc_method_description *protocol_copyMethodDescriptionList (Protocol *protocol, + BOOL requiredMethod, + BOOL instanceMethod, + unsigned int *numberOfReturnedMethods) +{ + struct objc_method_description_list *methods; + unsigned int count = 0; + struct objc_method_description *returnValue = NULL; + + /* TODO: New ABI */ + /* The current ABI does not have any information on optional protocol methods. */ + if (! requiredMethod) + { + if (numberOfReturnedMethods) + *numberOfReturnedMethods = 0; + + return NULL; + } + + /* Check that it is a Protocol object before casting it to (struct + objc_protocol *). */ + if (protocol == NULL || protocol->class_pointer != objc_lookupClass ("Protocol")) + { + if (numberOfReturnedMethods) + *numberOfReturnedMethods = 0; + + return NULL; + } + + /* We do not acquire any lock because protocols are currently + immutable. We can freely iterate over a protocol structure. */ + + if (instanceMethod) + methods = ((struct objc_protocol *)protocol)->instance_methods; + else + methods = ((struct objc_protocol *)protocol)->class_methods; + + if (methods) + { + unsigned int i; + count = methods->count; + + /* Allocate enough memory to hold them. */ + returnValue = (struct objc_method_description *)(malloc (sizeof (struct objc_method_description) * (count + 1))); + + /* Copy them. */ + for (i = 0; i < count; i++) + { + returnValue[i].name = methods->list[i].name; + returnValue[i].types = methods->list[i].types; + } + returnValue[i].name = NULL; + returnValue[i].types = NULL; + } + + if (numberOfReturnedMethods) + *numberOfReturnedMethods = count; + + return returnValue; +} + +Property protocol_getProperty (Protocol *protocol, const char *propertyName, + BOOL requiredProperty, BOOL instanceProperty) +{ + if (protocol == NULL || propertyName == NULL) + return NULL; + + if (!requiredProperty || !instanceProperty) + return NULL; + + /* Check that it is a Protocol object before casting it to (struct + objc_protocol *). */ + if (protocol->class_pointer != objc_lookupClass ("Protocol")) + return NULL; + + /* TODO: New ABI. */ + /* The current ABI does not have any information on protocol properties. */ + return NULL; +} + +Property *protocol_copyPropertyList (Protocol *protocol, unsigned int *numberOfReturnedProperties) +{ + unsigned int count = 0; + Property *returnValue = NULL; + + /* Check that it is a Protocol object before casting it to (struct + objc_protocol *). */ + if (protocol == NULL || protocol->class_pointer != objc_lookupClass ("Protocol")) + { + if (numberOfReturnedProperties) + *numberOfReturnedProperties = 0; + + return NULL; + } + + /* We do not acquire any lock because protocols are currently + immutable. We can freely iterate over a protocol structure. */ + + /* TODO: New ABI. */ + /* The current ABI does not have any information on protocol properties. */ + if (numberOfReturnedProperties) + *numberOfReturnedProperties = count; + + return returnValue; +} + +Protocol **protocol_copyProtocolList (Protocol *protocol, unsigned int *numberOfReturnedProtocols) +{ + unsigned int count = 0; + Protocol **returnValue = NULL; + struct objc_protocol_list* proto_list; + + /* Check that it is a Protocol object before casting it to (struct + objc_protocol *). */ + if (protocol == NULL || protocol->class_pointer != objc_lookupClass ("Protocol")) + { + if (numberOfReturnedProtocols) + *numberOfReturnedProtocols = 0; + + return NULL; + } + + /* We do not acquire any lock because protocols are currently + immutable. We can freely iterate over a protocol structure. */ + + /* Count how many protocols we have. */ + proto_list = ((struct objc_protocol *)protocol)->protocol_list; + + while (proto_list) + { + count = count + proto_list->count; + proto_list = proto_list->next; + } + + if (count != 0) + { + unsigned int i = 0; + + /* Allocate enough memory to hold them. */ + returnValue = (Protocol **)(malloc (sizeof (Protocol *) * (count + 1))); + + /* Copy the protocols. */ + proto_list = ((struct objc_protocol *)protocol)->protocol_list; + + while (proto_list) + { + size_t j; + for (j = 0; j < proto_list->count; j++) + { + returnValue[i] = proto_list->list[j]; + i++; + } + proto_list = proto_list->next; + } + + returnValue[i] = NULL; + } + + if (numberOfReturnedProtocols) + *numberOfReturnedProtocols = count; + + return returnValue; +} diff --git a/libobjc/sarray.c b/libobjc/sarray.c index 8d5303701e0..9dd160e51eb 100644 --- a/libobjc/sarray.c +++ b/libobjc/sarray.c @@ -24,9 +24,8 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see #include "objc-private/common.h" #include "objc-private/sarray.h" -#include "objc/objc.h" -#include "objc/objc-api.h" -#include "objc/thr.h" +#include "objc/runtime.h" /* For objc_malloc */ +#include "objc/thr.h" /* For objc_mutex_lock */ #include "objc-private/runtime.h" #include <stdio.h> #include <string.h> /* For memset */ diff --git a/libobjc/selector.c b/libobjc/selector.c index 93952fd3834..1d4bc7e69d7 100644 --- a/libobjc/selector.c +++ b/libobjc/selector.c @@ -23,7 +23,6 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see <http://www.gnu.org/licenses/>. */ #include "objc-private/common.h" -#include "objc/objc.h" #include "objc/objc-api.h" #include "objc/thr.h" #include "objc-private/hash.h" @@ -163,6 +162,14 @@ void __objc_register_instance_methods_to_class (Class class) __objc_update_dispatch_table_for_class (class->class_pointer); } +BOOL +sel_isEqual (SEL s1, SEL s2) +{ + if (s1 == 0 || s2 == 0) + return s1 == s2; + else + return s1->sel_id == s2->sel_id; +} /* Returns YES iff t1 and t2 have same method types, but we ignore the argframe layout */ @@ -293,6 +300,9 @@ const char *sel_getName (SEL selector) { const char *ret; + if (selector == NULL) + return "<null selector>"; + objc_mutex_lock (__objc_runtime_mutex); if ((soffset_decode ((sidx)selector->sel_id) > 0) && (soffset_decode ((sidx)selector->sel_id) <= __objc_selector_max_index)) @@ -306,6 +316,9 @@ const char *sel_getName (SEL selector) /* Traditional GNU Objective-C Runtime API. */ const char *sel_get_name (SEL selector) { + if (selector == NULL) + return 0; + return sel_getName (selector); } diff --git a/libobjc/sendmsg.c b/libobjc/sendmsg.c index a822af4a31a..02be39c5b05 100644 --- a/libobjc/sendmsg.c +++ b/libobjc/sendmsg.c @@ -33,7 +33,6 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see #include "tconfig.h" #include "coretypes.h" #include "tm.h" -#include "objc/objc.h" #include "objc/objc-api.h" #include "objc/thr.h" #include "objc-private/runtime.h" diff --git a/libobjc/thr.c b/libobjc/thr.c index 50196e81c58..609872d3d17 100644 --- a/libobjc/thr.c +++ b/libobjc/thr.c @@ -38,8 +38,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see #include "tm.h" #include "defaults.h" #include "objc/thr.h" -#include "objc/objc.h" -#include "objc/objc-api.h" +#include "objc/runtime.h" #include "objc-private/runtime.h" #include <gthr.h> |