Patchwork =?UTF-8?Q?libobjc=20-=20more=20work=20on=20headers=20(3)?=

login
register
mail settings
Submitter Nicola Pero
Date Oct. 10, 2010, 11:29 p.m.
Message ID <1286753363.153226768@192.168.2.229>
Download mbox | patch
Permalink /patch/67369/
State New
Headers show

Comments

Nicola Pero - Oct. 10, 2010, 11:29 p.m.
We are getting there ... :-)

Where we are getting to is that users including objc/objc-api.h (the traditional GNU Objective-C Runtime include) will get the traditional GNU Objective-C Runtime API, while users including objc/runtime.h (the standard include on Apple/NeXT Objective-C Runtime) will get the "modern" GNU Objective-C Runtime API, which is (being written to be) very similar/almost identical to the new, revised Apple Objective-C 2.0 Runtime API (this to facilitate porting programs from Apple to GNU, and to support Objective-C 2.0 while still allowing GNU Objective-C 1.0 programs to compile and run unchanged ...).

The hard bit is that we're trying to support two different (and occasionally conflicting) APIs at the same time (eg, in one Method is a pointer to struct objc_method, while in the other one Method is the actual struct objc_method itself!).  Since they are defined in separate headers this is possible, and
will be clean once finished, but it is confusing to implement as each and every
function and symbol needs to be examined.  Moreover the code inside libobjc itself
is being prepared for the switch from one API to the other and for the hiding of
most of the internal structs (which depend on the ABI, which will change in a
future release, probably the next one).  So, lot of tedious work.

I think I got past the hardest bits though.  :-)

Committed to trunk.

Thanks

2010-10-11  Nicola Pero  <nicola.pero@meta-innovation.com>

        * objc/objc.h: Updated comments.
        * objc/objc-api.h: (object_copy): Added one argument; use a
        #define to maintain backwards-compatibility.  Moved
        _objc_object_alloc, _objc_object_copy, _objc_object_dispose and
        objc_get_uninstalled_dtable into
        objc/deprecated/objc_get_uninstalled_dtable.h and
        objc/deprecated/objc_object_alloc.h.  Include these files.
        * objc/deprecated/objc_get_uninstalled_dtable.h: New.
        * objc/deprecated/objc_object_alloc.h: New.
        * objc/runtime.h (set_getName): New.
        (sel_getType): New.
        (sel_getUid): New.
        (sel_registerName): New.
        (sel_registerTypedName): New.
        (sel_isEqual): New.
        (class_createInstance): New.
        (object_copy): New.
        (object_dispose): New.
        * objects.c: Do not include tconfig.h.  Include gc_typed.h if
        building the garbage collection version.
        (__objc_object_alloc): Removed.
        (__objc_object_copy): Removed.
        (__objc_object_dispose): Removed.
        (class_createInstance): New from code in class_create_instance.
        Cast second argument of GC_malloc_explicitly_typed.  Use
        objc_calloc.  Do not call _objc_object_alloc.
        (class_create_instance): Call class_createInstance.
        (object_copy): Added extraBytes argument.  Do not call
        _objc_object_copy.
        (object_dispose): Do not call _objc_object_dispose.
        * memory.c (objc_free): When using garbage collection, mark the
        argument as unused.
        * selector.c (sel_getName): New.
        (sel_get_name): Call sel_getName.
        (sel_getType): New.
        (sel_get_type): Call sel_getType.
        (sel_registerName): New.
        (sel_register_name): Call sel_registerName.
        (sel_registerTypedName): New.
        (sel_register_typed_name): Call sel_registerTypedName.
        (sel_getUid): New.
        (sel_get_uid): Call sel_getUid.

Patch

Index: selector.c
===================================================================
--- selector.c	(revision 165248)
+++ selector.c	(working copy)
@@ -287,16 +287,9 @@  sel_get_any_uid (const char *name)
   return (SEL) l->head;
 }
 
-/* return selector representing name */
-SEL
-sel_get_uid (const char *name)
-{
-  return sel_register_typed_name (name, 0);
-}
-
 /* Get name of selector.  If selector is unknown, the empty string "" 
    is returned */ 
-const char *sel_get_name (SEL selector)
+const char *sel_getName (SEL selector)
 {
   const char *ret;
 
@@ -310,6 +303,12 @@  sel_get_any_uid (const char *name)
   return ret;
 }
 
