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

login
register
mail settings
Submitter Nicola Pero
Date Oct. 11, 2010, 2:36 a.m.
Message ID <1286764596.349721506@192.168.2.229>
Download mbox | patch
Permalink /patch/67378/
State New
Headers show

Comments

Nicola Pero - Oct. 11, 2010, 2:36 a.m.
This patch adds more of the "modern" Objective-C Runtime API functions.  No regressions; committed to trunk.

Thanks

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

        * Makefile.in (C_SOURCE_FILES): Added ivars.c.
        * ivars.c: New.
        * objc/objc.h: Updated comments.
        * objc/runtime.h (object_getClass): New.
        (object_getClassName): New.
        (object_setClass): New.
        (class_getInstanceVariable): New.
        (object_getIndexedIvars): New.
        (object_getInstanceVariable): New.
        (object_setInstanceVariable): New.
        (object_getIvar): New.
        (object_setIvar): New.  
        (ivar_getName): New.
        (ivar_getOffset): New.
        (ivar_getTypeEncoding): New.
        * objc-private/module-abi-8.h (struct objc_class): Added.
        * objects.c (object_getClassName): New.
        (object_setClass): New.

Patch

Index: Makefile.in
===================================================================
--- Makefile.in	(revision 165249)
+++ Makefile.in	(working copy)
@@ -171,6 +171,7 @@  C_SOURCE_FILES = \
    gc.c \
    hash.c \
    init.c \
+   ivars.c \
    memory.c \
    nil_method.c \
    objc-foreach.c \
Index: objc-private/module-abi-8.h
===================================================================
--- objc-private/module-abi-8.h	(revision 165256)
+++ objc-private/module-abi-8.h	(working copy)
@@ -145,6 +145,59 @@  struct objc_protocol_list
   Protocol *list[1];
 };
 
+/*
+  The compiler generates one of these structures for each class.  
+
+  This structure is the definition for classes.
+
+  This structure is generated by the compiler in the executable and
+  used by the run-time during normal messaging operations.  Therefore
+  some members change type. The compiler generates "char* const" and
+  places a string in the following member variables: super_class.
+*/
+struct objc_class {     
+  struct objc_class*  class_pointer;    /* Pointer to the class's meta
+					   class. */
+  struct objc_class*  super_class;      /* Pointer to the super
+					   class. NULL for class
+					   Object. */
+  const char*         name;             /* Name of the class. */
+  long                version;          /* Unknown. */
+  unsigned long       info;             /* Bit mask.  See class masks
+					   defined above. */
+  long                instance_size;    /* Size in bytes of the class.
+					   The sum of the class
+					   definition and all super
+					   class definitions. */
+#ifdef _WIN64
+  /* We pad the structure manually to prevent warning when -Wpadded is
+     used.  The compiler automatically pads the structures that it
+     generates, so this manually padded structure still matches the
+     one generated by the compiler, but if we don't pad manually,
+     -Wpadded detects that padding is being added and generates
+     annoying warnings.  This hack is necessary as on LLP64 targets
+     sizeof (long) isn't equal to sizeof (void *).  */
+  long pad;
+#endif
+  struct objc_ivar_list* ivars;         /* Pointer to a structure that
+					   describes the instance
+					   variables in the class
+					   definition.  NULL indicates
+					   no instance variables.
+					   Does not include super
+					   class variables. */
+  struct objc_method_list*  methods;    /* Linked list of instance
+					   methods defined for the
+					   class. */
+  struct sarray *    dtable;            /* Pointer to instance method
+					   dispatch table. */  
+  struct objc_class* subclass_list;     /* Subclasses */
+  struct objc_class* sibling_class;
+
+  struct objc_protocol_list *protocols; /* Protocols conformed to */
+  void* gc_object_type;
+};
+
 /* The compiler generates one of these structures for each category.
    A class may have many categories and contain both instance and
    factory methods.  */
Index: objects.c
===================================================================
--- objects.c	(revision 165264)
+++ objects.c	(working copy)
@@ -102,6 +102,29 @@  object_dispose (id object)
   return nil;
 }
 
