mirror of git://gcc.gnu.org/git/gcc.git
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:
parent
f3660703cb
commit
fdcbbfe70c
|
@ -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>
|
2010-10-11 Nicola Pero <nicola.pero@meta-innovation.com>
|
||||||
|
|
||||||
* objc/objc.h: Updated comments.
|
* objc/objc.h: Updated comments.
|
||||||
|
|
|
@ -171,6 +171,7 @@ C_SOURCE_FILES = \
|
||||||
gc.c \
|
gc.c \
|
||||||
hash.c \
|
hash.c \
|
||||||
init.c \
|
init.c \
|
||||||
|
ivars.c \
|
||||||
memory.c \
|
memory.c \
|
||||||
nil_method.c \
|
nil_method.c \
|
||||||
objc-foreach.c \
|
objc-foreach.c \
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
|
@ -145,6 +145,59 @@ struct objc_protocol_list
|
||||||
Protocol *list[1];
|
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.
|
/* The compiler generates one of these structures for each category.
|
||||||
A class may have many categories and contain both instance and
|
A class may have many categories and contain both instance and
|
||||||
factory methods. */
|
factory methods. */
|
||||||
|
|
|
@ -91,9 +91,7 @@ typedef struct objc_class *Class;
|
||||||
/* An 'id' is an object of an unknown class. The way the object data
|
/* 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
|
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
|
only the beginning of the actual struct. The first field is always
|
||||||
a pointer to the Class that the object belongs to. If performance
|
a pointer to the Class that the object belongs to.
|
||||||
is paramount, you can use this knowledge to get the class of an
|
|
||||||
object by doing '((id)object)->class_pointer'.
|
|
||||||
*/
|
*/
|
||||||
typedef struct objc_object
|
typedef struct objc_object
|
||||||
{
|
{
|
||||||
|
@ -101,7 +99,9 @@ typedef struct objc_object
|
||||||
of a Class object, this pointer points to the meta class.
|
of a Class object, this pointer points to the meta class.
|
||||||
|
|
||||||
Compatibility Note: The Apple/NeXT runtime calls this field
|
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;
|
Class class_pointer;
|
||||||
} *id;
|
} *id;
|
||||||
|
|
||||||
|
|
|
@ -146,6 +146,24 @@ struct objc_method_description
|
||||||
#define _F_GCINVISIBLE 0x20
|
#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. */
|
/** Internals: the following functions are in selector.c. */
|
||||||
|
|
||||||
/* Return the name of a given selector. */
|
/* 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. */
|
/** 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
|
of the returned object. This method allocates the appropriate
|
||||||
amount of memory for the instance, initializes it to zero, then
|
amount of memory for the instance, initializes it to zero, then
|
||||||
calls all the C++ constructors on appropriate C++ instance
|
calls all the C++ constructors on appropriate C++ instance
|
||||||
variables of the instance (if any) (TODO: This is not implemented
|
variables of the instance (if any) (TODO: The C++ constructors bit
|
||||||
yet). */
|
is not implemented yet). */
|
||||||
objc_EXPORT id class_createInstance (Class class, size_t extraBytes);
|
objc_EXPORT id class_createInstance (Class class_, size_t extraBytes);
|
||||||
|
|
||||||
/* Copy an object and return the copy. extraBytes should be identical
|
/* Copy an object and return the copy. extraBytes should be identical
|
||||||
to the extraBytes parameter that was passed when creating the
|
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. */
|
for the instance. */
|
||||||
objc_EXPORT id object_dispose (id object);
|
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. */
|
/* 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.
|
is set. Then, it will abort the program.
|
||||||
|
|
||||||
Compatibility note: the Apple runtime will not 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_EXPORT void objc_enumerationMutation (id collection);
|
||||||
|
|
||||||
/* 'objc_set_enumeration_mutation_handler' can be used to set a
|
/* '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
|
libraries; in the case of GNUstep, GNUstep Base may be using this
|
||||||
function to improve the standard enumeration mutation handling.
|
function to improve the standard enumeration mutation handling.
|
||||||
You probably shouldn't use this function unless you are writing
|
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));
|
objc_EXPORT void objc_setEnumerationMutationHandler (void (*handler)(id));
|
||||||
|
|
||||||
/* This structure (used during fast enumeration) is automatically
|
/* 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"
|
defined again with the name of NSFastEnumeration by "Foundation"
|
||||||
libraries such as GNUstep Base. And if NSFastEnumeration is
|
libraries such as GNUstep Base. And if NSFastEnumeration is
|
||||||
defined, the compiler will use it instead of
|
defined, the compiler will use it instead of
|
||||||
__objcFastEnumerationState when doing fast enumeration.
|
__objcFastEnumerationState when doing fast enumeration. */
|
||||||
*/
|
|
||||||
/*
|
/*
|
||||||
struct __objcFastEnumerationState
|
struct __objcFastEnumerationState
|
||||||
{
|
{
|
||||||
|
|
|
@ -102,6 +102,29 @@ object_dispose (id object)
|
||||||
return nil;
|
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
|
Hook functions for memory allocation and disposal. Deprecated
|
||||||
and currently unused.
|
and currently unused.
|
||||||
|
|
Loading…
Reference in New Issue