+/* Traditional GNU Objective-C Runtime API.  */
+const char *sel_get_name (SEL selector)
+{
+  return sel_getName (selector);
+}
+
 BOOL
 sel_is_mapped (SEL selector)
 {
@@ -317,8 +316,7 @@  sel_is_mapped (SEL selector)
   return ((idx > 0) && (idx <= __objc_selector_max_index));
 }
 
-
-const char *sel_get_type (SEL selector)
+const char *sel_getType (SEL selector)
 {
   if (selector)
     return selector->sel_types;
@@ -326,6 +324,12 @@  sel_is_mapped (SEL selector)
     return 0;
 }
 
+/* Traditional GNU Objective-C Runtime API.  */
+const char *sel_get_type (SEL selector)
+{
+  return sel_getType (selector);
+}
+
 /* The uninstalled dispatch table */
 extern struct sarray *__objc_uninstalled_dtable;
 
@@ -467,7 +471,7 @@  __sel_register_typed_name (const char *name, const
 }
 
 SEL
-sel_register_name (const char *name)
+sel_registerName (const char *name)
 {
   SEL ret;
     
@@ -480,9 +484,16 @@  SEL
   return ret;
 }
 
+/* Traditional GNU Objective-C Runtime API.  */
 SEL
-sel_register_typed_name (const char *name, const char *type)
+sel_register_name (const char *name)
 {
+  return sel_registerName (name);
+}
+
+SEL
+sel_registerTypedName (const char *name, const char *type)
+{
   SEL ret;
 
   objc_mutex_lock (__objc_runtime_mutex);
@@ -493,3 +504,23 @@  SEL
   
   return ret;
 }
+
+SEL
+sel_register_typed_name (const char *name, const char *type)
+{
+  return sel_registerTypedName (name, type);
+}
+
+/* return selector representing name */
+SEL
+sel_getUid (const char *name)
+{
+  return sel_registerTypedName (name, 0);
+}
+
+/* Traditional GNU Objective-C Runtime API.  */
+SEL
+sel_get_uid (const char *name)
+{
+  return sel_getUid (name);
+}
Index: objects.c
===================================================================
--- objects.c	(revision 165248)
+++ objects.c	(working copy)
@@ -23,51 +23,67 @@  see the files COPYING3 and COPYING.RUNTIME respect
 <http://www.gnu.org/licenses/>.  */
 
 #include "objc-private/common.h"
-#include <string.h> /* For memset */
-#include "tconfig.h"         /* include defs of bzero for target */
 #include "objc/objc.h"
 #include "objc/objc-api.h"
 #include "objc-private/runtime.h"		/* the kitchen sink */
 
+#include <string.h> /* For memcpy()  */
+
 #if OBJC_WITH_GC
 # include <gc.h>
+# include <gc_typed.h>
 #endif
 
-id __objc_object_alloc (Class);
-id __objc_object_dispose (id);
-id __objc_object_copy (id);
-
-id (*_objc_object_alloc) (Class)   = __objc_object_alloc;   /* !T:SINGLE */ 
-id (*_objc_object_dispose) (id)    = __objc_object_dispose; /* !T:SINGLE */
-id (*_objc_object_copy) (id)       = __objc_object_copy;    /* !T:SINGLE */
-
+/* FIXME: The semantics of extraBytes are not really clear.  */
+inline
 id
-class_create_instance (Class class)
+class_createInstance (Class class, size_t extraBytes)
 {
   id new = nil;
 
 #if OBJC_WITH_GC
   if (CLS_ISCLASS (class))
-    new = (id) GC_malloc_explicitly_typed (class->instance_size,
-					   class->gc_object_type);
+    new = (id) GC_malloc_explicitly_typed (class->instance_size + extraBytes,
+					   (GC_descr)class->gc_object_type);
 #else
   if (CLS_ISCLASS (class))
-    new = (*_objc_object_alloc) (class);
+    new = (id) objc_calloc (class->instance_size + extraBytes, 1);
 #endif
 
   if (new != nil)
     {
-      memset (new, 0, class->instance_size);
+      /* There is no need to zero the memory, since both
+	 GC_malloc_explicitly_typed and objc_calloc return zeroed
+	 memory.  */
       new->class_pointer = class;
     }
+
+  /* TODO: Invoke C++ constructors on all appropriate C++ instance
+     variables of the new object.  */
+
   return new;
 }
 