+const char *
+object_getClassName (id object)
+{
+  if (object != nil)
+    return object->class_pointer->name;
+  else
+    return "Nil";
+}
+
+Class
+object_setClass (id object, Class class_)
+{
+  if (object == nil)
+    return Nil;
+  else
+    {
+      Class old_class = object->class_pointer;
+
+      object->class_pointer = class_;
+      return old_class;
+    }
+}
+
 /*
   Hook functions for memory allocation and disposal.  Deprecated
   and currently unused.
Index: ChangeLog
===================================================================
--- ChangeLog	(revision 165264)
+++ ChangeLog	(working copy)
@@ -1,6 +1,27 @@ 
 2010-10-11  Nicola Pero  <nicola.pero@meta-innovation.com>
 
+	* Makefile.in (C_SOURCE_FILES): Added ivars.c.
+	* ivars.c: New.
 	* objc/objc.h: Updated comments.
+	* objc/runtime.h (object_getClass): New.
+	(object_getClassName): New.
+	(object_setClass): New.
+	(class_getInstanceVariable): New.
+	(object_getIndexedIvars): New.
+	(object_getInstanceVariable): New.
+	(object_setInstanceVariable): New.
+	(object_getIvar): New.
+	(object_setIvar): New.	
+	(ivar_getName): New.
+	(ivar_getOffset): New.
+	(ivar_getTypeEncoding): New.
+	* objc-private/module-abi-8.h (struct objc_class): Added.
+	* objects.c (object_getClassName): New.
+	(object_setClass): New.
+	
+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
Index: ivars.c
===================================================================
--- ivars.c	(revision 0)
+++ ivars.c	(revision 0)
@@ -0,0 +1,151 @@ 
+/* GNU Objective C Runtime ivar 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/objc.h"
+#include "objc/objc-api.h"
+#include "objc-private/runtime.h"		/* the kitchen sink */
+#include <string.h> /* For strcmp */
+
+struct objc_ivar *
+class_getInstanceVariable (Class class_, const char *name)
+{
+  if (class_ != Nil  &&  name != NULL)
+    {
+      objc_mutex_lock (__objc_runtime_mutex);
+      while (class_ != Nil)
+	{
+	  struct objc_ivar_list *ivars = class_->ivars;
+	  if (ivars != NULL)
+	    {
+	      int i;
+	      
+	      for (i = 0; i < ivars->ivar_count; i++)
+		{
+		  struct objc_ivar *ivar = &(ivars->ivar_list[i]);
+		  
+		  if (!strcmp (ivar->ivar_name, name))
+		    {
+		      objc_mutex_unlock (__objc_runtime_mutex);
+		      return ivar;
+		    }
+		}
+	    }
+	  class_ = class_->super_class;
+	}
+      objc_mutex_unlock (__objc_runtime_mutex);
+    }
+  return NULL;
+}
+
+void *
+object_getIndexedIvars (id object)
+{
+  if (object == nil)
+    return NULL;
+  else
+    {
+      return (void *)(((char *)object) 
+		      + object->class_pointer->instance_size);
+    }
+}
+
+struct objc_ivar *
+object_getInstanceVariable (id object, const char *name, void **returnValue)
+{
+  if (object == nil  ||  name == NULL)
+    return NULL;
+  else
+    {
+      struct objc_ivar * variable = class_getInstanceVariable (object->class_pointer, name);
+
+      if (variable != NULL  &&  returnValue != NULL)
+	{
+	  char *location = (char *)object + variable->ivar_offset;
+	 
+	  *returnValue = *((id *)location);
+	}
+
+      return variable;
+    }
+}
+
+struct objc_ivar *
+object_setInstanceVariable (id object, const char *name, void *newValue)
+{
+  if (object == nil  ||  name == NULL)
+    return NULL;
+  else
+    {
+      struct objc_ivar * variable = class_getInstanceVariable (object->class_pointer, name);
+
+      if (variable != NULL)
+	{
+	  char *location = (char *)object + variable->ivar_offset;
+	  
+	  *((id *)location) = (id)newValue;
+	}
+
+      return variable;
+    }
+}
+
+id object_getIvar (id object, struct objc_ivar * variable)
+{
+  if (object == nil  ||  variable == NULL)
+    return nil;
+  else
+    {
+      char *location = (char *)object + variable->ivar_offset;
+
+      return *((id *)location);
+    }
+}
+
+void object_setIvar (id object, struct objc_ivar * variable, id value)
+{
+  if (object == nil  ||  variable == NULL)
+    return;
+  else
+    {
+      char *location = (char *)object + variable->ivar_offset;
+
+      *((id *)location) = value;
+    }
+}
+
+const char * ivar_getName (struct objc_ivar * variable)
+{
+  return variable->ivar_name;
+}
+
+ptrdiff_t ivar_getOffset (struct objc_ivar * variable)
+{
+  return (ptrdiff_t)(variable->ivar_offset);
+}
+
+const char * ivar_getTypeEncoding (struct objc_ivar * variable)
+{
+  return variable->ivar_type;
+}
Index: objc/objc.h
===================================================================
--- objc/objc.h	(revision 165264)
+++ objc/objc.h	(working copy)
@@ -91,9 +91,7 @@  typedef struct objc_class *Class;
 /* 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'.
+   a pointer to the Class that the object belongs to.
 */
 typedef struct objc_object
 {
@@ -101,7 +99,9 @@  typedef struct objc_object
      of a Class object, this pointer points to the meta class.
 
      Compatibility Note: The Apple/NeXT runtime calls this field
-     'isa'.  */
+     'isa'.  To access this field in a portable way, use
+     object_getClass() from runtime.h, which is an inline function so
+     does not add any overhead.  */
   Class class_pointer;
 } *id;
 
