Patchwork =?UTF-8?Q?libobjc=20-=20more=20modern=20Objective-C=20runtime=20API=20(4?= =?UTF-8?Q?)?=

login
register
mail settings
Submitter Nicola Pero
Date Oct. 12, 2010, 6:44 p.m.
Message ID <1286909043.552515932@192.168.2.230>
Download mbox | patch
Permalink /patch/67605/
State New
Headers show

Comments

Nicola Pero - Oct. 12, 2010, 6:44 p.m.
This adds yet another chunk of new API functions.  With these, I was able to move another couple of libobjc source files to the new API/headers. :-)

No regressions, committed to trunk.

Thanks

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.

Patch

Index: objc-private/module-abi-8.h
===================================================================
--- objc-private/module-abi-8.h	(revision 165349)
+++ objc-private/module-abi-8.h	(working copy)
@@ -183,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
@@ -218,6 +218,45 @@  struct objc_class {
 };
 #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
    factory methods.  */
Index: class.c
===================================================================
--- class.c	(revision 165386)
+++ class.c	(working copy)
@@ -89,10 +89,11 @@  see the files COPYING3 and COPYING.RUNTIME respect
 
 #include "objc-private/common.h"
 #include "objc-private/error.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
@@ -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.  */
@@ -739,6 +736,49 @@  class_getName (Class class_)
   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)
 
 Class
Index: objects.c
===================================================================
--- objects.c	(revision 165386)
+++ objects.c	(working copy)
@@ -23,10 +23,12 @@  see the files COPYING3 and COPYING.RUNTIME respect
 <http://www.gnu.org/licenses/>.  */
 
 #include "objc-private/common.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>
Index: exception.c
===================================================================
--- exception.c	(revision 165348)
+++ exception.c	(working copy)
@@ -25,7 +25,7 @@  see the files COPYING3 and COPYING.RUNTIME respect
 #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, i
       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, _u
   
   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, _U
   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;
 }
Index: ChangeLog
===================================================================
--- ChangeLog	(revision 165386)
+++ ChangeLog	(working copy)
@@ -1,5 +1,43 @@ 
 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
Index: ivars.c
===================================================================
--- ivars.c	(revision 165386)
+++ ivars.c	(working copy)
@@ -60,6 +60,25 @@  class_getInstanceVariable (Class class_, const cha
   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)
 {
Index: objc/runtime.h
===================================================================
--- objc/runtime.h	(revision 165386)
+++ objc/runtime.h	(working copy)
@@ -239,6 +239,14 @@  objc_EXPORT Class object_setClass (id object, Clas
    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.  */
@@ -361,7 +369,49 @@  objc_EXPORT int objc_getClassList (Class *returnVa
    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