+/* Traditional GNU Objective-C Runtime API.  */
 id
-object_copy (id object)
+class_create_instance (Class class)
 {
+  return class_createInstance (class, 0);
+}
+
+/* Temporary, while we are including objc-api.h instead of runtime.h.  */
+#undef object_copy
+
+id
+object_copy (id object, size_t extraBytes)
+{
   if ((object != nil) && CLS_ISCLASS (object->class_pointer))
-    return (*_objc_object_copy) (object);
+    {
+      /* TODO: How should it work with C++ constructors ? */
+      id copy = class_createInstance (object->class_pointer, extraBytes);
+      memcpy (copy, object, object->class_pointer->instance_size + extraBytes);
+      return copy;
+    }
   else
     return nil;
 }
@@ -77,28 +93,20 @@  object_dispose (id object)
 {
   if ((object != nil) && CLS_ISCLASS (object->class_pointer))
     {
-      if (_objc_object_dispose)
-        (*_objc_object_dispose) (object);
-      else
-        objc_free (object);
+      /* TODO: Invoke C++ destructors on all appropriate C++ instance
+	 variables.  But what happens with the garbage collector ?
+	 Would object_dispose() be ever called in that case ?  */
+
+      objc_free (object);
     }
   return nil;
 }
 
-id __objc_object_alloc (Class class)
-{
-  return (id) objc_malloc (class->instance_size);
-}
+/*
+  Hook functions for memory allocation and disposal.  Deprecated
+  and currently unused.
+*/
 
-id __objc_object_dispose (id object) 
-{
-  objc_free (object);
-  return 0;
-}
-
-id __objc_object_copy (id object)
-{
-  id copy = class_create_instance (object->class_pointer);
-  memcpy (copy, object, object->class_pointer->instance_size);
-  return copy;
-}
+id (*_objc_object_alloc) (Class)   = 0;
+id (*_objc_object_dispose) (id)    = 0;
+id (*_objc_object_copy) (id)       = 0;
Index: ChangeLog
===================================================================
--- ChangeLog	(revision 165256)
+++ ChangeLog	(working copy)
@@ -1,3 +1,48 @@ 
+2010-10-11  Nicola Pero  <nicola.pero@meta-innovation.com>
+
+	* objc/objc.h: Updated comments.
+	* objc/objc-api.h: (object_copy): Added one argument; use a
+	#define to maintain backwards-compatibility.  Moved
+	_objc_object_alloc, _objc_object_copy, _objc_object_dispose and
+	objc_get_uninstalled_dtable into
+	objc/deprecated/objc_get_uninstalled_dtable.h and
+	objc/deprecated/objc_object_alloc.h.  Include these files.
+	* objc/deprecated/objc_get_uninstalled_dtable.h: New.
+	* objc/deprecated/objc_object_alloc.h: New.
+	* objc/runtime.h (set_getName): New.
+	(sel_getType): New.
+	(sel_getUid): New.
+	(sel_registerName): New.
+	(sel_registerTypedName): New.
+	(sel_isEqual): New.
+	(class_createInstance): New.
+	(object_copy): New.
+	(object_dispose): New.
+	* objects.c: Do not include tconfig.h.  Include gc_typed.h if
+	building the garbage collection version.
+	(__objc_object_alloc): Removed.
+	(__objc_object_copy): Removed.
+	(__objc_object_dispose): Removed.
+	(class_createInstance): New from code in class_create_instance.
+	Cast second argument of GC_malloc_explicitly_typed.  Use
+	objc_calloc.  Do not call _objc_object_alloc.
+	(class_create_instance): Call class_createInstance.
+	(object_copy): Added extraBytes argument.  Do not call
+	_objc_object_copy.
+	(object_dispose): Do not call _objc_object_dispose.
+	* memory.c (objc_free): When using garbage collection, mark the
+	argument as unused.
+	* selector.c (sel_getName): New.
+	(sel_get_name): Call sel_getName.
+	(sel_getType): New.
+	(sel_get_type): Call sel_getType.
+	(sel_registerName): New.
+	(sel_register_name): Call sel_registerName.
+	(sel_registerTypedName): New.
+	(sel_register_typed_name): Call sel_registerTypedName.
+	(sel_getUid): New.
+	(sel_get_uid): Call sel_getUid.
+	
 2010-10-10  Nicola Pero  <nicola.pero@meta-innovation.com>
 
 	* objc/objc-api.h: Define Method, Method_t, Category and
