backport fixes

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@29787 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
rfm 2010-02-27 19:23:58 +00:00
parent 1a6af09e33
commit 837d04cc56
4 changed files with 131 additions and 89 deletions

View file

@ -1,3 +1,11 @@
2010-02-27 Richard Frith-Macdonald <rfm@gnu.org>
* runtime.c:
* sync.m:
* runtime.h:
Backport David's fixes for @synchronize(class), suitably modified to
build with older compilers.
2010-02-27 Richard Frith-Macdonald <rfm@gnu.org> 2010-02-27 Richard Frith-Macdonald <rfm@gnu.org>
* Source/NSObject.m: ([methodSignatureForSelector:]) remote the check * Source/NSObject.m: ([methodSignatureForSelector:]) remote the check

View file

@ -3,7 +3,7 @@
/* Make glibc export strdup() */ /* Make glibc export strdup() */
#if defined __GLIBC__ #if defined __GLIBC__
#define __USE_BSD 1 #define __USE_BSD 1
#endif #endif
#undef __objc_INCLUDE_GNU #undef __objc_INCLUDE_GNU
@ -19,8 +19,8 @@
#define object_copy gnu_object_copy #define object_copy gnu_object_copy
#define object_dispose gnu_object_dispose #define object_dispose gnu_object_dispose
#define objc_super gnu_objc_super #define objc_super gnu_objc_super
#define objc_msg_lookup gnu_objc_msg_lookup #define objc_msg_lookup gnu_objc_msg_lookup
#define objc_msg_lookup_super gnu_objc_msg_lookup_super #define objc_msg_lookup_super gnu_objc_msg_lookup_super
#define BOOL GNU_BOOL #define BOOL GNU_BOOL
#define SEL GNU_SEL #define SEL GNU_SEL
#define Protocol GNU_Protocol #define Protocol GNU_Protocol
@ -37,11 +37,11 @@
#include <objc/encoding.h> #include <objc/encoding.h>
#undef Class #undef Class
#undef Protocol #undef Protocol
#undef SEL #undef SEL
#undef objc_msg_lookup #undef objc_msg_lookup
#undef objc_msg_lookup_super #undef objc_msg_lookup_super
#undef objc_super #undef objc_super
#undef Method #undef Method
#undef IMP #undef IMP
#undef id #undef id
#undef objc_object #undef objc_object
@ -90,9 +90,9 @@ class_getInstanceMethodNonrecursive(Class aClass, SEL aSelector)
const char *types = sel_get_type(aSelector); const char *types = sel_get_type(aSelector);
for (methods = aClass->methods; for (methods = aClass->methods;
methods != NULL; methods = methods->method_next) methods != NULL; methods = methods->method_next)
{ {
int i; int i;
for (i = 0; i < methods->method_count; i++) for (i = 0; i < methods->method_count; i++)
{ {
@ -100,8 +100,7 @@ class_getInstanceMethodNonrecursive(Class aClass, SEL aSelector)
if (strcmp(sel_get_name(method->method_name), name) == 0) if (strcmp(sel_get_name(method->method_name), name) == 0)
{ {
if (NULL == types if (NULL == types || strcmp(types, method->method_types) == 0)
|| strcmp(types, method->method_types) == 0)
{ {
return method; return method;
} }
@ -134,10 +133,8 @@ objc_updateDtableForClassContainingMethod(Method m)
BOOL BOOL
class_addIvar(Class cls, class_addIvar(Class cls,
const char *name, const char *name,
size_t size, size_t size, uint8_t alignment, const char *types)
uint8_t alignment,
const char *types)
{ {
struct objc_ivar_list *ivarlist; struct objc_ivar_list *ivarlist;
Ivar ivar; Ivar ivar;
@ -163,8 +160,9 @@ class_addIvar(Class cls,
{ {
ivarlist->ivar_count++; ivarlist->ivar_count++;
// objc_ivar_list contains one ivar. Others follow it. // objc_ivar_list contains one ivar. Others follow it.
cls->ivars = objc_realloc(ivarlist, sizeof(struct objc_ivar_list) cls->ivars = objc_realloc(ivarlist, sizeof(struct objc_ivar_list)
+ (ivarlist->ivar_count - 1) * sizeof(struct objc_ivar)); + (ivarlist->ivar_count -
1) * sizeof(struct objc_ivar));
} }
ivar = &cls->ivars->ivar_list[cls->ivars->ivar_count - 1]; ivar = &cls->ivars->ivar_list[cls->ivars->ivar_count - 1];
@ -183,9 +181,10 @@ class_addMethod(Class cls, SEL name, IMP imp, const char *types)
const char *methodName = sel_get_name(name); const char *methodName = sel_get_name(name);
struct objc_method_list *methods; struct objc_method_list *methods;
for (methods = cls->methods; methods != NULL; methods = methods->method_next) for (methods = cls->methods; methods != NULL;
methods = methods->method_next)
{ {
int i; int i;
for (i = 0; i < methods->method_count; i++) for (i = 0; i < methods->method_count; i++)
{ {
@ -206,7 +205,7 @@ class_addMethod(Class cls, SEL name, IMP imp, const char *types)
methods->method_list[0].method_name methods->method_list[0].method_name
= sel_register_typed_name(methodName, types); = sel_register_typed_name(methodName, types);
methods->method_list[0].method_types = strdup(types); methods->method_list[0].method_types = strdup(types);
methods->method_list[0].method_imp = (objc_imp_gnu)imp; methods->method_list[0].method_imp = (objc_imp_gnu) imp;
if (CLS_ISRESOLV(cls)) if (CLS_ISRESOLV(cls))
{ {
@ -217,7 +216,7 @@ class_addMethod(Class cls, SEL name, IMP imp, const char *types)
} }
BOOL BOOL
class_addProtocol(Class cls, Protocol *protocol) class_addProtocol(Class cls, Protocol * protocol)
{ {
struct objc_protocol_list *protocols; struct objc_protocol_list *protocols;
@ -240,19 +239,19 @@ class_addProtocol(Class cls, Protocol *protocol)
} }
BOOL BOOL
class_conformsToProtocol(Class cls, Protocol *protocol) class_conformsToProtocol(Class cls, Protocol * protocol)
{ {
struct objc_protocol_list *protocols; struct objc_protocol_list *protocols;
for (protocols = cls->protocols; for (protocols = cls->protocols;
protocols != NULL; protocols = protocols->next) protocols != NULL; protocols = protocols->next)
{ {
int i; int i;
for (i = 0; i < protocols->count; i++) for (i = 0; i < protocols->count; i++)
{ {
if (strcmp(protocols->list[i]->protocol_name, if (strcmp(protocols->list[i]->protocol_name,
protocol->protocol_name) == 0) protocol->protocol_name) == 0)
{ {
return YES; return YES;
} }
@ -298,7 +297,8 @@ class_copyMethodList(Class cls, unsigned int *outCount)
Method *copyDest; Method *copyDest;
struct objc_method_list *methods; struct objc_method_list *methods;
for (methods = cls->methods; methods != NULL; methods = methods->method_next) for (methods = cls->methods; methods != NULL;
methods = methods->method_next)
{ {
count += methods->method_count; count += methods->method_count;
} }
@ -314,7 +314,8 @@ class_copyMethodList(Class cls, unsigned int *outCount)
list = malloc(count * sizeof(struct objc_method *)); list = malloc(count * sizeof(struct objc_method *));
copyDest = list; copyDest = list;
for (methods = cls->methods; methods != NULL; methods = methods->method_next) for (methods = cls->methods; methods != NULL;
methods = methods->method_next)
{ {
unsigned int i; unsigned int i;
@ -346,16 +347,16 @@ class_copyProtocolList(Class cls, unsigned int *outCount)
*outCount = 0; *outCount = 0;
return NULL; return NULL;
} }
protocols = calloc(listSize, sizeof(Protocol*) + 1); protocols = calloc(listSize, sizeof(Protocol *) + 1);
index = 0; index = 0;
for (list = protocolList; list != NULL; list = list->next) for (list = protocolList; list != NULL; list = list->next)
{ {
memcpy(&protocols[index], list->list, list->count * sizeof(Protocol*)); memcpy(&protocols[index], list->list, list->count * sizeof(Protocol *));
index += list->count; index += list->count;
} }
protocols[listSize] = NULL; protocols[listSize] = NULL;
*outCount = listSize + 1; *outCount = listSize + 1;
return protocols; return protocols;
} }
@ -393,7 +394,7 @@ class_getClassMethod(Class aClass, SEL aSelector)
} }
Ivar Ivar
class_getClassVariable(Class cls, const char* name) class_getClassVariable(Class cls, const char *name)
{ {
assert(0 && "Class variables not implemented"); assert(0 && "Class variables not implemented");
return NULL; return NULL;
@ -406,7 +407,7 @@ class_getInstanceSize(Class cls)
} }
Ivar Ivar
class_getInstanceVariable(Class cls, const char* name) class_getInstanceVariable(Class cls, const char *name)
{ {
struct objc_ivar_list *ivarlist = cls->ivars; struct objc_ivar_list *ivarlist = cls->ivars;
int i; int i;
@ -433,21 +434,21 @@ class_getInstanceVariable(Class cls, const char* name)
const char * const char *
class_getIvarLayout(Class cls) class_getIvarLayout(Class cls)
{ {
return (char*)cls->ivars; return (char *) cls->ivars;
} }
IMP IMP
class_getMethodImplementation(Class cls, SEL name) class_getMethodImplementation(Class cls, SEL name)
{ {
struct objc_object_gnu obj = { cls }; struct objc_object_gnu obj = { cls };
return (IMP)objc_msg_lookup((id)&obj, name); return (IMP) objc_msg_lookup((id) & obj, name);
} }
IMP IMP
class_getMethodImplementation_stret(Class cls, SEL name) class_getMethodImplementation_stret(Class cls, SEL name)
{ {
struct objc_object_gnu obj = { cls }; struct objc_object_gnu obj = { cls };
return (IMP)objc_msg_lookup((id)&obj, name); return (IMP) objc_msg_lookup((id) & obj, name);
} }
const char * const char *
@ -498,8 +499,8 @@ class_replaceMethod(Class cls, SEL name, IMP imp, const char *types)
class_addMethod(cls, name, imp, types); class_addMethod(cls, name, imp, types);
return NULL; return NULL;
} }
old = (IMP)method->method_imp; old = (IMP) method->method_imp;
method->method_imp = (objc_imp_gnu)imp; method->method_imp = (objc_imp_gnu) imp;
return old; return old;
} }
@ -507,21 +508,20 @@ class_replaceMethod(Class cls, SEL name, IMP imp, const char *types)
BOOL BOOL
class_respondsToSelector(Class cls, SEL sel) class_respondsToSelector(Class cls, SEL sel)
{ {
return __objc_responds_to((id)&cls, sel); return __objc_responds_to((id) & cls, sel);
} }
void void
class_setIvarLayout(Class cls, const char *layout) class_setIvarLayout(Class cls, const char *layout)
{ {
struct objc_ivar_list *list = (struct objc_ivar_list*)layout; struct objc_ivar_list *list = (struct objc_ivar_list *) layout;
size_t listsize = sizeof(struct objc_ivar_list) + size_t listsize = sizeof(struct objc_ivar_list) +
sizeof(struct objc_ivar) * (list->ivar_count - 1); sizeof(struct objc_ivar) * (list->ivar_count - 1);
cls->ivars = malloc(listsize); cls->ivars = malloc(listsize);
memcpy(cls->ivars, list, listsize); memcpy(cls->ivars, list, listsize);
} }
OBJC_DEPRECATED OBJC_DEPRECATED Class
Class
class_setSuperclass(Class cls, Class newSuper) class_setSuperclass(Class cls, Class newSuper)
{ {
Class oldSuper = cls->super_class; Class oldSuper = cls->super_class;
@ -622,19 +622,17 @@ method_copyReturnType(Method method)
void void
method_exchangeImplementations(Method m1, Method m2) method_exchangeImplementations(Method m1, Method m2)
{ {
IMP tmp = (IMP)m1->method_imp; IMP tmp = (IMP) m1->method_imp;
m1->method_imp = m2->method_imp; m1->method_imp = m2->method_imp;
m2->method_imp = (objc_imp_gnu)tmp; m2->method_imp = (objc_imp_gnu) tmp;
objc_updateDtableForClassContainingMethod(m1); objc_updateDtableForClassContainingMethod(m1);
objc_updateDtableForClassContainingMethod(m2); objc_updateDtableForClassContainingMethod(m2);
} }
void void
method_getArgumentType(Method method, method_getArgumentType(Method method,
unsigned int index, unsigned int index, char *dst, size_t dst_len)
char *dst,
size_t dst_len)
{ {
const char *types; const char *types;
size_t length; size_t length;
@ -660,7 +658,7 @@ method_getArgumentType(Method method,
IMP IMP
method_getImplementation(Method method) method_getImplementation(Method method)
{ {
return (IMP)method->method_imp; return (IMP) method->method_imp;
} }
SEL SEL
@ -675,7 +673,7 @@ method_getNumberOfArguments(Method method)
const char *types = method->method_types; const char *types = method->method_types;
unsigned int count = 0; unsigned int count = 0;
while('\0' != *types) while ('\0' != *types)
{ {
types = objc_skip_argspec(types); types = objc_skip_argspec(types);
count++; count++;
@ -710,9 +708,9 @@ method_getTypeEncoding(Method method)
IMP IMP
method_setImplementation(Method method, IMP imp) method_setImplementation(Method method, IMP imp)
{ {
IMP old = (IMP)method->method_imp; IMP old = (IMP) method->method_imp;
method->method_imp = (objc_imp_gnu)old; method->method_imp = (objc_imp_gnu) old;
objc_updateDtableForClassContainingMethod(method); objc_updateDtableForClassContainingMethod(method);
return old; return old;
} }
@ -720,18 +718,18 @@ method_setImplementation(Method method, IMP imp)
id id
objc_getClass(const char *name) objc_getClass(const char *name)
{ {
return (id)objc_get_class(name); return (id) objc_get_class(name);
} }
int int
objc_getClassList(Class *buffer, int bufferLen) objc_getClassList(Class * buffer, int bufferLen)
{ {
int count = 0; int count = 0;
if (buffer == NULL) if (buffer == NULL)
{ {
void *state = NULL; void *state = NULL;
while(Nil != objc_next_class(&state)) while (Nil != objc_next_class(&state))
{ {
count++; count++;
} }
@ -754,8 +752,8 @@ objc_getClassList(Class *buffer, int bufferLen)
id id
objc_getMetaClass(const char *name) objc_getMetaClass(const char *name)
{ {
Class cls = (Class)objc_getClass(name); Class cls = (Class) objc_getClass(name);
return cls == Nil ? nil : (id)cls->class_pointer; return cls == Nil ? nil : (id) cls->class_pointer;
} }
id id
@ -774,7 +772,7 @@ id
objc_lookUpClass(const char *name) objc_lookUpClass(const char *name)
{ {
// TODO: Check these are the right way around. // TODO: Check these are the right way around.
return (id)objc_lookup_class(name); return (id) objc_lookup_class(name);
} }
static void static void
@ -789,7 +787,7 @@ freeMethodLists(Class aClass)
for (i = 0; i < methods->method_count; i++) for (i = 0; i < methods->method_count; i++)
{ {
free((void*)methods->method_list[i].method_types); free((void *) methods->method_list[i].method_types);
} }
current = methods; current = methods;
methods = methods->method_next; methods = methods->method_next;
@ -812,8 +810,8 @@ freeIvarLists(Class aClass)
{ {
Ivar ivar = &ivarlist->ivar_list[i]; Ivar ivar = &ivarlist->ivar_list[i];
free((void*)ivar->ivar_type); free((void *) ivar->ivar_type);
free((void*)ivar->ivar_name); free((void *) ivar->ivar_name);
} }
free(ivarlist); free(ivarlist);
} }
@ -848,7 +846,7 @@ safe_remove_from_subclass_list(Class cls)
void void
objc_disposeClassPair(Class cls) objc_disposeClassPair(Class cls)
{ {
Class meta = ((id)cls)->isa; Class meta = ((id) cls)->isa;
// Remove from the runtime system so nothing tries updating the dtable // Remove from the runtime system so nothing tries updating the dtable
// while we are freeing the class. // while we are freeing the class.
@ -901,7 +899,7 @@ objc_allocateClassPair(Class superclass, const char *name, size_t extraBytes)
newClass->class_pointer = metaClass; newClass->class_pointer = metaClass;
// Set the superclass pointer to the name. The runtime will fix this when // Set the superclass pointer to the name. The runtime will fix this when
// the class links are resolved. // the class links are resolved.
newClass->super_class = (Class)superclass->name; newClass->super_class = (Class) superclass->name;
newClass->name = strdup(name); newClass->name = strdup(name);
newClass->info = _CLS_CLASS; newClass->info = _CLS_CLASS;
newClass->dtable = __objc_uninstalled_dtable; newClass->dtable = __objc_uninstalled_dtable;
@ -910,14 +908,30 @@ objc_allocateClassPair(Class superclass, const char *name, size_t extraBytes)
return newClass; return newClass;
} }
Class
objc_allocateMetaClass(Class superclass, size_t extraBytes)
{
Class metaClass = calloc(1, sizeof(struct objc_class) + extraBytes);
// Initialize the metaclass
metaClass->class_pointer = superclass->class_pointer->class_pointer;
metaClass->super_class = superclass->class_pointer;
metaClass->name = strdup(superclass->name);
metaClass->info = _CLS_META;
metaClass->dtable = __objc_uninstalled_dtable;
metaClass->instance_size = sizeof(struct objc_class);
return metaClass;
}
void * void *
object_getIndexedIvars(id obj) object_getIndexedIvars(id obj)
{ {
if (class_isMetaClass(obj->isa)) if (class_isMetaClass(obj->isa))
{ {
return ((char*)obj) + sizeof(struct objc_class); return ((char *) obj) + sizeof(struct objc_class);
} }
return ((char*)obj) + obj->isa->instance_size; return ((char *) obj) + obj->isa->instance_size;
} }
Class Class
@ -935,7 +949,7 @@ object_setClass(id obj, Class cls)
{ {
if (nil != obj) if (nil != obj)
{ {
Class oldClass = obj->isa; Class oldClass = obj->isa;
obj->isa = cls; obj->isa = cls;
return oldClass; return oldClass;
@ -975,43 +989,44 @@ objectNew(id cls)
{ {
newSel = sel_get_uid("new"); newSel = sel_get_uid("new");
} }
newIMP = (IMP)objc_msg_lookup((void*)cls, newSel); newIMP = (IMP) objc_msg_lookup((void *) cls, newSel);
return newIMP((id)cls, newSel); return newIMP((id) cls, newSel);
} }
Protocol * Protocol *
objc_getProtocol(const char *name) objc_getProtocol(const char *name)
{ {
// Protocols are not centrally registered in the GNU runtime. // Protocols are not centrally registered in the GNU runtime.
Protocol *protocol = (Protocol*)(objectNew(objc_getClass("Protocol"))); Protocol *protocol = (Protocol *) (objectNew(objc_getClass("Protocol")));
protocol->protocol_name = (char*)name; protocol->protocol_name = (char *) name;
return protocol; return protocol;
} }
BOOL BOOL
protocol_conformsToProtocol(Protocol *p, Protocol *other) protocol_conformsToProtocol(Protocol * p, Protocol * other)
{ {
return NO; return NO;
} }
struct objc_method_description * struct objc_method_description *
protocol_copyMethodDescriptionList(Protocol *p, protocol_copyMethodDescriptionList(Protocol * p,
BOOL isRequiredMethod, BOOL isInstanceMethod, unsigned int *count) BOOL isRequiredMethod,
BOOL isInstanceMethod, unsigned int *count)
{ {
*count = 0; *count = 0;
return NULL; return NULL;
} }
Protocol ** Protocol **
protocol_copyProtocolList(Protocol *p, unsigned int *count) protocol_copyProtocolList(Protocol * p, unsigned int *count)
{ {
*count = 0; *count = 0;
return NULL; return NULL;
} }
const char * const char *
protocol_getName(Protocol *p) protocol_getName(Protocol * p)
{ {
if (NULL != p) if (NULL != p)
{ {
@ -1021,14 +1036,13 @@ protocol_getName(Protocol *p)
} }
BOOL BOOL
protocol_isEqual(Protocol *p, Protocol *other) protocol_isEqual(Protocol * p, Protocol * other)
{ {
if (NULL == p || NULL == other) if (NULL == p || NULL == other)
{ {
return NO; return NO;
} }
if (p == other if (p == other || 0 == strcmp(p->protocol_name, other->protocol_name))
|| 0 == strcmp(p->protocol_name, other->protocol_name))
{ {
return YES; return YES;
} }
@ -1038,14 +1052,16 @@ protocol_isEqual(Protocol *p, Protocol *other)
const char * const char *
sel_getName(SEL sel) sel_getName(SEL sel)
{ {
if (sel == 0) return "<null selector>"; if (sel == 0)
return "<null selector>";
return sel_get_name(sel); return sel_get_name(sel);
} }
SEL SEL
sel_getUid(const char *selName) sel_getUid(const char *selName)
{ {
if (selName == 0) return 0; if (selName == 0)
return 0;
return sel_get_uid(selName); return sel_get_uid(selName);
} }
@ -1058,7 +1074,7 @@ sel_isEqual(SEL sel1, SEL sel2)
SEL SEL
sel_registerName(const char *selName) sel_registerName(const char *selName)
{ {
if (selName == 0) return 0; if (selName == 0)
return 0;
return sel_register_name(selName); return sel_register_name(selName);
} }

View file

@ -1,6 +1,7 @@
#include <stdint.h> #include <stdint.h>
#include <stddef.h> #include <stddef.h>
#include <sys/types.h> #include <sys/types.h>
#include "Availability.h"
#if defined(ERROR_UNSUPPORTED_RUNTIME_FUNCTIONS) #if defined(ERROR_UNSUPPORTED_RUNTIME_FUNCTIONS)
# define OBJC_GNU_RUNTIME_UNSUPPORTED(x) \ # define OBJC_GNU_RUNTIME_UNSUPPORTED(x) \
@ -199,7 +200,11 @@ const char * method_getTypeEncoding(Method method);
IMP method_setImplementation(Method method, IMP imp); IMP method_setImplementation(Method method, IMP imp);
Class objc_allocateClassPair(Class superclass, const char *name, size_t extraBytes); Class
objc_allocateClassPair(Class superclass, const char *name, size_t extraBytes);
OBJC_NONPORTABLE
Class objc_allocateMetaClass(Class superclass, size_t extraBytes);
void objc_disposeClassPair(Class cls); void objc_disposeClassPair(Class cls);

View file

@ -53,19 +53,32 @@ findLockClass(id obj)
static inline Class static inline Class
initLockObject(id obj) initLockObject(id obj)
{ {
char nameBuffer[40];
Class lockClass; Class lockClass;
const char *types; const char *types;
pthread_mutex_t *lock; pthread_mutex_t *lock;
pthread_mutexattr_t attr; pthread_mutexattr_t attr;
snprintf(nameBuffer, 39, "hiddenlockClass%lld", lockClassId++); if (class_isMetaClass(obj->isa))
lockClass = objc_allocateClassPair(obj->isa, nameBuffer, {
sizeof(pthread_mutex_t)); lockClass = objc_allocateMetaClass(obj, sizeof(pthread_mutex_t));
}
else
{
char nameBuffer[40];
snprintf(nameBuffer, 39, "hiddenlockClass%lld", lockClassId++);
lockClass = objc_allocateClassPair(obj->isa, nameBuffer,
sizeof(pthread_mutex_t));
}
types = method_getTypeEncoding(class_getInstanceMethod(obj->isa, types = method_getTypeEncoding(class_getInstanceMethod(obj->isa,
@selector(dealloc))); @selector(dealloc)));
class_addMethod(lockClass, @selector(dealloc), (IMP)deallocLockClass, types); class_addMethod(lockClass, @selector(dealloc), (IMP)deallocLockClass, types);
objc_registerClassPair(lockClass);
if (!class_isMetaClass(obj->isa))
{
objc_registerClassPair(lockClass);
}
lock = object_getIndexedIvars(lockClass); lock = object_getIndexedIvars(lockClass);
pthread_mutexattr_init(&attr); pthread_mutexattr_init(&attr);