Index: objc/runtime.h
===================================================================
--- objc/runtime.h	(revision 165264)
+++ objc/runtime.h	(working copy)
@@ -146,6 +146,24 @@  struct objc_method_description
 #define _F_GCINVISIBLE	0x20
 
 
+/** Internals: defined inline.  */
+
+/* Return the class of 'object', or Nil if the object is nil.  If
+   'object' is a class, the meta class is returned; if 'object' is a
+   meta class, the root meta class is returned (note that this is
+   different from the traditional GNU Objective-C Runtime API function
+   object_get_class(), which for a meta class would return the meta
+   class itself).  */
+static inline Class
+object_getClass (id object)
+{
+  if (object != nil)
+    return object->class_pointer;
+  else
+    return Nil;
+}
+
+
 /** Internals: the following functions are in selector.c.  */
 
 /* Return the name of a given selector.  */
@@ -182,13 +200,13 @@  objc_EXPORT BOOL sel_isEqual (SEL first_selector,
 
 /** Internals: the following functions are in objects.c.  */
 
-/* Create an instance of class 'class', adding extraBytes to the size
+/* 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);
+   variables of the instance (if any) (TODO: The C++ constructors bit
+   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
@@ -201,10 +219,74 @@  objc_EXPORT id object_copy (id object, size_t extr
    for the instance.  */
 objc_EXPORT id object_dispose (id object);
 
+/* Return the name of the class of 'object'.  If 'object' is 'nil',
+   returns "Nil".  */
+objc_EXPORT const char * object_getClassName (id object);
 
+/* Change the class of object to be class_.  Return the previous class
+   of object.  This is currently not really thread-safe.  */
+objc_EXPORT Class object_setClass (id object, Class class_);
+
+
+/** Internals: the following functions are in ivars.c.  */
+
+/* Return an instance variable given the class and the instance
+   variable name.  This is an expensive function to call, so try to
+   reuse the returned Ivar if you can.  */
+objc_EXPORT Ivar class_getInstanceVariable (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.  */
+objc_EXPORT void * object_getIndexedIvars (id object);
+
+/* Get the value of an instance variable of type 'id'.  The function
+   returns the instance variable.  To get the value of the instance
+   variable, you should pass as 'returnValue' a pointer to an 'id';
+   the value will be copied there.  Note that 'returnValue' is really
+   a 'void *', not a 'void **'.  This function really works only with
+   instance variables of type 'id'; for other types of instance
+   variables, access directly the data at (char *)object +
+   ivar_getOffset (ivar).  */
+objc_EXPORT Ivar object_getInstanceVariable (id object, const char *name, void **returnValue);
+
+/* Set the value of an instance variable.  The value to set is passed
+   in 'newValue' (which really is an 'id', not a 'void *').  The
+   function returns the instance variable.  This function really works
+   only with instance variables of type 'id'; for other types of
+   instance variables, access directly the data at (char *)object +
+   ivar_getOffset (ivar).  */
+objc_EXPORT Ivar object_setInstanceVariable (id object, const char *name, void *newValue);
+
+/* Get the value of an instance variable of type 'id' of the object
+   'object'.  This is faster than object_getInstanceVariable if you
+   already have the instance variable because it avoids the expensive
+   call to class_getInstanceVariable that is done by
+   object_getInstanceVariable.  */
+objc_EXPORT id object_getIvar (id object, Ivar variable);
+
+/* Set the value of an instance variable of type 'id' of the object
+   'object'.  This is faster than object_setInstanceVariable if you
+   already have the instance variable because it avoids the expensive
+   call to class_getInstanceVariable that is done by
+   object_setInstanceVariable.  */
+objc_EXPORT void object_setIvar (id object, Ivar variable, id value);
+
+/* Return the name of the instance variable.  */
+objc_EXPORT const char * ivar_getName (Ivar variable);
+
+/* Return the offset of the instance variable from the start of the
+   object data.  */
+objc_EXPORT ptrdiff_t ivar_getOffset (Ivar variable);
+
+/* Return the type encoding of the variable.  */
+objc_EXPORT const char * ivar_getTypeEncoding (Ivar variable);
+
+
 /* 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