Index: memory.c
===================================================================
--- memory.c	(revision 165248)
+++ memory.c	(working copy)
@@ -30,6 +30,8 @@  see the files COPYING3 and COPYING.RUNTIME respect
   so that they work properly with garbage collectors.
 */
 
+/* TODO: Turn these into macros or inline functions.  */
+
 #include "objc-private/common.h"
 #include "objc-private/error.h"
 
@@ -85,7 +87,7 @@  objc_calloc (size_t nelem, size_t size)
 }
 
 void
-objc_free (void *mem)
+objc_free (void *mem __attribute__ ((__unused__)))
 {
   return;
 }
Index: objc/deprecated/objc_get_uninstalled_dtable.h
===================================================================
--- objc/deprecated/objc_get_uninstalled_dtable.h	(revision 0)
+++ objc/deprecated/objc_get_uninstalled_dtable.h	(revision 0)
@@ -0,0 +1,2 @@ 
+objc_EXPORT struct sarray* 
+objc_get_uninstalled_dtable(void);
Index: objc/deprecated/objc_object_alloc.h
===================================================================
--- objc/deprecated/objc_object_alloc.h	(revision 0)
+++ objc/deprecated/objc_object_alloc.h	(revision 0)
@@ -0,0 +1,8 @@ 
+/* These functions are deprecated and currently ignored.  */
+/*
+** Hook functions for allocating, copying and disposing of instances
+*/
+objc_EXPORT id (*_objc_object_alloc)(Class _class);
+objc_EXPORT id (*_objc_object_copy)(id object);
+objc_EXPORT id (*_objc_object_dispose)(id object);
+
Index: objc/objc.h
===================================================================
--- objc/objc.h	(revision 165248)
+++ objc/objc.h	(working copy)
@@ -88,22 +88,20 @@  typedef struct objc_class *Class;
 #include "deprecated/MetaClass.h"
 #include "deprecated/struct_objc_class.h"
 
-/* An 'id' is an object of an unknown class.  The struct objc_object
-   is private and what you see here is only the beginning of the
-   struct.  In theory, the fact that 'class_pointer' is public means
-   that if you have any object 'object', you can immediately get its
-   class by using '((id)object)->class_pointer', but this is not
-   recommended; you should use object_get_class(object) instead.
+/* An 'id' is an object of an unknown class.  The way the object data
+   is stored inside the object is private and what you see here is
+   only the beginning of the actual struct.  The first field is always
+   a pointer to the Class that the object belongs to.  If performance
+   is paramount, you can use this knowledge to get the class of an
+   object by doing '((id)object)->class_pointer'.
 */
 typedef struct objc_object
 {
   /* 'class_pointer' is the Class that the object belongs to.  In case
-     of a Class object, this pointer points to the meta class.  */
-  /* Note that the Apple/NeXT runtime calls this variable 'isa'.
-     TODO: Decide if we want to call it 'isa' too.  TODO: Why not
-     simply hide this pointer and force users to use the proper API to
-     get it ?
-  */
+     of a Class object, this pointer points to the meta class.
+
+     Compatibility Note: The Apple/NeXT runtime calls this field
+     'isa'.  */
   Class class_pointer;
 } *id;
 
Index: objc/runtime.h
===================================================================
--- objc/runtime.h	(revision 165256)
+++ objc/runtime.h	(working copy)
@@ -145,8 +145,68 @@  struct objc_method_description
 #define _F_ONEWAY	0x10
 #define _F_GCINVISIBLE	0x20
 
-/* TODO: Add all the functions in the API.  */
 
