Support for The Stupidest Idea Ever Introduced To The GNU Objective-C Runtime AKA Typed Selectors, which somehow got carried over to clang too.

This commit is contained in:
Christopher Lloyd 2013-05-28 23:59:15 -04:00
parent bd1ef43a46
commit 97e0ea5eb8
6 changed files with 181 additions and 87 deletions

View File

@ -247,14 +247,14 @@ static OBJCArray *OBJCModuleQueue(){
static void OBJCSymbolTableRegisterSelectors(OBJCSymbolTable *symbolTable){
SEL *selectorReferences=symbolTable->selectorReferences;
if(selectorReferences!=NULL){
while(*selectorReferences!=NULL){
*selectorReferences=(SEL)sel_registerNameNoCopy((const char *)*selectorReferences);
selectorReferences++;
objc_selector_internal *selectorReferences=symbolTable->selectorReferences;
if(selectorReferences!=NULL){
while(objc_getSelectorReferenceName(selectorReferences)!=NULL){
objc_setSelectorReferenceName(&selectorReferences,sel_registerNameNoCopy(objc_getSelectorReferenceName(selectorReferences)));
selectorReferences++;
}
}
}
}
void OBJCAddToUnResolvedClasses(Class class) {
@ -471,47 +471,47 @@ static void OBJCSymbolTableRegisterCategories(OBJCSymbolTable *symbolTable){
// GNU style for now
static void OBJCSymbolTableRegisterStringsIfNeeded(OBJCSymbolTable *symbolTable){
static OBJCArray *unlinkedObjects=NULL;
unsigned long offset=symbolTable->classCount+symbolTable->categoryCount;
OBJCStaticInstanceList **listOfLists=symbolTable->definitions[offset];
if(unlinkedObjects!=NULL){
int count=unlinkedObjects->count;
while(--count>=0){
OBJCStaticInstanceList *staticInstances=OBJCArrayItemAtIndex(unlinkedObjects,count);
Class class=objc_lookUpClass(staticInstances->name);
if(class!=Nil){
unsigned i;
for(i=0;staticInstances->instances[i]!= nil;i++)
staticInstances->instances[i]->isa = class;
OBJCArrayRemoveItemAtIndex(unlinkedObjects,count);
}
}
}
if(listOfLists!=NULL){
for (;*listOfLists != NULL;listOfLists++) {
OBJCStaticInstanceList *staticInstances=*listOfLists;
Class class=objc_lookUpClass(staticInstances->name);
unsigned i;
if(class!=Nil){
for(i=0;staticInstances->instances[i]!= nil;i++)
staticInstances->instances[i]->isa = class;
}
else {
if(unlinkedObjects==NULL)
unlinkedObjects=OBJCArrayNew();
OBJCArrayAdd(unlinkedObjects,staticInstances);
}
static OBJCArray *unlinkedObjects=NULL;
unsigned long offset=symbolTable->classCount+symbolTable->categoryCount;
OBJCStaticInstanceList **listOfLists=symbolTable->definitions[offset];
if(unlinkedObjects!=NULL){
int count=unlinkedObjects->count;
while(--count>=0){
OBJCStaticInstanceList *staticInstances=OBJCArrayItemAtIndex(unlinkedObjects,count);
Class class=objc_lookUpClass(staticInstances->name);
if(class!=Nil) {
unsigned i;
for(i=0;staticInstances->instances[i]!= nil;i++)
staticInstances->instances[i]->isa = class;
OBJCArrayRemoveItemAtIndex(unlinkedObjects,count);
}
}
}
if(listOfLists!=NULL){
for (;*listOfLists != NULL;listOfLists++) {
OBJCStaticInstanceList *staticInstances=*listOfLists;
Class class=objc_lookUpClass(staticInstances->name);
unsigned i;
if(class!=Nil){
for(i=0;staticInstances->instances[i]!= nil;i++)
staticInstances->instances[i]->isa = class;
}
else {
if(unlinkedObjects==NULL)
unlinkedObjects=OBJCArrayNew();
OBJCArrayAdd(unlinkedObjects,staticInstances);
}
}
}
}
}
static void OBJCSymbolTableRegisterProtocolsIfNeeded(OBJCSymbolTable *symbolTable){

View File

@ -59,7 +59,7 @@ void OBJCRegisterProtocol(OBJCProtocolTemplate *template) {
if(instanceMethods!=NULL)
for(i=0;i<instanceMethods->count;i++)
if(instanceMethods->list[i].name==selector)
if(instanceMethods->list[i].name==sel_getSelector(selector))
return &instanceMethods->list[i];
list=childProtocols;
@ -70,7 +70,7 @@ void OBJCRegisterProtocol(OBJCProtocolTemplate *template) {
unsigned k;
for(k=0;k<list->list[j]->instanceMethods->count;k++)
if(list->list[j]->instanceMethods->list[k].name==selector)
if(list->list[j]->instanceMethods->list[k].name==sel_getSelector(selector))
return &list->list[j]->instanceMethods->list[k];
}
list=list->next;
@ -85,7 +85,7 @@ void OBJCRegisterProtocol(OBJCProtocolTemplate *template) {
if(classMethods!=NULL)
for(i=0;i<classMethods->count;i++)
if(classMethods->list[i].name==selector)
if(classMethods->list[i].name==sel_getSelector(selector))
return &classMethods->list[i];
list=childProtocols;
@ -96,7 +96,7 @@ void OBJCRegisterProtocol(OBJCProtocolTemplate *template) {
unsigned k;
for (k=0;k<list->list[j]->classMethods->count;k++)
if(list->list[j]->classMethods->list[k].name==selector)
if(list->list[j]->classMethods->list[k].name==sel_getSelector(selector))
return &list->list[j]->classMethods->list[k];
}
list=list->next;

View File

@ -58,6 +58,10 @@ id objc_lookUpClass(const char *className) {
return result;
}
id objc_lookup_class(const char *className) {
return objc_lookUpClass(className);
}
id objc_getClass(const char *name) {
id result;
@ -240,9 +244,9 @@ Ivar class_getClassVariable(Class cls,const char *name) {
static inline struct objc_method *OBJCLookupUniqueIdInMethodList(struct objc_method_list *list,SEL uniqueId){
int i;
for(i=0;i<list->method_count;i++){
if(((SEL)list->method_list[i].method_name)==uniqueId)
if(((SEL)list->method_list[i].method_name)==sel_getSelector(uniqueId))
return list->method_list+i;
}
@ -769,7 +773,7 @@ static void OBJCCreateCacheForClass(Class class){
}
void OBJCRegisterClass(Class class) {
{
struct objc_class* futureClass=OBJCHashValueForKey(OBJCFutureClassTable(), class->name);
@ -778,7 +782,7 @@ void OBJCRegisterClass(Class class) {
class=futureClass;
}
}
pthread_mutex_lock(&classTableLock);
OBJCHashInsertValueForKey(OBJCClassTable(), class->name, class);
pthread_mutex_unlock(&classTableLock);
@ -836,18 +840,18 @@ void OBJCRegisterCategoryInClass(Category category,Class class) {
}
static void OBJCLinkClass(Class class) {
if(!(class->info&CLASS_INFO_LINKED)){
Class superClass=objc_lookUpClass((const char *)class->super_class);
Class metaRoot=objc_lookUpClass((const char *)class->isa->isa);
if(superClass!=NULL && metaRoot!= NULL){
class->super_class=superClass;
class->info|=CLASS_INFO_LINKED;
class->isa->super_class=class->super_class->isa;
class->isa->info|=CLASS_INFO_LINKED;
class->isa->isa=metaRoot->isa;
}
}
if(!(class->info&CLASS_INFO_LINKED)){
Class superClass=(class->super_class==NULL)?NULL:objc_lookUpClass((const char *)class->super_class);
Class metaRoot=(class->isa->isa==NULL)?NULL:objc_lookUpClass((const char *)class->isa->isa);
if(superClass!=NULL){
class->super_class=superClass;
class->info|=CLASS_INFO_LINKED;
class->isa->super_class=class->super_class->isa;
class->isa->info|=CLASS_INFO_LINKED;
class->isa->isa=(metaRoot==NULL)?NULL:metaRoot->isa;
}
}
}
void OBJCLinkClassTable(void) {
@ -910,10 +914,10 @@ IMP OBJCInitializeLookupAndCacheUniqueIdForObject(id object,SEL selector){
Class checkInit=(class->info&CLASS_INFO_META)?(Class)object:class;
OBJCInitializeClass(checkInit);
}
IMP result=class_getMethodImplementation(class,selector);
if(result==NULL){
IMP result=class_getMethodImplementation(class,selector);
if(result==NULL){
result=objc_forwardHandler;
}
return result;

View File

@ -27,8 +27,8 @@ IMP objc_msg_lookup(id object,SEL selector) {
do{
struct objc_method *check=checkEntry->method;
if(((SEL)check->method_name)==selector)
if(((SEL)check->method_name)==sel_getSelector(selector))
return check->method_imp;
checkEntry=((void *)checkEntry)+checkEntry->offsetToNextEntry;
@ -45,7 +45,7 @@ IMP objc_msg_lookup_super(struct objc_super *super,SEL selector) {
do{
struct objc_method *check=checkEntry->method;
if(((SEL)check->method_name)==selector)
if(((SEL)check->method_name)==sel_getSelector(selector))
return check->method_imp;
checkEntry=((void *)checkEntry)+checkEntry->offsetToNextEntry;

View File

@ -9,5 +9,50 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
#import <objc/objc.h>
#import <objc/objc-class.h>
OBJC_EXPORT SEL sel_registerNameNoCopy(const char *name);
OBJC_EXPORT const char *sel_registerNameNoCopy(const char *name);
OBJC_EXPORT SEL sel_registerSelectorNoCopyName(const char *name);
#ifdef OBJC_TYPED_SELECTORS
typedef struct {
const char *name;
const char *types;
} objc_selector_internal;
static inline const char *objc_getSelectorReferenceName(objc_selector_internal *ref) {
return ref->name;
}
static inline void objc_setSelectorReferenceName(objc_selector_internal **ref,const char *name) {
(*ref)->name=name;
}
static inline SEL sel_getSelector(SEL selector) {
if(selector==NULL)
return selector;
struct {
SEL selector;
} *typed=(void *)selector;
return typed->selector;
}
#else
typedef SEL objc_selector_internal;
static inline const char *objc_getSelectorReferenceName(objc_selector_internal *ref) {
return *ref;
}
static inline void objc_setSelectorReferenceName(objc_selector_internal **ref,const char *name) {
**ref=name;
}
static inline SEL sel_getSelector(SEL selector) {
return selector;
}
#endif

View File

@ -15,20 +15,45 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
#define INITIAL_SELECTOR_TABLE_SIZE 4096 // Big System has about 3700 selectors
static OBJCHashTable *nameToNumber=NULL;
static OBJCHashTable *nameToSelector=NULL;
SEL sel_registerNameNoCopy(const char *name){
const char *sel_registerNameNoCopy(const char *name) {
const char *result;
if(nameToNumber==NULL)
nameToNumber=OBJCCreateHashTable(INITIAL_SELECTOR_TABLE_SIZE);
result=OBJCHashValueForKey(nameToNumber,name);
if(result==NULL){
result=OBJCHashInsertValueForKey(nameToNumber,name,name);
}
return result;
}
SEL sel_registerSelectorNoCopyName(const char *name){
#ifndef OBJC_TYPED_SELECTORS
return sel_registerNameNoCopy(name);
#else
SEL result;
if(nameToNumber==NULL)
nameToNumber=OBJCCreateHashTable(INITIAL_SELECTOR_TABLE_SIZE);
if(nameToSelector==NULL)
nameToSelector=OBJCCreateHashTable(INITIAL_SELECTOR_TABLE_SIZE);
result=(SEL)OBJCHashValueForKey(nameToNumber,name);
result=(SEL)OBJCHashValueForKey(nameToSelector,name);
if(result==NULL){
result=(SEL)OBJCHashInsertValueForKey(nameToNumber,name, (char*)name);
objc_selector_internal *ughp;
ughp=objc_malloc(sizeof(objc_selector_internal));
ughp->name=sel_registerNameNoCopy(name);
result=(SEL)OBJCHashInsertValueForKey(nameToSelector,(char*)name,ughp);
}
return result;
#endif
}
@ -38,30 +63,50 @@ const char *sel_getName(SEL selector) {
if(nameToNumber==NULL)
return NULL;
selector=sel_getSelector(selector);
return (const char*)OBJCHashValueForKey(nameToNumber, selector);
}
SEL sel_getUid(const char *selectorName) {
SEL result;
SEL result;
if(nameToNumber==NULL)
#ifndef OBJC_TYPED_SELECTORS
if(nameToNumber==NULL)
result=NULL;
else
result=(SEL)OBJCHashValueForKey(nameToNumber,selectorName);
if(result==NULL){
char *copy=objc_malloc(sizeof(char)*(strlen(selectorName)+1));
strcpy(copy,selectorName);
result=(SEL)sel_registerNameNoCopy(copy);
}
#else
if(nameToSelector==NULL)
result=NULL;
else
result=(SEL)OBJCHashValueForKey(nameToNumber,selectorName);
result=(SEL)OBJCHashValueForKey(nameToSelector,selectorName);
if(result==NULL){
if(result==NULL){
char *copy=objc_malloc(sizeof(char)*(strlen(selectorName)+1));
strcpy(copy,selectorName);
result=(SEL)sel_registerNameNoCopy(copy);
result=sel_registerSelectorNoCopyName(copy);
}
#endif
return result;
}
BOOL sel_isEqual(SEL selector,SEL other) {
return (selector==other)?YES:NO;
selector=sel_getSelector(selector);
other=sel_getSelector(other);
return (selector==other)?YES:NO;
}
SEL sel_registerName(const char *cString){