diff options
-rw-r--r-- | libobjc/ChangeLog | 21 | ||||
-rw-r--r-- | libobjc/Makefile.in | 1 | ||||
-rw-r--r-- | libobjc/ivars.c | 151 | ||||
-rw-r--r-- | libobjc/objc-private/module-abi-8.h | 53 | ||||
-rw-r--r-- | libobjc/objc/objc.h | 8 | ||||
-rw-r--r-- | libobjc/objc/runtime.h | 98 | ||||
-rw-r--r-- | libobjc/objects.c | 23 |
7 files changed, 341 insertions, 14 deletions
diff --git a/libobjc/ChangeLog b/libobjc/ChangeLog index a63e43a..e7881c6 100644 --- a/libobjc/ChangeLog +++ b/libobjc/ChangeLog @@ -1,5 +1,26 @@ 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 diff --git a/libobjc/Makefile.in b/libobjc/Makefile.in index aeb6892..86f65ba 100644 --- a/libobjc/Makefile.in +++ b/libobjc/Makefile.in @@ -171,6 +171,7 @@ C_SOURCE_FILES = \ gc.c \ hash.c \ init.c \ + ivars.c \ memory.c \ nil_method.c \ objc-foreach.c \ diff --git a/libobjc/ivars.c b/libobjc/ivars.c new file mode 100644 index 0000000..18c6e8a --- /dev/null +++ b/libobjc/ivars.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; +} diff --git a/libobjc/objc-private/module-abi-8.h b/libobjc/objc-private/module-abi-8.h index 7296273..a20e3a3 100644 --- a/libobjc/objc-private/module-abi-8.h +++ b/libobjc/objc-private/module-abi-8.h @@ -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. */ diff --git a/libobjc/objc/objc.h b/libobjc/objc/objc.h index 76812ad..7d38216 100644 --- a/libobjc/objc/objc.h +++ b/libobjc/objc/objc.h @@ -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; diff --git a/libobjc/objc/runtime.h b/libobjc/objc/runtime.h index 73c05d9..95928c8 100644 --- a/libobjc/objc/runtime.h +++ b/libobjc/objc/runtime.h @@ -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 { diff --git a/libobjc/objects.c b/libobjc/objects.c index d37a95d..2562be5 100644 --- a/libobjc/objects.c +++ b/libobjc/objects.c @@ -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. |