Commit a39d31bc by Kresten Krab Thorup

This patch makes selectors in the Objective-C language be pointers to a struct { void *sel_id...

        This patch makes selectors in the Objective-C language be pointers
        to a struct { void *sel_id, char *sel_types }, where the sel_types
        element is the type encoding of the method arguments.

From-SVN: r7622
parent 7a1dd323
/* Interface for the Object class for Objective-C. /* Interface for the Object class for Objective-C.
Copyright (C) 1993 Free Software Foundation, Inc. Copyright (C) 1993, 1994 Free Software Foundation, Inc.
This file is part of GNU CC. This file is part of GNU CC.
...@@ -93,8 +93,8 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ ...@@ -93,8 +93,8 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
- - perform:(SEL)aSel with:anObject1 with:anObject2; - - perform:(SEL)aSel with:anObject1 with:anObject2;
/* Forwarding */ /* Forwarding */
- - forward:(SEL)aSel :(arglist_t)argFrame; - (retval_t)forward:(SEL)aSel :(arglist_t)argFrame;
- - performv:(SEL)aSel :(arglist_t)argFrame; - (retval_t)performv:(SEL)aSel :(arglist_t)argFrame;
/* Posing */ /* Posing */
+ + poseAs:(Class*)aClassObject; + + poseAs:(Class*)aClassObject;
...@@ -112,14 +112,10 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ ...@@ -112,14 +112,10 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
/* Archiving */ /* Archiving */
+ (int)version; + (int)version;
+ + setVersion:(int)aVersion; + + setVersion:(int)aVersion;
#ifndef __alpha__ /* TypedStream not supported on alpha yet. */
+ (int)streamVersion: (TypedStream*)aStream; + (int)streamVersion: (TypedStream*)aStream;
- - read: (TypedStream*)aStream; - - read: (TypedStream*)aStream;
- - write: (TypedStream*)aStream; - - write: (TypedStream*)aStream;
#endif
- - awake; - - awake;
@end @end
......
...@@ -132,6 +132,27 @@ objc_get_class (const char *name) ...@@ -132,6 +132,27 @@ objc_get_class (const char *name)
abort(); abort();
} }
/* This function provides a way to enumerate all the classes in the
executable. Pass *ENUM_STATE == NULL to start the enumeration. The
function will return 0 when there are no more classes.
For example:
id class;
void *es = NULL;
while ((class = objc_next_class(&es)))
... do something with class;
*/
Class*
objc_next_class(void **enum_state)
{
/* make sure the table is there */
assert(__objc_class_hash);
*(node_ptr*)enum_state =
hash_next(__objc_class_hash, *(node_ptr*)enum_state);
if (*(node_ptr*)enum_state)
return (*(node_ptr*)enum_state)->value;
return (Class*)0;
}
/* Resolve super/subclass links for all classes. The only thing we /* Resolve super/subclass links for all classes. The only thing we
can be sure of is that the class_pointer for class objects point can be sure of is that the class_pointer for class objects point
...@@ -217,6 +238,9 @@ void __objc_resolve_class_links() ...@@ -217,6 +238,9 @@ void __objc_resolve_class_links()
Class* Class*
class_pose_as (Class* impostor, Class* super_class) class_pose_as (Class* impostor, Class* super_class)
{ {
node_ptr node;
Class* class1;
if (!CLS_ISRESOLV (impostor)) if (!CLS_ISRESOLV (impostor))
__objc_resolve_class_links (); __objc_resolve_class_links ();
...@@ -230,19 +254,13 @@ class_pose_as (Class* impostor, Class* super_class) ...@@ -230,19 +254,13 @@ class_pose_as (Class* impostor, Class* super_class)
{ {
Class **subclass = &(super_class->subclass_list); Class **subclass = &(super_class->subclass_list);
BOOL super_is_base_class = NO;
/* move subclasses of super_class to impostor */ /* move subclasses of super_class to impostor */
while (*subclass) while (*subclass)
{ {
Class *nextSub = (*subclass)->sibling_class; Class *nextSub = (*subclass)->sibling_class;
/* this happens when super_class is a base class */ if (*subclass != impostor)
if (*subclass == CLASSOF (super_class))
{
super_is_base_class = YES;
}
else if (*subclass != impostor)
{ {
Class *sub = *subclass; Class *sub = *subclass;
...@@ -251,11 +269,18 @@ class_pose_as (Class* impostor, Class* super_class) ...@@ -251,11 +269,18 @@ class_pose_as (Class* impostor, Class* super_class)
sub->super_class = impostor; sub->super_class = impostor;
impostor->subclass_list = sub; impostor->subclass_list = sub;
/* It will happen that SUB is not a class object if it is
the top of the meta class hierachy chain. (root
meta-class objects inherit theit class object) If that is
the case... dont mess with the meta-meta class. */
if (CLS_ISCLASS (sub))
{
/* meta classes */ /* meta classes */
CLASSOF (sub)->sibling_class = CLASSOF (impostor)->subclass_list; CLASSOF (sub)->sibling_class = CLASSOF (impostor)->subclass_list;
CLASSOF (sub)->super_class = CLASSOF (impostor); CLASSOF (sub)->super_class = CLASSOF (impostor);
CLASSOF (impostor)->subclass_list = CLASSOF (sub); CLASSOF (impostor)->subclass_list = CLASSOF (sub);
} }
}
*subclass = nextSub; *subclass = nextSub;
} }
...@@ -267,66 +292,31 @@ class_pose_as (Class* impostor, Class* super_class) ...@@ -267,66 +292,31 @@ class_pose_as (Class* impostor, Class* super_class)
/* set impostor to have no sibling classes */ /* set impostor to have no sibling classes */
impostor->sibling_class = 0; impostor->sibling_class = 0;
CLASSOF (impostor)->sibling_class = 0; CLASSOF (impostor)->sibling_class = 0;
/* impostor has a sibling... */
if (super_is_base_class)
{
CLASSOF (super_class)->sibling_class = 0;
impostor->sibling_class = CLASSOF (super_class);
}
} }
/* check relationship of impostor and super_class */ /* check relationship of impostor and super_class is kept. */
assert (impostor->super_class == super_class); assert (impostor->super_class == super_class);
assert (CLASSOF (impostor)->super_class == CLASSOF (super_class)); assert (CLASSOF (impostor)->super_class == CLASSOF (super_class));
/* by now, the re-organization of the class hierachy /* This is how to update the lookup table. Regardless of
is done. We only need to update various tables. */ what the keys of the hashtable is, change all values that are
suprecalss into impostor. */
/* First, we change the names in the hash table. for (node = hash_next (__objc_class_hash, NULL); node;
This will change the behavior of objc_get_class () */ node = hash_next (__objc_class_hash, node))
{ {
char* buffer = (char*) __objc_xmalloc(strlen (super_class->name) + 2); class1 = (Class*)node->value;
if (class1 == super_class)
strcpy (buffer+1, super_class->name);
buffer[0] = '*';
/* keep on prepending '*' until the name is unique */
while (hash_value_for_key (__objc_class_hash, buffer))
{ {
char *bbuffer = (char*) __objc_xmalloc (strlen (buffer)+2); node->value = impostor; /* change hash table value */
strcpy (bbuffer+1, buffer);
bbuffer[0] = '*';
free (buffer);
buffer = bbuffer;
} }
hash_remove (__objc_class_hash, super_class->name);
hash_add (&__objc_class_hash, buffer, super_class);
hash_add (&__objc_class_hash, super_class->name, impostor);
/* Note that -name and +name will still respond with
the same strings as before. This way any
-isKindOfGivenName: will always work. */
} }
/* next, we update the dispatch tables... */ /* next, we update the dispatch tables... */
{ __objc_update_dispatch_table_for_class (CLASSOF (impostor));
Class *subclass; __objc_update_dispatch_table_for_class (impostor);
for (subclass = impostor->subclass_list;
subclass; subclass = subclass->sibling_class)
{
/* we use the opportunity to check what we did */
assert (subclass->super_class == impostor);
assert (CLASSOF (subclass)->super_class == CLASSOF (impostor));
__objc_update_dispatch_table_for_class (CLASSOF (subclass));
__objc_update_dispatch_table_for_class (subclass);
}
}
return impostor; return impostor;
} }
...@@ -35,6 +35,10 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ ...@@ -35,6 +35,10 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
({ typeof(X) __x = (X), __y = (Y); \ ({ typeof(X) __x = (X), __y = (Y); \
(__x < __y ? __x : __y); }) (__x < __y ? __x : __y); })
#define ROUND(V, A) \
({ typeof(V) __v=(V); typeof(A) __a=(A); \
__a*((__v+__a-1)/__a); })
static inline int static inline int
atoi (const char* str) atoi (const char* str)
...@@ -121,8 +125,7 @@ objc_sizeof_type(const char* type) ...@@ -121,8 +125,7 @@ objc_sizeof_type(const char* type)
while (*type != _C_STRUCT_E); while (*type != _C_STRUCT_E);
{ {
align = objc_alignof_type (type); /* padd to alignment */ align = objc_alignof_type (type); /* padd to alignment */
if ((acc_size % align) != 0) acc_size += ROUND (acc_size, align);
acc_size += align - (acc_size % align);
acc_size += objc_sizeof_type (type); /* add component size */ acc_size += objc_sizeof_type (type); /* add component size */
type = objc_skip_typespec (type); /* skip component */ type = objc_skip_typespec (type); /* skip component */
} }
...@@ -244,11 +247,7 @@ objc_aligned_size (const char* type) ...@@ -244,11 +247,7 @@ objc_aligned_size (const char* type)
{ {
int size = objc_sizeof_type (type); int size = objc_sizeof_type (type);
int align = objc_alignof_type (type); int align = objc_alignof_type (type);
return ROUND (size, align);
if ((size % align) != 0)
return size + align - (size % align);
else
return size;
} }
/* /*
...@@ -262,10 +261,7 @@ objc_promoted_size (const char* type) ...@@ -262,10 +261,7 @@ objc_promoted_size (const char* type)
int size = objc_sizeof_type (type); int size = objc_sizeof_type (type);
int wordsize = sizeof (void*); int wordsize = sizeof (void*);
if ((size % wordsize) != 0) return ROUND (size, wordsize);
return size + wordsize - (size % wordsize);
else
return size;
} }
/* /*
......
...@@ -39,6 +39,8 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ ...@@ -39,6 +39,8 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#define EXPANSION(cache) \ #define EXPANSION(cache) \
((cache)->size * 2) ((cache)->size * 2)
void *__objc_xcalloc (size_t, size_t);
cache_ptr cache_ptr
hash_new (unsigned int size, hash_func_type hash_func, hash_new (unsigned int size, hash_func_type hash_func,
compare_func_type compare_func) compare_func_type compare_func)
......
...@@ -28,7 +28,7 @@ You should have received a copy of the GNU General Public License along with ...@@ -28,7 +28,7 @@ You should have received a copy of the GNU General Public License along with
/* The version number of this runtime. This must match the number /* The version number of this runtime. This must match the number
defined in gcc (objc-act.c) */ defined in gcc (objc-act.c) */
#define OBJC_VERSION 5 #define OBJC_VERSION 6
#define PROTOCOL_VERSION 2 #define PROTOCOL_VERSION 2
/* This list contains all modules currently loaded into the runtime */ /* This list contains all modules currently loaded into the runtime */
...@@ -49,6 +49,11 @@ static void __objc_class_add_protocols (Class*, struct objc_protocol_list*); ...@@ -49,6 +49,11 @@ static void __objc_class_add_protocols (Class*, struct objc_protocol_list*);
/* Is all categories/classes resolved? */ /* Is all categories/classes resolved? */
BOOL __objc_dangling_categories = NO; BOOL __objc_dangling_categories = NO;
extern SEL
__sel_register_typed_name (const char *name, const char *types,
struct objc_selector *orig);
/* This function is called by constructor functions generated for each /* This function is called by constructor functions generated for each
module compiled. (_GLOBAL_$I$...) The purpose of this function is to module compiled. (_GLOBAL_$I$...) The purpose of this function is to
gather the module pointers so that they may be processed by the gather the module pointers so that they may be processed by the
...@@ -70,7 +75,7 @@ __objc_exec_class (Module_t module) ...@@ -70,7 +75,7 @@ __objc_exec_class (Module_t module)
struct objc_list** cell; struct objc_list** cell;
/* The table of selector references for this module */ /* The table of selector references for this module */
SEL *selectors = symtab->refs; SEL selectors = symtab->refs;
/* dummy counter */ /* dummy counter */
int i; int i;
...@@ -91,6 +96,19 @@ __objc_exec_class (Module_t module) ...@@ -91,6 +96,19 @@ __objc_exec_class (Module_t module)
/* Save the module pointer for later processing. (not currently used) */ /* Save the module pointer for later processing. (not currently used) */
__objc_module_list = list_cons(module, __objc_module_list); __objc_module_list = list_cons(module, __objc_module_list);
/* Replace referenced selectors from names to SEL's. */
if (selectors)
{
for (i = 0; selectors[i].sel_id; ++i)
{
const char *name, *type;
name = (char*)selectors[i].sel_id;
type = (char*)selectors[i].sel_types;
__sel_register_typed_name (name, type,
(struct objc_selector*)&(selectors[i]));
}
}
/* Parse the classes in the load module and gather selector information. */ /* Parse the classes in the load module and gather selector information. */
DEBUG_PRINTF ("gathering selectors from module: %s\n", module->name); DEBUG_PRINTF ("gathering selectors from module: %s\n", module->name);
for (i = 0; i < symtab->cls_def_cnt; ++i) for (i = 0; i < symtab->cls_def_cnt; ++i)
...@@ -117,13 +135,6 @@ __objc_exec_class (Module_t module) ...@@ -117,13 +135,6 @@ __objc_exec_class (Module_t module)
__objc_init_protocols (class->protocols); __objc_init_protocols (class->protocols);
} }
/* Replace referenced selectors from names to SEL's. */
if (selectors)
{
for (i = 0; selectors[i]; ++i)
selectors[i] = sel_register_name ((const char *) selectors[i]);
}
/* Process category information from the module. */ /* Process category information from the module. */
for (i = 0; i < symtab->cat_def_cnt; ++i) for (i = 0; i < symtab->cat_def_cnt; ++i)
{ {
...@@ -166,7 +177,7 @@ __objc_exec_class (Module_t module) ...@@ -166,7 +177,7 @@ __objc_exec_class (Module_t module)
categories to objects. */ categories to objects. */
for (cell = &unclaimed_categories; for (cell = &unclaimed_categories;
*cell; *cell;
*cell && ((cell = &(*cell)->tail))) ({ if (*cell) cell = &(*cell)->tail; }))
{ {
Category_t category = (*cell)->head; Category_t category = (*cell)->head;
Class* class = objc_lookup_class (category->class_name); Class* class = objc_lookup_class (category->class_name);
...@@ -209,7 +220,7 @@ static void init_check_module_version(Module_t module) ...@@ -209,7 +220,7 @@ static void init_check_module_version(Module_t module)
if ((module->version != OBJC_VERSION) || (module->size != sizeof (Module))) if ((module->version != OBJC_VERSION) || (module->size != sizeof (Module)))
{ {
fprintf (stderr, "Module %s version %d doesn't match runtime %d\n", fprintf (stderr, "Module %s version %d doesn't match runtime %d\n",
module->name, module->version, OBJC_VERSION); module->name, (int)module->version, OBJC_VERSION);
if(module->version > OBJC_VERSION) if(module->version > OBJC_VERSION)
fprintf (stderr, "Runtime (libobjc.a) is out of date\n"); fprintf (stderr, "Runtime (libobjc.a) is out of date\n");
else if (module->version < OBJC_VERSION) else if (module->version < OBJC_VERSION)
...@@ -255,7 +266,7 @@ __objc_init_protocols (struct objc_protocol_list* protos) ...@@ -255,7 +266,7 @@ __objc_init_protocols (struct objc_protocol_list* protos)
{ {
fprintf (stderr, fprintf (stderr,
"Version %d doesn't match runtime protocol version %d\n", "Version %d doesn't match runtime protocol version %d\n",
((size_t)protos->list[i]->class_pointer), (int)((char*)protos->list[i]->class_pointer-(char*)0),
PROTOCOL_VERSION); PROTOCOL_VERSION);
abort (); abort ();
} }
......
...@@ -30,6 +30,12 @@ void objc_error(id object, const char* fmt, va_list); ...@@ -30,6 +30,12 @@ void objc_error(id object, const char* fmt, va_list);
void (*_objc_error)(id, const char*, va_list) = objc_error; void (*_objc_error)(id, const char*, va_list) = objc_error;
#ifdef __alpha__
#include <stdlib.h>
extern int write (int, const char*, int);
extern size_t strlen (const char*);
#endif
void void
objc_error(id object, const char* fmt, va_list ap) objc_error(id object, const char* fmt, va_list ap)
{ {
...@@ -40,7 +46,7 @@ objc_error(id object, const char* fmt, va_list ap) ...@@ -40,7 +46,7 @@ objc_error(id object, const char* fmt, va_list ap)
volatile void volatile void
objc_fatal(const char* msg) objc_fatal(const char* msg)
{ {
write(2, msg, (size_t)strlen((char*)msg)); write(2, msg, (int)strlen((const char*)msg));
abort(); abort();
} }
...@@ -65,8 +71,12 @@ __objc_xrealloc(void* mem, size_t size) ...@@ -65,8 +71,12 @@ __objc_xrealloc(void* mem, size_t size)
void* void*
__objc_xcalloc(size_t nelem, size_t size) __objc_xcalloc(size_t nelem, size_t size)
{ {
void* res = (void*)calloc(nelem, size); #ifdef __alpha__
extern bzero (void *, size_t);
#endif
void* res = (void*)malloc(nelem * size);
if(!res) if(!res)
objc_fatal("Virtual memory exhausted\n"); objc_fatal("Virtual memory exhausted\n");
bzero (res, nelem * size);
return res; return res;
} }
...@@ -44,8 +44,6 @@ struct objc_method_description ...@@ -44,8 +44,6 @@ struct objc_method_description
char *types; /* type encoding */ char *types; /* type encoding */
}; };
/* Filer types used to describe Ivars and Methods. */ /* Filer types used to describe Ivars and Methods. */
#define _C_ID '@' #define _C_ID '@'
#define _C_CLASS '#' #define _C_CLASS '#'
...@@ -92,7 +90,7 @@ extern BOOL objc_trace; ...@@ -92,7 +90,7 @@ extern BOOL objc_trace;
*/ */
typedef struct objc_symtab { typedef struct objc_symtab {
unsigned long sel_ref_cnt; /* Unknown. */ unsigned long sel_ref_cnt; /* Unknown. */
SEL *refs; /* Unknown. */ SEL refs; /* Unknown. */
unsigned short cls_def_cnt; /* Number of classes compiled unsigned short cls_def_cnt; /* Number of classes compiled
(defined) in the module. */ (defined) in the module. */
unsigned short cat_def_cnt; /* Number of categories unsigned short cat_def_cnt; /* Number of categories
...@@ -303,12 +301,23 @@ Class* objc_get_class(const char *name); ...@@ -303,12 +301,23 @@ Class* objc_get_class(const char *name);
Class* objc_lookup_class(const char *name); Class* objc_lookup_class(const char *name);
Class* objc_next_class(void **enum_state);
const char *sel_get_name(SEL selector); const char *sel_get_name(SEL selector);
const char *sel_get_type(SEL selector);
SEL sel_get_uid(const char *name); SEL sel_get_uid(const char *name);
SEL sel_get_any_uid(const char *name);
SEL sel_get_typed_uid(const char *name, const char*);
SEL sel_register_name(const char *name); SEL sel_register_name(const char *name);
SEL sel_register_typed_name(const char *name, const char*type);
BOOL sel_is_mapped (SEL aSel); BOOL sel_is_mapped (SEL aSel);
extern id class_create_instance(Class* class); extern id class_create_instance(Class* class);
......
...@@ -40,12 +40,24 @@ typedef char BOOL; ...@@ -40,12 +40,24 @@ typedef char BOOL;
#define NO (BOOL)0 #define NO (BOOL)0
/* /*
** Definition of a selector. Selectors are really of type unsigned int. ** Definition of a selector. Selectors themselves are not unique, but
** The runtime does this mapping from SEL's to names internally in the ** the sel_id is a unique identifier.
** sel_... operations. You should never use the fact that it is actually
** an integer, since other Objective-C implementations use other conventions.
*/ */
typedef void* SEL; typedef const struct objc_selector
{
void *sel_id;
const char *sel_types;
} *SEL;
inline static BOOL
sel_eq (SEL s1, SEL s2)
{
if (s1 == 0 || s2 == 0)
return s1 == s2;
else
return s1->sel_id == s2->sel_id;
}
/* /*
** ObjC uses this typedef for untyped instances. ** ObjC uses this typedef for untyped instances.
...@@ -131,36 +143,8 @@ typedef union { ...@@ -131,36 +143,8 @@ typedef union {
} *arglist_t; /* argument frame */ } *arglist_t; /* argument frame */
#if defined(__OBJC__)
#include "objc/sarray.h"
/*
This is the function called when messages are send to nil. You may
set a breakpoint in your debugger at this function to catch messages
too nil.
*/
extern id nil_method(id rcv, SEL op, ...);
/*
The messager is inlined, thus it is defined here directly. The
inlining is quite time-consuming when optimizing. This will be
taken care of later by hand-coding the messager in the compiler.
*/
extern __inline__ IMP
objc_msg_lookup(id receiver, SEL op)
{
if(receiver)
return sarray_get(receiver->class_pointer->dtable, (size_t)(op));
else
return nil_method;
}
#else
IMP objc_msg_lookup(id receiver, SEL op); IMP objc_msg_lookup(id receiver, SEL op);
#endif
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
......
...@@ -43,7 +43,7 @@ class_create_instance(Class* class) ...@@ -43,7 +43,7 @@ class_create_instance(Class* class)
new = (*_objc_object_alloc)(class); new = (*_objc_object_alloc)(class);
if (new!=nil) if (new!=nil)
{ {
bzero (new, class->instance_size); memchr (new, 0, class->instance_size);
new->class_pointer = class; new->class_pointer = class;
} }
return new; return new;
......
...@@ -61,12 +61,14 @@ extern BOOL __objc_class_links_resolved; ...@@ -61,12 +61,14 @@ extern BOOL __objc_class_links_resolved;
extern int __objc_selector_max_index; extern int __objc_selector_max_index;
#ifdef DEBUG #ifdef DEBUG
#define DEBUG_PRINTF printf #define DEBUG_PRINTF(format, args...) printf (format, ## args)
#else #else
#define DEBUG_PRINTF #define DEBUG_PRINTF(format, args...)
#endif #endif
BOOL __objc_responds_to (id object, SEL sel); /* for internal use only! */ BOOL __objc_responds_to (id object, SEL sel); /* for internal use only! */
SEL __sel_register_typed_name (const char*, const char*,
struct objc_selector*);
#endif /* not __objc_runtime_INCLUDE_GNU */ #endif /* not __objc_runtime_INCLUDE_GNU */
......
...@@ -40,6 +40,11 @@ const char* __objc_sparse2_id = "2 level sparse indices"; ...@@ -40,6 +40,11 @@ const char* __objc_sparse2_id = "2 level sparse indices";
const char* __objc_sparse3_id = "3 level sparse indices"; const char* __objc_sparse3_id = "3 level sparse indices";
#endif #endif
#ifdef __alpha__
const void *memcpy (void*, const void*, size_t);
void free (const void*);
#endif
void void
sarray_at_put(struct sarray* array, sidx index, void* element) sarray_at_put(struct sarray* array, sidx index, void* element)
{ {
...@@ -117,7 +122,7 @@ sarray_at_put(struct sarray* array, sidx index, void* element) ...@@ -117,7 +122,7 @@ sarray_at_put(struct sarray* array, sidx index, void* element)
/* The bucket was previously empty (or something like that), */ /* The bucket was previously empty (or something like that), */
/* allocate a new. This is the effect of `lazy' allocation */ /* allocate a new. This is the effect of `lazy' allocation */
*the_bucket = (struct sbucket*)__objc_xmalloc(sizeof(struct sbucket)); *the_bucket = (struct sbucket*)__objc_xmalloc(sizeof(struct sbucket));
memcpy( *the_bucket,array->empty_bucket, sizeof(struct sbucket)); memcpy((void *) *the_bucket, (const void*)array->empty_bucket, sizeof(struct sbucket));
(*the_bucket)->version = array->version; (*the_bucket)->version = array->version;
nbuckets += 1; nbuckets += 1;
......
...@@ -31,7 +31,8 @@ You should have received a copy of the GNU General Public License along with ...@@ -31,7 +31,8 @@ You should have received a copy of the GNU General Public License along with
#define SELECTOR_HASH_SIZE 128 #define SELECTOR_HASH_SIZE 128
/* Tables mapping selector names to uid and opposite */ /* Tables mapping selector names to uid and opposite */
static struct sarray* __objc_selector_array = 0; /* uid -> name */ static struct sarray* __objc_selector_array = 0; /* uid -> sel */
static struct sarray* __objc_selector_names = 0; /* uid -> name */
static cache_ptr __objc_selector_hash = 0; /* name -> uid */ static cache_ptr __objc_selector_hash = 0; /* name -> uid */
static void register_selectors_from_list(MethodList_t); static void register_selectors_from_list(MethodList_t);
...@@ -42,6 +43,7 @@ int __objc_selector_max_index = 0; ...@@ -42,6 +43,7 @@ int __objc_selector_max_index = 0;
void __objc_init_selector_tables() void __objc_init_selector_tables()
{ {
__objc_selector_array = sarray_new (SELECTOR_HASH_SIZE, 0); __objc_selector_array = sarray_new (SELECTOR_HASH_SIZE, 0);
__objc_selector_names = sarray_new (SELECTOR_HASH_SIZE, 0);
__objc_selector_hash __objc_selector_hash
= hash_new (SELECTOR_HASH_SIZE, = hash_new (SELECTOR_HASH_SIZE,
(hash_func_type) hash_string, (hash_func_type) hash_string,
...@@ -78,16 +80,67 @@ register_selectors_from_list (MethodList_t method_list) ...@@ -78,16 +80,67 @@ register_selectors_from_list (MethodList_t method_list)
while (i < method_list->method_count) while (i < method_list->method_count)
{ {
Method_t method = &method_list->method_list[i]; Method_t method = &method_list->method_list[i];
method->method_name = sel_register_name ((char*)method->method_name); method->method_name
= sel_register_typed_name ((const char*)method->method_name,
method->method_types);
i += 1; i += 1;
} }
} }
/* return selector representing name */ /* return selector representing name */
SEL SEL
sel_get_typed_uid (const char *name, const char *types)
{
struct objc_list *l;
sidx i;
i = (sidx) hash_value_for_key (__objc_selector_hash, name);
if (i == 0)
return 0;
for (l = (struct objc_list*)sarray_get (__objc_selector_array, i);
l; l = l->tail)
{
SEL s = (SEL)l->head;
if (types == 0 || s->sel_types == 0)
{
if (s->sel_types == types)
{
return s;
}
}
else if (! strcmp (s->sel_types, types))
{
return s;
}
}
return 0;
}
/* return selector representing name */
SEL
sel_get_any_uid (const char *name)
{
struct objc_list *l;
sidx i;
i = (sidx) hash_value_for_key (__objc_selector_hash, name);
if (soffset_decode (i) == 0)
return 0;
l = (struct objc_list*)sarray_get (__objc_selector_array, i);
if (l == 0)
return 0;
return (SEL)l->head;
}
/* return selector representing name */
SEL
sel_get_uid (const char *name) sel_get_uid (const char *name)
{ {
return (SEL) hash_value_for_key (__objc_selector_hash, name); return sel_register_typed_name (name, 0);
} }
/* Get name of selector. If selector is unknown, the empty string "" /* Get name of selector. If selector is unknown, the empty string ""
...@@ -95,45 +148,123 @@ sel_get_uid (const char *name) ...@@ -95,45 +148,123 @@ sel_get_uid (const char *name)
const char* const char*
sel_get_name (SEL selector) sel_get_name (SEL selector)
{ {
if ((soffset_decode((sidx)selector) > 0) if ((soffset_decode((sidx)selector->sel_id) > 0)
&& (soffset_decode((sidx)selector) <= __objc_selector_max_index)) && (soffset_decode((sidx)selector->sel_id) <= __objc_selector_max_index))
return sarray_get (__objc_selector_array, (sidx) selector); return sarray_get (__objc_selector_array, (sidx) selector->sel_id);
else else
return NULL; return 0;
} }
BOOL BOOL
sel_is_mapped (SEL selector) sel_is_mapped (SEL selector)
{ {
unsigned int idx = soffset_decode ((sidx)selector); unsigned int idx = soffset_decode ((sidx)selector->sel_id);
return ((idx > 0) && (idx <= __objc_selector_max_index)); return ((idx > 0) && (idx <= __objc_selector_max_index));
} }
const char*
sel_get_type (SEL selector)
{
if (selector)
return selector->sel_types;
else
return 0;
}
/* The uninstalled dispatch table */ /* The uninstalled dispatch table */
extern struct sarray* __objc_uninstalled_dtable; extern struct sarray* __objc_uninstalled_dtable;
/* Store the passed selector name in the selector record and return its /* Store the passed selector name in the selector record and return its
selector value (value returned by sel_get_uid). */ selector value (value returned by sel_get_uid). */
SEL SEL
sel_register_name (const char *sel) __sel_register_typed_name (const char *name, const char *types,
struct objc_selector *orig)
{ {
SEL j; struct objc_selector* j;
sidx i; sidx i;
struct objc_list *l;
if ((j = sel_get_uid ((const char *) sel))) i = (sidx) hash_value_for_key (__objc_selector_hash, name);
return j; if (soffset_decode (i) != 0)
{
for (l = (struct objc_list*)sarray_get (__objc_selector_array, i);
l; l = l->tail)
{
SEL s = (SEL)l->head;
if (types == 0 || s->sel_types == 0)
{
if (s->sel_types == types)
{
if (orig)
{
orig->sel_id = (void*)i;
return orig;
}
else
return s;
}
}
else if (strcmp (s->sel_types, types))
{
if (orig)
{
orig->sel_id = (void*)i;
return orig;
}
else
return s;
}
}
if (orig)
j = orig;
else
j = __objc_xmalloc (sizeof (struct objc_selector));
/* Save the selector name. */ j->sel_id = (void*)i;
j->sel_types = (const char*)types;
l = (struct objc_list*)sarray_get (__objc_selector_array, i);
}
else
{
__objc_selector_max_index += 1; __objc_selector_max_index += 1;
i = soffset_encode(__objc_selector_max_index); i = soffset_encode(__objc_selector_max_index);
if (orig)
j = orig;
else
j = __objc_xmalloc (sizeof (struct objc_selector));
DEBUG_PRINTF ("Record selector %s as: %#x\n", sel, i); j->sel_id = (void*)i;
j->sel_types = (const char*)types;
l = 0;
}
DEBUG_PRINTF ("Record selector %s[%s] as: %ld\n", name, types,
soffset_decode (i));
sarray_at_put_safe (__objc_selector_array, i, (void *) sel); {
hash_add (&__objc_selector_hash, (void *) sel, (void *) i); int is_new = (l == 0);
l = list_cons ((void*)j, l);
sarray_at_put_safe (__objc_selector_names, i, (void *) name);
sarray_at_put_safe (__objc_selector_array, i, (void *) l);
if (is_new)
hash_add (&__objc_selector_hash, (void *) name, (void *) i);
}
sarray_realloc(__objc_uninstalled_dtable, __objc_selector_max_index+1); sarray_realloc(__objc_uninstalled_dtable, __objc_selector_max_index+1);
return (SEL) i; return (SEL) j;
}
SEL
sel_register_name (const char *name)
{
return __sel_register_typed_name (name, 0, 0);
}
SEL
sel_register_typed_name (const char *name, const char *type)
{
return __sel_register_typed_name (name, type, 0);
} }
...@@ -30,8 +30,6 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ ...@@ -30,8 +30,6 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "objc/hash.h" #include "objc/hash.h"
#include <stdio.h> #include <stdio.h>
#ifndef __alpha__ /* alpha is currently not supported */
typedef int (*objc_typed_read_func)(void*, char*, int); typedef int (*objc_typed_read_func)(void*, char*, int);
typedef int (*objc_typed_write_func)(void*, const char*, int); typedef int (*objc_typed_write_func)(void*, const char*, int);
typedef int (*objc_typed_flush_func)(void*); typedef int (*objc_typed_flush_func)(void*);
...@@ -100,7 +98,7 @@ int objc_read_types (TypedStream* stream, const char* type, ...); ...@@ -100,7 +98,7 @@ int objc_read_types (TypedStream* stream, const char* type, ...);
int objc_write_object_reference (TypedStream* stream, id object); int objc_write_object_reference (TypedStream* stream, id object);
int objc_write_root_object (TypedStream* stream, id object); int objc_write_root_object (TypedStream* stream, id object);
int objc_get_stream_class_version (TypedStream* stream, Class* class); long objc_get_stream_class_version (TypedStream* stream, Class* class);
/* /*
...@@ -130,6 +128,4 @@ void objc_close_typed_stream (TypedStream* stream); ...@@ -130,6 +128,4 @@ void objc_close_typed_stream (TypedStream* stream);
BOOL objc_end_of_typed_stream (TypedStream* stream); BOOL objc_end_of_typed_stream (TypedStream* stream);
void objc_flush_typed_stream (TypedStream* stream); void objc_flush_typed_stream (TypedStream* stream);
#endif /* __alpha__ */
#endif /* not __typedstream_INCLUDE_GNU */ #endif /* not __typedstream_INCLUDE_GNU */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment