In libobjc/: 2010-10-11 Nicola Pero <nicola.pero@meta-innovation.com>

In libobjc/:
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.

From-SVN: r165269
This commit is contained in:
Nicola Pero 2010-10-11 02:36:32 +00:00 committed by Nicola Pero
parent f3660703cb
commit fdcbbfe70c
7 changed files with 341 additions and 14 deletions

View File

@ -1,3 +1,24 @@
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.

View File

@ -171,6 +171,7 @@ C_SOURCE_FILES = \
gc.c \
hash.c \
init.c \
ivars.c \
memory.c \
nil_method.c \
objc-foreach.c \

151
libobjc/ivars.c Normal file
View File

@ -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;
}

View File

@ -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. */

View File

@ -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;

View File

@ -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, SEL second_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,6 +219,69 @@ objc_EXPORT id object_copy (id object, size_t extraBytes);
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. */
@ -216,8 +297,7 @@ objc_EXPORT id object_dispose (id object);
is set. Then, it will abort the program.
Compatibility note: the Apple runtime will not abort the program
after calling the mutation handler.
*/
after calling the mutation handler. */
objc_EXPORT void objc_enumerationMutation (id collection);
/* 'objc_set_enumeration_mutation_handler' can be used to set a
@ -236,8 +316,7 @@ objc_EXPORT void objc_enumerationMutation (id collection);
libraries; in the case of GNUstep, GNUstep Base may be using this
function to improve the standard enumeration mutation handling.
You probably shouldn't use this function unless you are writing
your own Foundation library.
*/
your own Foundation library. */
objc_EXPORT void objc_setEnumerationMutationHandler (void (*handler)(id));
/* This structure (used during fast enumeration) is automatically
@ -246,8 +325,7 @@ objc_EXPORT void objc_setEnumerationMutationHandler (void (*handler)(id));
defined again with the name of NSFastEnumeration by "Foundation"
libraries such as GNUstep Base. And if NSFastEnumeration is
defined, the compiler will use it instead of
__objcFastEnumerationState when doing fast enumeration.
*/
__objcFastEnumerationState when doing fast enumeration. */
/*
struct __objcFastEnumerationState
{

View File

@ -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.