+/** Internals: the following functions are in selector.c.  */
+
+/* Return the name of a given selector.  */
+objc_EXPORT const char *sel_getName (SEL selector);
+
+/* Return the type of a given selector.
+
+   Compatibility Note: the Apple/NeXT runtime has untyped selectors,
+   so it does not have this function, which is specific to the GNU
+   Runtime.  */
+objc_EXPORT const char *sel_getType (SEL selector);
+
+/* This is the same as sel_registerName ().  Please use
+   sel_registerName () instead.  */
+objc_EXPORT SEL sel_getUid (const char *name);
+
+/* Register a selector with a given name (but unspecified types).  If
+   you know the types, it is better to call sel_registerTypedName().
+   If a selector with this name already exists, it is returned.  */
+objc_EXPORT SEL sel_registerName (const char *name);
+
+/* Register a selector with a given name and types.  If a selector
+   with this name and types already exists, it is returned.
+
+   Compatibility Note: the Apple/NeXT runtime has untyped selectors,
+   so it does not have this function, which is specific to the GNU
+   Runtime.  */
+objc_EXPORT SEL set_registerTypedName (const char *name, const char *type);
+
+/* Return YES if first_selector is the same as second_selector, and NO
+   if not.  */
+objc_EXPORT BOOL sel_isEqual (SEL first_selector, SEL second_selector);
+
+
+/** Internals: the following functions are in objects.c.  */
+
+/* Create an instance of class 'class', adding extraBytes to the size
+   of the returned object.  This method allocates the appropriate
+   amount of memory for the instance, initializes it to zero, then
+   calls all the C++ constructors on appropriate C++ instance
+   variables of the instance (if any) (TODO: This is not implemented
+   yet).  */
+objc_EXPORT id class_createInstance (Class class, size_t extraBytes);
+
+/* Copy an object and return the copy.  extraBytes should be identical
+   to the extraBytes parameter that was passed when creating the
+   original object.  */
+objc_EXPORT id object_copy (id object, size_t extraBytes);
+
+/* Dispose of an object.  This method calls the appropriate C++
+   destructors on appropriate C++ instance variables of the instance
+   (if any) (TODO: This is not implemented yet), then frees the memory
+   for the instance.  */
+objc_EXPORT id object_dispose (id object);
+
+
+/* TODO: Add all the other functions in the API.  */
+
+
+/** Internals: the following functions are in objc-foreach.c.  */
+
 /* 'objc_enumerationMutation()' is called when a collection is
    mutated while being "fast enumerated".  That is a hard error, and
    objc_enumerationMutation is called to deal with it.  'collection'
@@ -199,6 +259,8 @@  struct __objcFastEnumerationState
 */
 
 
+/** Internals: the following functions are implemented in encoding.c.  */
+
 /* Traditional GNU Objective-C Runtime functions that are currently
    used to implement method forwarding.
 */
Index: objc/objc-api.h
===================================================================
--- objc/objc-api.h	(revision 165256)
+++ objc/objc-api.h	(working copy)
@@ -193,12 +193,7 @@  objc_EXPORT Class (*_objc_lookup_class)(const char
 */
 objc_EXPORT void (*_objc_load_callback)(Class _class, Category* category);
 
-/*
-** Hook functions for allocating, copying and disposing of instances
-*/
-objc_EXPORT id (*_objc_object_alloc)(Class _class);
-objc_EXPORT id (*_objc_object_copy)(id object);
-objc_EXPORT id (*_objc_object_dispose)(id object);
+#include "deprecated/objc_object_alloc.h"
 
 /*
   Standard functions for memory allocation and disposal.  Users should
@@ -326,7 +321,12 @@  objc_EXPORT IMP method_get_imp(Method_t method);
 
 objc_EXPORT IMP get_imp (Class _class, SEL sel);
 
-objc_EXPORT id object_copy(id object);
+/* object_copy used to take a single argument in the traditional GNU
+   Objective-C Runtime API (the one declared here), but takes 2 in the
+   modern API (implemented in the actual runtime).  Define the old
+   object_copy in terms of the new one.  */
+objc_EXPORT id object_copy (id object, size_t size);
+#define object_copy(X) (object_copy ((X), 0))
 
 objc_EXPORT id object_dispose(id object);
 
@@ -394,8 +394,7 @@  object_is_meta_class (id object)
 	  &&  !object_is_class (object));
 }
 
-objc_EXPORT struct sarray* 
-objc_get_uninstalled_dtable(void);
+#include "deprecated/objc_get_uninstalled_dtable.h"
 
 #ifdef __cplusplus
 }