encoding.h: Fix formatting.
2002-07-02 Rodney Brown <rbrown64@csc.com.au> * objc/encoding.h: Fix formatting. * objc/hash.h: Likewise. * objc/objc-api.h: Likewise. * objc/runtime.h: Likewise. * objc/thr.h: Likewise. * archive.c: Likewise. * class.c: Likewise. * encoding.c: Likewise. * gc.c: Likewise. * hash.c: Likewise. * init.c: Likewise. * misc.c: Likewise. * nil_method.c: Likewise. * objects.c: Likewise. * sarray.c: Likewise. * selector.c: Likewise. * sendmsg.c: Likewise. * thr-mach.c: Likewise. * thr.c: Likewise. From-SVN: r55190
This commit is contained in:
parent
52702ae16e
commit
40165636b5
|
@ -1,3 +1,25 @@
|
||||||
|
2002-07-02 Rodney Brown <rbrown64@csc.com.au>
|
||||||
|
|
||||||
|
* objc/encoding.h: Fix formatting.
|
||||||
|
* objc/hash.h: Likewise.
|
||||||
|
* objc/objc-api.h: Likewise.
|
||||||
|
* objc/runtime.h: Likewise.
|
||||||
|
* objc/thr.h: Likewise.
|
||||||
|
* archive.c: Likewise.
|
||||||
|
* class.c: Likewise.
|
||||||
|
* encoding.c: Likewise.
|
||||||
|
* gc.c: Likewise.
|
||||||
|
* hash.c: Likewise.
|
||||||
|
* init.c: Likewise.
|
||||||
|
* misc.c: Likewise.
|
||||||
|
* nil_method.c: Likewise.
|
||||||
|
* objects.c: Likewise.
|
||||||
|
* sarray.c: Likewise.
|
||||||
|
* selector.c: Likewise.
|
||||||
|
* sendmsg.c: Likewise.
|
||||||
|
* thr-mach.c: Likewise.
|
||||||
|
* thr.c: Likewise.
|
||||||
|
|
||||||
2002-06-25 DJ Delorie <dj@redhat.com>
|
2002-06-25 DJ Delorie <dj@redhat.com>
|
||||||
|
|
||||||
* aclocal.m4 (GLIBCPP_CONFIGURE): Split out
|
* aclocal.m4 (GLIBCPP_CONFIGURE): Split out
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,5 +1,6 @@
|
||||||
/* GNU Objective C Runtime class related functions
|
/* GNU Objective C Runtime class related functions
|
||||||
Copyright (C) 1993, 1995, 1996, 1997, 2001 Free Software Foundation, Inc.
|
Copyright (C) 1993, 1995, 1996, 1997, 2001, 2002
|
||||||
|
Free Software Foundation, Inc.
|
||||||
Contributed by Kresten Krab Thorup and Dennis Glatting.
|
Contributed by Kresten Krab Thorup and Dennis Glatting.
|
||||||
|
|
||||||
Lock-free class table code designed and written from scratch by
|
Lock-free class table code designed and written from scratch by
|
||||||
|
@ -166,7 +167,7 @@ static void
|
||||||
class_table_setup (void)
|
class_table_setup (void)
|
||||||
{
|
{
|
||||||
/* Start - nothing in the table. */
|
/* Start - nothing in the table. */
|
||||||
memset (class_table_array, 0, sizeof(class_node_ptr) * CLASS_TABLE_SIZE);
|
memset (class_table_array, 0, sizeof (class_node_ptr) * CLASS_TABLE_SIZE);
|
||||||
|
|
||||||
/* The table writing mutex. */
|
/* The table writing mutex. */
|
||||||
__class_table_lock = objc_mutex_allocate ();
|
__class_table_lock = objc_mutex_allocate ();
|
||||||
|
@ -339,7 +340,7 @@ class_table_next (struct class_table_enumerator **e)
|
||||||
#if 0 /* DEBUGGING FUNCTIONS */
|
#if 0 /* DEBUGGING FUNCTIONS */
|
||||||
/* Debugging function - print the class table. */
|
/* Debugging function - print the class table. */
|
||||||
void
|
void
|
||||||
class_table_print ()
|
class_table_print (void)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
@ -362,7 +363,7 @@ class_table_print ()
|
||||||
function of hash key values. Useful to evaluate the hash function
|
function of hash key values. Useful to evaluate the hash function
|
||||||
in real cases. */
|
in real cases. */
|
||||||
void
|
void
|
||||||
class_table_print_histogram ()
|
class_table_print_histogram (void)
|
||||||
{
|
{
|
||||||
int i, j;
|
int i, j;
|
||||||
int counter = 0;
|
int counter = 0;
|
||||||
|
@ -408,64 +409,66 @@ class_table_print_histogram ()
|
||||||
/* This is a hook which is called by objc_get_class and
|
/* This is a hook which is called by objc_get_class and
|
||||||
objc_lookup_class if the runtime is not able to find the class.
|
objc_lookup_class if the runtime is not able to find the class.
|
||||||
This may e.g. try to load in the class using dynamic loading. */
|
This may e.g. try to load in the class using dynamic loading. */
|
||||||
Class (*_objc_lookup_class)(const char* name) = 0; /* !T:SAFE */
|
Class (*_objc_lookup_class) (const char *name) = 0; /* !T:SAFE */
|
||||||
|
|
||||||
|
|
||||||
/* True when class links has been resolved. */
|
/* True when class links has been resolved. */
|
||||||
BOOL __objc_class_links_resolved = NO; /* !T:UNUSED */
|
BOOL __objc_class_links_resolved = NO; /* !T:UNUSED */
|
||||||
|
|
||||||
|
|
||||||
void __objc_init_class_tables()
|
void
|
||||||
|
__objc_init_class_tables (void)
|
||||||
{
|
{
|
||||||
/* Allocate the class hash table. */
|
/* Allocate the class hash table. */
|
||||||
|
|
||||||
if(__class_table_lock)
|
if (__class_table_lock)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
objc_mutex_lock(__objc_runtime_mutex);
|
objc_mutex_lock (__objc_runtime_mutex);
|
||||||
|
|
||||||
class_table_setup ();
|
class_table_setup ();
|
||||||
|
|
||||||
objc_mutex_unlock(__objc_runtime_mutex);
|
objc_mutex_unlock (__objc_runtime_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This function adds a class to the class hash table, and assigns the
|
/* This function adds a class to the class hash table, and assigns the
|
||||||
class a number, unless it's already known. */
|
class a number, unless it's already known. */
|
||||||
void
|
void
|
||||||
__objc_add_class_to_hash(Class class)
|
__objc_add_class_to_hash (Class class)
|
||||||
{
|
{
|
||||||
Class h_class;
|
Class h_class;
|
||||||
|
|
||||||
objc_mutex_lock(__objc_runtime_mutex);
|
objc_mutex_lock (__objc_runtime_mutex);
|
||||||
|
|
||||||
/* Make sure the table is there. */
|
/* Make sure the table is there. */
|
||||||
assert(__class_table_lock);
|
assert (__class_table_lock);
|
||||||
|
|
||||||
/* Make sure it's not a meta class. */
|
/* Make sure it's not a meta class. */
|
||||||
assert(CLS_ISCLASS(class));
|
assert (CLS_ISCLASS (class));
|
||||||
|
|
||||||
/* Check to see if the class is already in the hash table. */
|
/* Check to see if the class is already in the hash table. */
|
||||||
h_class = class_table_get_safe (class->name);
|
h_class = class_table_get_safe (class->name);
|
||||||
if (!h_class)
|
if (! h_class)
|
||||||
{
|
{
|
||||||
/* The class isn't in the hash table. Add the class and assign a class
|
/* The class isn't in the hash table. Add the class and assign a class
|
||||||
number. */
|
number. */
|
||||||
static unsigned int class_number = 1;
|
static unsigned int class_number = 1;
|
||||||
|
|
||||||
CLS_SETNUMBER(class, class_number);
|
CLS_SETNUMBER (class, class_number);
|
||||||
CLS_SETNUMBER(class->class_pointer, class_number);
|
CLS_SETNUMBER (class->class_pointer, class_number);
|
||||||
|
|
||||||
++class_number;
|
++class_number;
|
||||||
class_table_insert (class->name, class);
|
class_table_insert (class->name, class);
|
||||||
}
|
}
|
||||||
|
|
||||||
objc_mutex_unlock(__objc_runtime_mutex);
|
objc_mutex_unlock (__objc_runtime_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get the class object for the class named NAME. If NAME does not
|
/* Get the class object for the class named NAME. If NAME does not
|
||||||
identify a known class, the hook _objc_lookup_class is called. If
|
identify a known class, the hook _objc_lookup_class is called. If
|
||||||
this fails, nil is returned. */
|
this fails, nil is returned. */
|
||||||
Class objc_lookup_class (const char* name)
|
Class
|
||||||
|
objc_lookup_class (const char *name)
|
||||||
{
|
{
|
||||||
Class class;
|
Class class;
|
||||||
|
|
||||||
|
@ -475,7 +478,7 @@ Class objc_lookup_class (const char* name)
|
||||||
return class;
|
return class;
|
||||||
|
|
||||||
if (_objc_lookup_class)
|
if (_objc_lookup_class)
|
||||||
return (*_objc_lookup_class)(name);
|
return (*_objc_lookup_class) (name);
|
||||||
else
|
else
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -494,20 +497,20 @@ objc_get_class (const char *name)
|
||||||
return class;
|
return class;
|
||||||
|
|
||||||
if (_objc_lookup_class)
|
if (_objc_lookup_class)
|
||||||
class = (*_objc_lookup_class)(name);
|
class = (*_objc_lookup_class) (name);
|
||||||
|
|
||||||
if(class)
|
if (class)
|
||||||
return class;
|
return class;
|
||||||
|
|
||||||
objc_error(nil, OBJC_ERR_BAD_CLASS,
|
objc_error (nil, OBJC_ERR_BAD_CLASS,
|
||||||
"objc runtime: cannot find class %s\n", name);
|
"objc runtime: cannot find class %s\n", name);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
MetaClass
|
MetaClass
|
||||||
objc_get_meta_class(const char *name)
|
objc_get_meta_class (const char *name)
|
||||||
{
|
{
|
||||||
return objc_get_class(name)->class_pointer;
|
return objc_get_class (name)->class_pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This function provides a way to enumerate all the classes in the
|
/* This function provides a way to enumerate all the classes in the
|
||||||
|
@ -516,22 +519,22 @@ objc_get_meta_class(const char *name)
|
||||||
For example:
|
For example:
|
||||||
id class;
|
id class;
|
||||||
void *es = NULL;
|
void *es = NULL;
|
||||||
while ((class = objc_next_class(&es)))
|
while ((class = objc_next_class (&es)))
|
||||||
... do something with class;
|
... do something with class;
|
||||||
*/
|
*/
|
||||||
Class
|
Class
|
||||||
objc_next_class(void **enum_state)
|
objc_next_class (void **enum_state)
|
||||||
{
|
{
|
||||||
Class class;
|
Class class;
|
||||||
|
|
||||||
objc_mutex_lock(__objc_runtime_mutex);
|
objc_mutex_lock (__objc_runtime_mutex);
|
||||||
|
|
||||||
/* Make sure the table is there. */
|
/* Make sure the table is there. */
|
||||||
assert(__class_table_lock);
|
assert (__class_table_lock);
|
||||||
|
|
||||||
class = class_table_next ((struct class_table_enumerator **)enum_state);
|
class = class_table_next ((struct class_table_enumerator **) enum_state);
|
||||||
|
|
||||||
objc_mutex_unlock(__objc_runtime_mutex);
|
objc_mutex_unlock (__objc_runtime_mutex);
|
||||||
|
|
||||||
return class;
|
return class;
|
||||||
}
|
}
|
||||||
|
@ -539,33 +542,34 @@ objc_next_class(void **enum_state)
|
||||||
/* 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 to
|
can be sure of is that the class_pointer for class objects point to
|
||||||
the right meta class objects. */
|
the right meta class objects. */
|
||||||
void __objc_resolve_class_links()
|
void
|
||||||
|
__objc_resolve_class_links (void)
|
||||||
{
|
{
|
||||||
struct class_table_enumerator *es = NULL;
|
struct class_table_enumerator *es = NULL;
|
||||||
Class object_class = objc_get_class ("Object");
|
Class object_class = objc_get_class ("Object");
|
||||||
Class class1;
|
Class class1;
|
||||||
|
|
||||||
assert(object_class);
|
assert (object_class);
|
||||||
|
|
||||||
objc_mutex_lock(__objc_runtime_mutex);
|
objc_mutex_lock (__objc_runtime_mutex);
|
||||||
|
|
||||||
/* Assign subclass links. */
|
/* Assign subclass links. */
|
||||||
while ((class1 = class_table_next (&es)))
|
while ((class1 = class_table_next (&es)))
|
||||||
{
|
{
|
||||||
/* Make sure we have what we think we have. */
|
/* Make sure we have what we think we have. */
|
||||||
assert (CLS_ISCLASS(class1));
|
assert (CLS_ISCLASS (class1));
|
||||||
assert (CLS_ISMETA(class1->class_pointer));
|
assert (CLS_ISMETA (class1->class_pointer));
|
||||||
|
|
||||||
/* The class_pointer of all meta classes point to Object's meta
|
/* The class_pointer of all meta classes point to Object's meta
|
||||||
class. */
|
class. */
|
||||||
class1->class_pointer->class_pointer = object_class->class_pointer;
|
class1->class_pointer->class_pointer = object_class->class_pointer;
|
||||||
|
|
||||||
if (!(CLS_ISRESOLV(class1)))
|
if (! CLS_ISRESOLV (class1))
|
||||||
{
|
{
|
||||||
CLS_SETRESOLV(class1);
|
CLS_SETRESOLV (class1);
|
||||||
CLS_SETRESOLV(class1->class_pointer);
|
CLS_SETRESOLV (class1->class_pointer);
|
||||||
|
|
||||||
if(class1->super_class)
|
if (class1->super_class)
|
||||||
{
|
{
|
||||||
Class a_super_class
|
Class a_super_class
|
||||||
= objc_get_class ((char *) class1->super_class);
|
= objc_get_class ((char *) class1->super_class);
|
||||||
|
@ -607,12 +611,12 @@ void __objc_resolve_class_links()
|
||||||
sub_class = sub_class->sibling_class)
|
sub_class = sub_class->sibling_class)
|
||||||
{
|
{
|
||||||
sub_class->super_class = class1;
|
sub_class->super_class = class1;
|
||||||
if(CLS_ISCLASS(sub_class))
|
if (CLS_ISCLASS (sub_class))
|
||||||
sub_class->class_pointer->super_class = class1->class_pointer;
|
sub_class->class_pointer->super_class = class1->class_pointer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
objc_mutex_unlock(__objc_runtime_mutex);
|
objc_mutex_unlock (__objc_runtime_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -622,7 +626,7 @@ void __objc_resolve_class_links()
|
||||||
Class
|
Class
|
||||||
class_pose_as (Class impostor, Class super_class)
|
class_pose_as (Class impostor, Class super_class)
|
||||||
{
|
{
|
||||||
if (!CLS_ISRESOLV (impostor))
|
if (! CLS_ISRESOLV (impostor))
|
||||||
__objc_resolve_class_links ();
|
__objc_resolve_class_links ();
|
||||||
|
|
||||||
/* Preconditions */
|
/* Preconditions */
|
||||||
|
@ -685,11 +689,11 @@ class_pose_as (Class impostor, Class super_class)
|
||||||
keys of the hashtable is, change all values that are superclass
|
keys of the hashtable is, change all values that are superclass
|
||||||
into impostor. */
|
into impostor. */
|
||||||
|
|
||||||
objc_mutex_lock(__objc_runtime_mutex);
|
objc_mutex_lock (__objc_runtime_mutex);
|
||||||
|
|
||||||
class_table_replace (super_class, impostor);
|
class_table_replace (super_class, impostor);
|
||||||
|
|
||||||
objc_mutex_unlock(__objc_runtime_mutex);
|
objc_mutex_unlock (__objc_runtime_mutex);
|
||||||
|
|
||||||
/* Next, we update the dispatch tables... */
|
/* Next, we update the dispatch tables... */
|
||||||
__objc_update_dispatch_table_for_class (CLASSOF (impostor));
|
__objc_update_dispatch_table_for_class (CLASSOF (impostor));
|
||||||
|
|
|
@ -34,18 +34,18 @@ Boston, MA 02111-1307, USA. */
|
||||||
|
|
||||||
#undef MAX
|
#undef MAX
|
||||||
#define MAX(X, Y) \
|
#define MAX(X, Y) \
|
||||||
({ typeof(X) __x = (X), __y = (Y); \
|
({ typeof (X) __x = (X), __y = (Y); \
|
||||||
(__x > __y ? __x : __y); })
|
(__x > __y ? __x : __y); })
|
||||||
|
|
||||||
#undef MIN
|
#undef MIN
|
||||||
#define MIN(X, Y) \
|
#define MIN(X, Y) \
|
||||||
({ typeof(X) __x = (X), __y = (Y); \
|
({ typeof (X) __x = (X), __y = (Y); \
|
||||||
(__x < __y ? __x : __y); })
|
(__x < __y ? __x : __y); })
|
||||||
|
|
||||||
#undef ROUND
|
#undef ROUND
|
||||||
#define ROUND(V, A) \
|
#define ROUND(V, A) \
|
||||||
({ typeof(V) __v=(V); typeof(A) __a=(A); \
|
({ typeof (V) __v = (V); typeof (A) __a = (A); \
|
||||||
__a*((__v+__a-1)/__a); })
|
__a * ((__v+__a - 1)/__a); })
|
||||||
|
|
||||||
|
|
||||||
/* Various hacks for objc_layout_record. These are used by the target
|
/* Various hacks for objc_layout_record. These are used by the target
|
||||||
|
@ -89,7 +89,7 @@ static int __attribute__ ((__unused__)) target_flags = 0;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
objc_sizeof_type (const char* type)
|
objc_sizeof_type (const char *type)
|
||||||
{
|
{
|
||||||
/* Skip the variable name if any */
|
/* Skip the variable name if any */
|
||||||
if (*type == '"')
|
if (*type == '"')
|
||||||
|
@ -98,81 +98,83 @@ objc_sizeof_type (const char* type)
|
||||||
/* do nothing */;
|
/* do nothing */;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch(*type) {
|
switch (*type) {
|
||||||
case _C_ID:
|
case _C_ID:
|
||||||
return sizeof(id);
|
return sizeof (id);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case _C_CLASS:
|
case _C_CLASS:
|
||||||
return sizeof(Class);
|
return sizeof (Class);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case _C_SEL:
|
case _C_SEL:
|
||||||
return sizeof(SEL);
|
return sizeof (SEL);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case _C_CHR:
|
case _C_CHR:
|
||||||
return sizeof(char);
|
return sizeof (char);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case _C_UCHR:
|
case _C_UCHR:
|
||||||
return sizeof(unsigned char);
|
return sizeof (unsigned char);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case _C_SHT:
|
case _C_SHT:
|
||||||
return sizeof(short);
|
return sizeof (short);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case _C_USHT:
|
case _C_USHT:
|
||||||
return sizeof(unsigned short);
|
return sizeof (unsigned short);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case _C_INT:
|
case _C_INT:
|
||||||
return sizeof(int);
|
return sizeof (int);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case _C_UINT:
|
case _C_UINT:
|
||||||
return sizeof(unsigned int);
|
return sizeof (unsigned int);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case _C_LNG:
|
case _C_LNG:
|
||||||
return sizeof(long);
|
return sizeof (long);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case _C_ULNG:
|
case _C_ULNG:
|
||||||
return sizeof(unsigned long);
|
return sizeof (unsigned long);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case _C_LNG_LNG:
|
case _C_LNG_LNG:
|
||||||
return sizeof(long long);
|
return sizeof (long long);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case _C_ULNG_LNG:
|
case _C_ULNG_LNG:
|
||||||
return sizeof(unsigned long long);
|
return sizeof (unsigned long long);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case _C_FLT:
|
case _C_FLT:
|
||||||
return sizeof(float);
|
return sizeof (float);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case _C_DBL:
|
case _C_DBL:
|
||||||
return sizeof(double);
|
return sizeof (double);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case _C_VOID:
|
case _C_VOID:
|
||||||
return sizeof(void);
|
return sizeof (void);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case _C_PTR:
|
case _C_PTR:
|
||||||
case _C_ATOM:
|
case _C_ATOM:
|
||||||
case _C_CHARPTR:
|
case _C_CHARPTR:
|
||||||
return sizeof(char*);
|
return sizeof (char *);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case _C_ARY_B:
|
case _C_ARY_B:
|
||||||
{
|
{
|
||||||
int len = atoi(type+1);
|
int len = atoi (type + 1);
|
||||||
while (isdigit((unsigned char)*++type));
|
while (isdigit ((unsigned char)*++type))
|
||||||
return len*objc_aligned_size (type);
|
;
|
||||||
|
return len * objc_aligned_size (type);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -183,7 +185,8 @@ objc_sizeof_type (const char* type)
|
||||||
int startByte, endByte;
|
int startByte, endByte;
|
||||||
|
|
||||||
position = atoi (type + 1);
|
position = atoi (type + 1);
|
||||||
while (isdigit ((unsigned char)*++type));
|
while (isdigit ((unsigned char)*++type))
|
||||||
|
;
|
||||||
size = atoi (type + 1);
|
size = atoi (type + 1);
|
||||||
|
|
||||||
startByte = position / BITS_PER_UNIT;
|
startByte = position / BITS_PER_UNIT;
|
||||||
|
@ -207,7 +210,8 @@ objc_sizeof_type (const char* type)
|
||||||
case _C_UNION_B:
|
case _C_UNION_B:
|
||||||
{
|
{
|
||||||
int max_size = 0;
|
int max_size = 0;
|
||||||
while (*type != _C_UNION_E && *type++ != '=') /* do nothing */;
|
while (*type != _C_UNION_E && *type++ != '=')
|
||||||
|
/* do nothing */;
|
||||||
while (*type != _C_UNION_E)
|
while (*type != _C_UNION_E)
|
||||||
{
|
{
|
||||||
/* Skip the variable name if any */
|
/* Skip the variable name if any */
|
||||||
|
@ -224,7 +228,7 @@ objc_sizeof_type (const char* type)
|
||||||
|
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
objc_error(nil, OBJC_ERR_BAD_TYPE, "unknown type %s\n", type);
|
objc_error (nil, OBJC_ERR_BAD_TYPE, "unknown type %s\n", type);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -236,7 +240,7 @@ objc_sizeof_type (const char* type)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
objc_alignof_type(const char* type)
|
objc_alignof_type (const char *type)
|
||||||
{
|
{
|
||||||
/* Skip the variable name if any */
|
/* Skip the variable name if any */
|
||||||
if (*type == '"')
|
if (*type == '"')
|
||||||
|
@ -244,75 +248,76 @@ objc_alignof_type(const char* type)
|
||||||
for (type++; *type++ != '"';)
|
for (type++; *type++ != '"';)
|
||||||
/* do nothing */;
|
/* do nothing */;
|
||||||
}
|
}
|
||||||
switch(*type) {
|
switch (*type) {
|
||||||
case _C_ID:
|
case _C_ID:
|
||||||
return __alignof__(id);
|
return __alignof__ (id);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case _C_CLASS:
|
case _C_CLASS:
|
||||||
return __alignof__(Class);
|
return __alignof__ (Class);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case _C_SEL:
|
case _C_SEL:
|
||||||
return __alignof__(SEL);
|
return __alignof__ (SEL);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case _C_CHR:
|
case _C_CHR:
|
||||||
return __alignof__(char);
|
return __alignof__ (char);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case _C_UCHR:
|
case _C_UCHR:
|
||||||
return __alignof__(unsigned char);
|
return __alignof__ (unsigned char);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case _C_SHT:
|
case _C_SHT:
|
||||||
return __alignof__(short);
|
return __alignof__ (short);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case _C_USHT:
|
case _C_USHT:
|
||||||
return __alignof__(unsigned short);
|
return __alignof__ (unsigned short);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case _C_INT:
|
case _C_INT:
|
||||||
return __alignof__(int);
|
return __alignof__ (int);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case _C_UINT:
|
case _C_UINT:
|
||||||
return __alignof__(unsigned int);
|
return __alignof__ (unsigned int);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case _C_LNG:
|
case _C_LNG:
|
||||||
return __alignof__(long);
|
return __alignof__ (long);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case _C_ULNG:
|
case _C_ULNG:
|
||||||
return __alignof__(unsigned long);
|
return __alignof__ (unsigned long);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case _C_LNG_LNG:
|
case _C_LNG_LNG:
|
||||||
return __alignof__(long long);
|
return __alignof__ (long long);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case _C_ULNG_LNG:
|
case _C_ULNG_LNG:
|
||||||
return __alignof__(unsigned long long);
|
return __alignof__ (unsigned long long);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case _C_FLT:
|
case _C_FLT:
|
||||||
return __alignof__(float);
|
return __alignof__ (float);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case _C_DBL:
|
case _C_DBL:
|
||||||
return __alignof__(double);
|
return __alignof__ (double);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case _C_PTR:
|
case _C_PTR:
|
||||||
case _C_ATOM:
|
case _C_ATOM:
|
||||||
case _C_CHARPTR:
|
case _C_CHARPTR:
|
||||||
return __alignof__(char*);
|
return __alignof__ (char *);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case _C_ARY_B:
|
case _C_ARY_B:
|
||||||
while (isdigit((unsigned char)*++type)) /* do nothing */;
|
while (isdigit ((unsigned char)*++type))
|
||||||
|
/* do nothing */;
|
||||||
return objc_alignof_type (type);
|
return objc_alignof_type (type);
|
||||||
|
|
||||||
case _C_STRUCT_B:
|
case _C_STRUCT_B:
|
||||||
|
@ -331,7 +336,8 @@ objc_alignof_type(const char* type)
|
||||||
case _C_UNION_B:
|
case _C_UNION_B:
|
||||||
{
|
{
|
||||||
int maxalign = 0;
|
int maxalign = 0;
|
||||||
while (*type != _C_UNION_E && *type++ != '=') /* do nothing */;
|
while (*type != _C_UNION_E && *type++ != '=')
|
||||||
|
/* do nothing */;
|
||||||
while (*type != _C_UNION_E)
|
while (*type != _C_UNION_E)
|
||||||
{
|
{
|
||||||
/* Skip the variable name if any */
|
/* Skip the variable name if any */
|
||||||
|
@ -348,7 +354,7 @@ objc_alignof_type(const char* type)
|
||||||
|
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
objc_error(nil, OBJC_ERR_BAD_TYPE, "unknown type %s\n", type);
|
objc_error (nil, OBJC_ERR_BAD_TYPE, "unknown type %s\n", type);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -359,7 +365,7 @@ objc_alignof_type(const char* type)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
objc_aligned_size (const char* type)
|
objc_aligned_size (const char *type)
|
||||||
{
|
{
|
||||||
int size, align;
|
int size, align;
|
||||||
|
|
||||||
|
@ -378,11 +384,11 @@ objc_aligned_size (const char* type)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
The size rounded up to the nearest integral of the wordsize, taken
|
The size rounded up to the nearest integral of the wordsize, taken
|
||||||
to be the size of a void*.
|
to be the size of a void *.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
objc_promoted_size (const char* type)
|
objc_promoted_size (const char *type)
|
||||||
{
|
{
|
||||||
int size, wordsize;
|
int size, wordsize;
|
||||||
|
|
||||||
|
@ -394,7 +400,7 @@ objc_promoted_size (const char* type)
|
||||||
}
|
}
|
||||||
|
|
||||||
size = objc_sizeof_type (type);
|
size = objc_sizeof_type (type);
|
||||||
wordsize = sizeof (void*);
|
wordsize = sizeof (void *);
|
||||||
|
|
||||||
return ROUND (size, wordsize);
|
return ROUND (size, wordsize);
|
||||||
}
|
}
|
||||||
|
@ -404,8 +410,8 @@ objc_promoted_size (const char* type)
|
||||||
occurring in method prototype encodings.
|
occurring in method prototype encodings.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
inline const char*
|
inline const char *
|
||||||
objc_skip_type_qualifiers (const char* type)
|
objc_skip_type_qualifiers (const char *type)
|
||||||
{
|
{
|
||||||
while (*type == _C_CONST
|
while (*type == _C_CONST
|
||||||
|| *type == _C_IN
|
|| *type == _C_IN
|
||||||
|
@ -427,8 +433,8 @@ objc_skip_type_qualifiers (const char* type)
|
||||||
qualifiers, these are skipped as well.
|
qualifiers, these are skipped as well.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const char*
|
const char *
|
||||||
objc_skip_typespec (const char* type)
|
objc_skip_typespec (const char *type)
|
||||||
{
|
{
|
||||||
/* Skip the variable name if any */
|
/* Skip the variable name if any */
|
||||||
if (*type == '"')
|
if (*type == '"')
|
||||||
|
@ -449,7 +455,8 @@ objc_skip_typespec (const char* type)
|
||||||
return type;
|
return type;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
while (*++type != '"') /* do nothing */;
|
while (*++type != '"')
|
||||||
|
/* do nothing */;
|
||||||
return type + 1;
|
return type + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -478,34 +485,45 @@ objc_skip_typespec (const char* type)
|
||||||
case _C_ARY_B:
|
case _C_ARY_B:
|
||||||
/* skip digits, typespec and closing ']' */
|
/* skip digits, typespec and closing ']' */
|
||||||
|
|
||||||
while(isdigit((unsigned char)*++type));
|
while (isdigit ((unsigned char)*++type))
|
||||||
type = objc_skip_typespec(type);
|
;
|
||||||
|
type = objc_skip_typespec (type);
|
||||||
if (*type == _C_ARY_E)
|
if (*type == _C_ARY_E)
|
||||||
return ++type;
|
return ++type;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
objc_error(nil, OBJC_ERR_BAD_TYPE, "bad array type %s\n", type);
|
objc_error (nil, OBJC_ERR_BAD_TYPE, "bad array type %s\n", type);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
case _C_BFLD:
|
case _C_BFLD:
|
||||||
/* The new encoding of bitfields is: b 'position' 'type' 'size' */
|
/* The new encoding of bitfields is: b 'position' 'type' 'size' */
|
||||||
while (isdigit ((unsigned char)*++type)); /* skip position */
|
while (isdigit ((unsigned char)*++type))
|
||||||
while (isdigit ((unsigned char)*++type)); /* skip type and size */
|
; /* skip position */
|
||||||
|
while (isdigit ((unsigned char)*++type))
|
||||||
|
; /* skip type and size */
|
||||||
return type;
|
return type;
|
||||||
|
|
||||||
case _C_STRUCT_B:
|
case _C_STRUCT_B:
|
||||||
/* skip name, and elements until closing '}' */
|
/* skip name, and elements until closing '}' */
|
||||||
|
|
||||||
while (*type != _C_STRUCT_E && *type++ != '=');
|
while (*type != _C_STRUCT_E && *type++ != '=')
|
||||||
while (*type != _C_STRUCT_E) { type = objc_skip_typespec (type); }
|
;
|
||||||
|
while (*type != _C_STRUCT_E)
|
||||||
|
{
|
||||||
|
type = objc_skip_typespec (type);
|
||||||
|
}
|
||||||
return ++type;
|
return ++type;
|
||||||
|
|
||||||
case _C_UNION_B:
|
case _C_UNION_B:
|
||||||
/* skip name, and elements until closing ')' */
|
/* skip name, and elements until closing ')' */
|
||||||
|
|
||||||
while (*type != _C_UNION_E && *type++ != '=');
|
while (*type != _C_UNION_E && *type++ != '=')
|
||||||
while (*type != _C_UNION_E) { type = objc_skip_typespec (type); }
|
;
|
||||||
|
while (*type != _C_UNION_E)
|
||||||
|
{
|
||||||
|
type = objc_skip_typespec (type);
|
||||||
|
}
|
||||||
return ++type;
|
return ++type;
|
||||||
|
|
||||||
case _C_PTR:
|
case _C_PTR:
|
||||||
|
@ -515,7 +533,7 @@ objc_skip_typespec (const char* type)
|
||||||
|
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
objc_error(nil, OBJC_ERR_BAD_TYPE, "unknown type %s\n", type);
|
objc_error (nil, OBJC_ERR_BAD_TYPE, "unknown type %s\n", type);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -525,19 +543,21 @@ objc_skip_typespec (const char* type)
|
||||||
Skip an offset as part of a method encoding. This is prepended by a
|
Skip an offset as part of a method encoding. This is prepended by a
|
||||||
'+' if the argument is passed in registers.
|
'+' if the argument is passed in registers.
|
||||||
*/
|
*/
|
||||||
inline const char*
|
inline const char *
|
||||||
objc_skip_offset (const char* type)
|
objc_skip_offset (const char *type)
|
||||||
{
|
{
|
||||||
if (*type == '+') type++;
|
if (*type == '+')
|
||||||
while(isdigit((unsigned char)*++type));
|
type++;
|
||||||
|
while (isdigit ((unsigned char) *++type))
|
||||||
|
;
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Skip an argument specification of a method encoding.
|
Skip an argument specification of a method encoding.
|
||||||
*/
|
*/
|
||||||
const char*
|
const char *
|
||||||
objc_skip_argspec (const char* type)
|
objc_skip_argspec (const char *type)
|
||||||
{
|
{
|
||||||
type = objc_skip_typespec (type);
|
type = objc_skip_typespec (type);
|
||||||
type = objc_skip_offset (type);
|
type = objc_skip_offset (type);
|
||||||
|
@ -550,10 +570,10 @@ objc_skip_argspec (const char* type)
|
||||||
`_cmd'.
|
`_cmd'.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
method_get_number_of_arguments (struct objc_method* mth)
|
method_get_number_of_arguments (struct objc_method *mth)
|
||||||
{
|
{
|
||||||
int i = 0;
|
int i = 0;
|
||||||
const char* type = mth->method_types;
|
const char *type = mth->method_types;
|
||||||
while (*type)
|
while (*type)
|
||||||
{
|
{
|
||||||
type = objc_skip_argspec (type);
|
type = objc_skip_argspec (type);
|
||||||
|
@ -569,9 +589,9 @@ method_get_number_of_arguments (struct objc_method* mth)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
method_get_sizeof_arguments (struct objc_method* mth)
|
method_get_sizeof_arguments (struct objc_method *mth)
|
||||||
{
|
{
|
||||||
const char* type = objc_skip_typespec (mth->method_types);
|
const char *type = objc_skip_typespec (mth->method_types);
|
||||||
return atoi (type);
|
return atoi (type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -591,15 +611,14 @@ method_get_sizeof_arguments (struct objc_method* mth)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if ((flags & _F_IN) == _F_IN)
|
if ((flags & _F_IN) == _F_IN)
|
||||||
[portal encodeData: *(char**)datum ofType: ++type];
|
[portal encodeData: *(char **) datum ofType: ++type];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
char*
|
char *
|
||||||
method_get_next_argument (arglist_t argframe,
|
method_get_next_argument (arglist_t argframe, const char **type)
|
||||||
const char **type)
|
|
||||||
{
|
{
|
||||||
const char *t = objc_skip_argspec (*type);
|
const char *t = objc_skip_argspec (*type);
|
||||||
|
|
||||||
|
@ -621,10 +640,10 @@ method_get_next_argument (arglist_t argframe,
|
||||||
is returned in TYPE. type must be passed to successive calls of
|
is returned in TYPE. type must be passed to successive calls of
|
||||||
method_get_next_argument.
|
method_get_next_argument.
|
||||||
*/
|
*/
|
||||||
char*
|
char *
|
||||||
method_get_first_argument (struct objc_method* m,
|
method_get_first_argument (struct objc_method *m,
|
||||||
arglist_t argframe,
|
arglist_t argframe,
|
||||||
const char** type)
|
const char **type)
|
||||||
{
|
{
|
||||||
*type = m->method_types;
|
*type = m->method_types;
|
||||||
return method_get_next_argument (argframe, type);
|
return method_get_next_argument (argframe, type);
|
||||||
|
@ -636,12 +655,12 @@ method_get_first_argument (struct objc_method* m,
|
||||||
is returned in the value-result argument TYPE
|
is returned in the value-result argument TYPE
|
||||||
*/
|
*/
|
||||||
|
|
||||||
char*
|
char *
|
||||||
method_get_nth_argument (struct objc_method* m,
|
method_get_nth_argument (struct objc_method *m,
|
||||||
arglist_t argframe, int arg,
|
arglist_t argframe, int arg,
|
||||||
const char **type)
|
const char **type)
|
||||||
{
|
{
|
||||||
const char* t = objc_skip_argspec (m->method_types);
|
const char *t = objc_skip_argspec (m->method_types);
|
||||||
|
|
||||||
if (arg > method_get_number_of_arguments (m))
|
if (arg > method_get_number_of_arguments (m))
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -659,7 +678,7 @@ method_get_nth_argument (struct objc_method* m,
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned
|
unsigned
|
||||||
objc_get_type_qualifiers (const char* type)
|
objc_get_type_qualifiers (const char *type)
|
||||||
{
|
{
|
||||||
unsigned res = 0;
|
unsigned res = 0;
|
||||||
BOOL flag = YES;
|
BOOL flag = YES;
|
||||||
|
@ -712,7 +731,7 @@ objc_layout_structure (const char *type,
|
||||||
|
|
||||||
if (*type++ != _C_STRUCT_B)
|
if (*type++ != _C_STRUCT_B)
|
||||||
{
|
{
|
||||||
objc_error(nil, OBJC_ERR_BAD_TYPE,
|
objc_error (nil, OBJC_ERR_BAD_TYPE,
|
||||||
"record type expected in objc_layout_structure, got %s\n",
|
"record type expected in objc_layout_structure, got %s\n",
|
||||||
type);
|
type);
|
||||||
}
|
}
|
||||||
|
@ -760,7 +779,7 @@ objc_layout_structure_next_member (struct objc_struct_layout *layout)
|
||||||
else {
|
else {
|
||||||
/* Get the bitfield's type */
|
/* Get the bitfield's type */
|
||||||
for (bfld_type = type + 1;
|
for (bfld_type = type + 1;
|
||||||
isdigit((unsigned char)*bfld_type);
|
isdigit ((unsigned char)*bfld_type);
|
||||||
bfld_type++)
|
bfld_type++)
|
||||||
/* do nothing */;
|
/* do nothing */;
|
||||||
|
|
||||||
|
@ -784,12 +803,14 @@ objc_layout_structure_next_member (struct objc_struct_layout *layout)
|
||||||
type = objc_skip_type_qualifiers (layout->type);
|
type = objc_skip_type_qualifiers (layout->type);
|
||||||
|
|
||||||
if (*type != _C_BFLD)
|
if (*type != _C_BFLD)
|
||||||
desired_align = objc_alignof_type(type) * BITS_PER_UNIT;
|
desired_align = objc_alignof_type (type) * BITS_PER_UNIT;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
desired_align = 1;
|
desired_align = 1;
|
||||||
/* Skip the bitfield's offset */
|
/* Skip the bitfield's offset */
|
||||||
for (bfld_type = type + 1; isdigit((unsigned char)*bfld_type); bfld_type++)
|
for (bfld_type = type + 1;
|
||||||
|
isdigit ((unsigned char) *bfld_type);
|
||||||
|
bfld_type++)
|
||||||
/* do nothing */;
|
/* do nothing */;
|
||||||
|
|
||||||
bfld_type_size = objc_sizeof_type (bfld_type) * BITS_PER_UNIT;
|
bfld_type_size = objc_sizeof_type (bfld_type) * BITS_PER_UNIT;
|
||||||
|
@ -809,7 +830,7 @@ objc_layout_structure_next_member (struct objc_struct_layout *layout)
|
||||||
is meaningless. */
|
is meaningless. */
|
||||||
#ifndef PCC_BITFIELD_TYPE_MATTERS
|
#ifndef PCC_BITFIELD_TYPE_MATTERS
|
||||||
layout->record_align = MAX (layout->record_align, desired_align);
|
layout->record_align = MAX (layout->record_align, desired_align);
|
||||||
#else
|
#else /* PCC_BITFIELD_TYPE_MATTERS */
|
||||||
if (*type == _C_BFLD)
|
if (*type == _C_BFLD)
|
||||||
{
|
{
|
||||||
/* For these machines, a zero-length field does not
|
/* For these machines, a zero-length field does not
|
||||||
|
@ -841,7 +862,7 @@ objc_layout_structure_next_member (struct objc_struct_layout *layout)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
layout->record_align = MAX (layout->record_align, desired_align);
|
layout->record_align = MAX (layout->record_align, desired_align);
|
||||||
#endif
|
#endif /* PCC_BITFIELD_TYPE_MATTERS */
|
||||||
|
|
||||||
/* Does this field automatically have alignment it needs
|
/* Does this field automatically have alignment it needs
|
||||||
by virtue of the fields that precede it and the record's
|
by virtue of the fields that precede it and the record's
|
||||||
|
@ -875,7 +896,7 @@ void objc_layout_finish_structure (struct objc_struct_layout *layout,
|
||||||
in the record type. Round it up to a multiple of the record's
|
in the record type. Round it up to a multiple of the record's
|
||||||
alignment. */
|
alignment. */
|
||||||
|
|
||||||
#if defined(ROUND_TYPE_ALIGN) && !defined(__sparc__)
|
#if defined (ROUND_TYPE_ALIGN) && ! defined (__sparc__)
|
||||||
layout->record_align = ROUND_TYPE_ALIGN (layout->original_type,
|
layout->record_align = ROUND_TYPE_ALIGN (layout->original_type,
|
||||||
1,
|
1,
|
||||||
layout->record_align);
|
layout->record_align);
|
||||||
|
|
62
libobjc/gc.c
62
libobjc/gc.c
|
@ -1,5 +1,5 @@
|
||||||
/* Basic data types for Objective C.
|
/* Basic data types for Objective C.
|
||||||
Copyright (C) 1998 Free Software Foundation, Inc.
|
Copyright (C) 1998, 2002 Free Software Foundation, Inc.
|
||||||
Contributed by Ovidiu Predescu.
|
Contributed by Ovidiu Predescu.
|
||||||
|
|
||||||
This file is part of GNU CC.
|
This file is part of GNU CC.
|
||||||
|
@ -58,11 +58,11 @@ typedef GC_signed_word signed_word;
|
||||||
The offset is incremented with the size of the type. */
|
The offset is incremented with the size of the type. */
|
||||||
|
|
||||||
#define ROUND(V, A) \
|
#define ROUND(V, A) \
|
||||||
({ typeof(V) __v=(V); typeof(A) __a=(A); \
|
({ typeof (V) __v = (V); typeof (A) __a = (A); \
|
||||||
__a*((__v+__a-1)/__a); })
|
__a * ((__v+__a - 1)/__a); })
|
||||||
|
|
||||||
#define SET_BIT_FOR_OFFSET(mask, offset) \
|
#define SET_BIT_FOR_OFFSET(mask, offset) \
|
||||||
GC_set_bit(mask, offset / sizeof (void*))
|
GC_set_bit (mask, offset / sizeof (void *))
|
||||||
|
|
||||||
/* Some prototypes */
|
/* Some prototypes */
|
||||||
static void
|
static void
|
||||||
|
@ -74,9 +74,9 @@ __objc_gc_setup_union (GC_bitmap mask, const char *type, int offset);
|
||||||
static void
|
static void
|
||||||
__objc_gc_setup_array (GC_bitmap mask, const char *type, int offset)
|
__objc_gc_setup_array (GC_bitmap mask, const char *type, int offset)
|
||||||
{
|
{
|
||||||
int i, len = atoi(type + 1);
|
int i, len = atoi (type + 1);
|
||||||
|
|
||||||
while (isdigit(*++type))
|
while (isdigit (*++type))
|
||||||
/* do nothing */; /* skip the size of the array */
|
/* do nothing */; /* skip the size of the array */
|
||||||
|
|
||||||
switch (*type) {
|
switch (*type) {
|
||||||
|
@ -138,8 +138,8 @@ __objc_gc_setup_struct (GC_bitmap mask, const char *type, int offset)
|
||||||
case _C_PTR:
|
case _C_PTR:
|
||||||
case _C_CHARPTR:
|
case _C_CHARPTR:
|
||||||
case _C_ATOM:
|
case _C_ATOM:
|
||||||
if (!gc_invisible)
|
if (! gc_invisible)
|
||||||
SET_BIT_FOR_OFFSET(mask, position);
|
SET_BIT_FOR_OFFSET (mask, position);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case _C_ARY_B:
|
case _C_ARY_B:
|
||||||
|
@ -178,11 +178,11 @@ __objc_gc_setup_union (GC_bitmap mask, const char *type, int offset)
|
||||||
size = objc_sizeof_type (type);
|
size = objc_sizeof_type (type);
|
||||||
align = objc_alignof_type (type);
|
align = objc_alignof_type (type);
|
||||||
|
|
||||||
offset = ROUND(offset, align);
|
offset = ROUND (offset, align);
|
||||||
for (i = 0; i < size; i += sizeof (void*))
|
for (i = 0; i < size; i += sizeof (void *))
|
||||||
{
|
{
|
||||||
SET_BIT_FOR_OFFSET(mask, offset);
|
SET_BIT_FOR_OFFSET (mask, offset);
|
||||||
offset += sizeof (void*);
|
offset += sizeof (void *);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -223,8 +223,8 @@ __objc_gc_type_description_from_type (GC_bitmap mask, const char *type)
|
||||||
case _C_SEL:
|
case _C_SEL:
|
||||||
case _C_PTR:
|
case _C_PTR:
|
||||||
case _C_CHARPTR:
|
case _C_CHARPTR:
|
||||||
if (!gc_invisible)
|
if (! gc_invisible)
|
||||||
SET_BIT_FOR_OFFSET(mask, offset);
|
SET_BIT_FOR_OFFSET (mask, offset);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case _C_ARY_B:
|
case _C_ARY_B:
|
||||||
|
@ -254,9 +254,9 @@ __objc_class_structure_encoding (Class class, char **type, int *size,
|
||||||
int *current)
|
int *current)
|
||||||
{
|
{
|
||||||
int i, ivar_count;
|
int i, ivar_count;
|
||||||
struct objc_ivar_list* ivars;
|
struct objc_ivar_list *ivars;
|
||||||
|
|
||||||
if (!class)
|
if (! class)
|
||||||
{
|
{
|
||||||
strcat (*type, "{");
|
strcat (*type, "{");
|
||||||
*current++;
|
*current++;
|
||||||
|
@ -267,7 +267,7 @@ __objc_class_structure_encoding (Class class, char **type, int *size,
|
||||||
__objc_class_structure_encoding (class->super_class, type, size, current);
|
__objc_class_structure_encoding (class->super_class, type, size, current);
|
||||||
|
|
||||||
ivars = class->ivars;
|
ivars = class->ivars;
|
||||||
if (!ivars)
|
if (! ivars)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ivar_count = ivars->ivar_count;
|
ivar_count = ivars->ivar_count;
|
||||||
|
@ -282,7 +282,7 @@ __objc_class_structure_encoding (Class class, char **type, int *size,
|
||||||
{
|
{
|
||||||
/* Increase the size of the encoding string so that it
|
/* Increase the size of the encoding string so that it
|
||||||
contains this ivar's type. */
|
contains this ivar's type. */
|
||||||
*size = ROUND(*current + len + 1, 10);
|
*size = ROUND (*current + len + 1, 10);
|
||||||
*type = objc_realloc (*type, *size);
|
*type = objc_realloc (*type, *size);
|
||||||
}
|
}
|
||||||
strcat (*type + *current, ivar_type);
|
strcat (*type + *current, ivar_type);
|
||||||
|
@ -302,7 +302,7 @@ __objc_generate_gc_type_description (Class class)
|
||||||
int type_size = 10, current;
|
int type_size = 10, current;
|
||||||
char *class_structure_type;
|
char *class_structure_type;
|
||||||
|
|
||||||
if (!CLS_ISCLASS(class))
|
if (! CLS_ISCLASS (class))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* We have to create a mask in which each bit counts for a pointer member.
|
/* We have to create a mask in which each bit counts for a pointer member.
|
||||||
|
@ -311,9 +311,9 @@ __objc_generate_gc_type_description (Class class)
|
||||||
|
|
||||||
/* The number of bits in the mask is the size of an instance in bytes divided
|
/* The number of bits in the mask is the size of an instance in bytes divided
|
||||||
by the size of a pointer. */
|
by the size of a pointer. */
|
||||||
bits_no = (ROUND(class_get_instance_size (class), sizeof(void*))
|
bits_no = (ROUND (class_get_instance_size (class), sizeof (void *))
|
||||||
/ sizeof (void*));
|
/ sizeof (void *));
|
||||||
size = ROUND(bits_no, BITS_PER_WORD) / BITS_PER_WORD;
|
size = ROUND (bits_no, BITS_PER_WORD) / BITS_PER_WORD;
|
||||||
mask = objc_atomic_malloc (size * sizeof (int));
|
mask = objc_atomic_malloc (size * sizeof (int));
|
||||||
memset (mask, 0, size * sizeof (int));
|
memset (mask, 0, size * sizeof (int));
|
||||||
|
|
||||||
|
@ -342,7 +342,7 @@ __objc_generate_gc_type_description (Class class)
|
||||||
puts ("");
|
puts ("");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
class->gc_object_type = (void*)GC_make_descriptor (mask, bits_no);
|
class->gc_object_type = (void *) GC_make_descriptor (mask, bits_no);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -370,17 +370,17 @@ __objc_ivar_pointer (const char *type)
|
||||||
This operation only makes sense on instance variables that are
|
This operation only makes sense on instance variables that are
|
||||||
pointers. */
|
pointers. */
|
||||||
void
|
void
|
||||||
class_ivar_set_gcinvisible (Class class, const char* ivarname,
|
class_ivar_set_gcinvisible (Class class, const char *ivarname,
|
||||||
BOOL gc_invisible)
|
BOOL gc_invisible)
|
||||||
{
|
{
|
||||||
int i, ivar_count;
|
int i, ivar_count;
|
||||||
struct objc_ivar_list* ivars;
|
struct objc_ivar_list *ivars;
|
||||||
|
|
||||||
if (!class || !ivarname)
|
if (! class || ! ivarname)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ivars = class->ivars;
|
ivars = class->ivars;
|
||||||
if (!ivars)
|
if (! ivars)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ivar_count = ivars->ivar_count;
|
ivar_count = ivars->ivar_count;
|
||||||
|
@ -390,7 +390,7 @@ class_ivar_set_gcinvisible (Class class, const char* ivarname,
|
||||||
struct objc_ivar *ivar = &(ivars->ivar_list[i]);
|
struct objc_ivar *ivar = &(ivars->ivar_list[i]);
|
||||||
const char *type;
|
const char *type;
|
||||||
|
|
||||||
if (!ivar->ivar_name || strcmp (ivar->ivar_name, ivarname))
|
if (! ivar->ivar_name || strcmp (ivar->ivar_name, ivarname))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
assert (ivar->ivar_type);
|
assert (ivar->ivar_type);
|
||||||
|
@ -407,7 +407,7 @@ class_ivar_set_gcinvisible (Class class, const char* ivarname,
|
||||||
{
|
{
|
||||||
char *new_type;
|
char *new_type;
|
||||||
|
|
||||||
if (gc_invisible || !__objc_ivar_pointer (type))
|
if (gc_invisible || ! __objc_ivar_pointer (type))
|
||||||
return; /* The type of the variable already matches the
|
return; /* The type of the variable already matches the
|
||||||
requested gc_invisible type */
|
requested gc_invisible type */
|
||||||
|
|
||||||
|
@ -422,7 +422,7 @@ class_ivar_set_gcinvisible (Class class, const char* ivarname,
|
||||||
{
|
{
|
||||||
char *new_type;
|
char *new_type;
|
||||||
|
|
||||||
if (!gc_invisible || !__objc_ivar_pointer (type))
|
if (! gc_invisible || ! __objc_ivar_pointer (type))
|
||||||
return; /* The type of the variable already matches the
|
return; /* The type of the variable already matches the
|
||||||
requested gc_invisible type */
|
requested gc_invisible type */
|
||||||
|
|
||||||
|
@ -451,7 +451,7 @@ __objc_generate_gc_type_description (Class class __attribute__ ((__unused__)))
|
||||||
}
|
}
|
||||||
|
|
||||||
void class_ivar_set_gcinvisible (Class class __attribute__ ((__unused__)),
|
void class_ivar_set_gcinvisible (Class class __attribute__ ((__unused__)),
|
||||||
const char* ivarname __attribute__ ((__unused__)),
|
const char *ivarname __attribute__ ((__unused__)),
|
||||||
BOOL gc_invisible __attribute__ ((__unused__)))
|
BOOL gc_invisible __attribute__ ((__unused__)))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,7 +47,7 @@ hash_new (unsigned int size, hash_func_type hash_func,
|
||||||
|
|
||||||
/* Pass me a value greater than 0 and a power of 2. */
|
/* Pass me a value greater than 0 and a power of 2. */
|
||||||
assert (size);
|
assert (size);
|
||||||
assert (!(size & (size - 1)));
|
assert (! (size & (size - 1)));
|
||||||
|
|
||||||
/* Allocate the cache structure. calloc insures
|
/* Allocate the cache structure. calloc insures
|
||||||
its initialization for default values. */
|
its initialization for default values. */
|
||||||
|
@ -196,7 +196,7 @@ hash_remove (cache_ptr cache, const void *key)
|
||||||
objc_free(node);
|
objc_free(node);
|
||||||
} else
|
} else
|
||||||
prev = node, node = node->next;
|
prev = node, node = node->next;
|
||||||
} while (!removed && node);
|
} while (! removed && node);
|
||||||
assert (removed);
|
assert (removed);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -210,7 +210,7 @@ hash_next (cache_ptr cache, node_ptr node)
|
||||||
{
|
{
|
||||||
/* If the scan is being started then reset the last node
|
/* If the scan is being started then reset the last node
|
||||||
visitied pointer and bucket index. */
|
visitied pointer and bucket index. */
|
||||||
if (!node)
|
if (! node)
|
||||||
cache->last_bucket = 0;
|
cache->last_bucket = 0;
|
||||||
|
|
||||||
/* If there is a node visited last then check for another
|
/* If there is a node visited last then check for another
|
||||||
|
@ -258,7 +258,7 @@ hash_value_for_key (cache_ptr cache, const void *key)
|
||||||
break;
|
break;
|
||||||
} else
|
} else
|
||||||
node = node->next;
|
node = node->next;
|
||||||
} while (!retval && node);
|
} while (! retval && node);
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
372
libobjc/init.c
372
libobjc/init.c
|
@ -1,5 +1,5 @@
|
||||||
/* GNU Objective C Runtime initialization
|
/* GNU Objective C Runtime initialization
|
||||||
Copyright (C) 1993, 1995, 1996, 1997 Free Software Foundation, Inc.
|
Copyright (C) 1993, 1995, 1996, 1997, 2002 Free Software Foundation, Inc.
|
||||||
Contributed by Kresten Krab Thorup
|
Contributed by Kresten Krab Thorup
|
||||||
+load support contributed by Ovidiu Predescu <ovidiu@net-community.com>
|
+load support contributed by Ovidiu Predescu <ovidiu@net-community.com>
|
||||||
|
|
||||||
|
@ -27,62 +27,62 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||||
#include "runtime.h"
|
#include "runtime.h"
|
||||||
|
|
||||||
/* 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 8
|
#define OBJC_VERSION 8
|
||||||
#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. */
|
||||||
static struct objc_list* __objc_module_list = 0; /* !T:MUTEX */
|
static struct objc_list *__objc_module_list = 0; /* !T:MUTEX */
|
||||||
|
|
||||||
/* This list contains all proto_list's not yet assigned class links */
|
/* This list contains all proto_list's not yet assigned class links. */
|
||||||
static struct objc_list* unclaimed_proto_list = 0; /* !T:MUTEX */
|
static struct objc_list *unclaimed_proto_list = 0; /* !T:MUTEX */
|
||||||
|
|
||||||
/* List of unresolved static instances. */
|
/* List of unresolved static instances. */
|
||||||
static struct objc_list *uninitialized_statics = 0; /* !T:MUTEX */
|
static struct objc_list *uninitialized_statics = 0; /* !T:MUTEX */
|
||||||
|
|
||||||
/* Global runtime "write" mutex. */
|
/* Global runtime "write" mutex. */
|
||||||
objc_mutex_t __objc_runtime_mutex = 0;
|
objc_mutex_t __objc_runtime_mutex = 0;
|
||||||
|
|
||||||
/* Number of threads that are alive. */
|
/* Number of threads that are alive. */
|
||||||
int __objc_runtime_threads_alive = 1; /* !T:MUTEX */
|
int __objc_runtime_threads_alive = 1; /* !T:MUTEX */
|
||||||
|
|
||||||
/* Check compiler vs runtime version */
|
/* Check compiler vs runtime version. */
|
||||||
static void init_check_module_version (Module_t);
|
static void init_check_module_version (Module_t);
|
||||||
|
|
||||||
/* Assign isa links to protos */
|
/* Assign isa links to protos. */
|
||||||
static void __objc_init_protocols (struct objc_protocol_list* protos);
|
static void __objc_init_protocols (struct objc_protocol_list *protos);
|
||||||
|
|
||||||
/* Add protocol to class */
|
/* Add protocol to class. */
|
||||||
static void __objc_class_add_protocols (Class, struct objc_protocol_list*);
|
static void __objc_class_add_protocols (Class, struct objc_protocol_list *);
|
||||||
|
|
||||||
/* This is a hook which is called by __objc_exec_class every time a class
|
/* This is a hook which is called by __objc_exec_class every time a
|
||||||
or a category is loaded into the runtime. This may e.g. help a
|
class or a category is loaded into the runtime. This may e.g. help
|
||||||
dynamic loader determine the classes that have been loaded when
|
a dynamic loader determine the classes that have been loaded when
|
||||||
an object file is dynamically linked in */
|
an object file is dynamically linked in. */
|
||||||
void (*_objc_load_callback)(Class class, Category* category); /* !T:SAFE */
|
void (*_objc_load_callback) (Class class, Category *category); /* !T:SAFE */
|
||||||
|
|
||||||
/* Is all categories/classes resolved? */
|
/* Is all categories/classes resolved? */
|
||||||
BOOL __objc_dangling_categories = NO; /* !T:UNUSED */
|
BOOL __objc_dangling_categories = NO; /* !T:UNUSED */
|
||||||
|
|
||||||
extern SEL
|
extern SEL
|
||||||
__sel_register_typed_name (const char *name, const char *types,
|
__sel_register_typed_name (const char *name, const char *types,
|
||||||
struct objc_selector *orig, BOOL is_const);
|
struct objc_selector *orig, BOOL is_const);
|
||||||
|
|
||||||
/* Sends +load to all classes and categories in certain situations. */
|
/* Sends +load to all classes and categories in certain situations. */
|
||||||
static void objc_send_load (void);
|
static void objc_send_load (void);
|
||||||
|
|
||||||
/* Inserts all the classes defined in module in a tree of classes that
|
/* Inserts all the classes defined in module in a tree of classes that
|
||||||
resembles the class hierarchy. This tree is traversed in preorder and the
|
resembles the class hierarchy. This tree is traversed in preorder
|
||||||
classes in its nodes receive the +load message if these methods were not
|
and the classes in its nodes receive the +load message if these
|
||||||
executed before. The algorithm ensures that when the +load method of a class
|
methods were not executed before. The algorithm ensures that when
|
||||||
is executed all the superclasses have been already received the +load
|
the +load method of a class is executed all the superclasses have
|
||||||
message. */
|
been already received the +load message. */
|
||||||
static void __objc_create_classes_tree (Module_t module);
|
static void __objc_create_classes_tree (Module_t module);
|
||||||
|
|
||||||
static void __objc_call_callback (Module_t module);
|
static void __objc_call_callback (Module_t module);
|
||||||
|
|
||||||
/* A special version that works only before the classes are completely
|
/* A special version that works only before the classes are completely
|
||||||
installed in the runtime. */
|
installed in the runtime. */
|
||||||
static BOOL class_is_subclass_of_class (Class class, Class superclass);
|
static BOOL class_is_subclass_of_class (Class class, Class superclass);
|
||||||
|
|
||||||
typedef struct objc_class_tree {
|
typedef struct objc_class_tree {
|
||||||
|
@ -90,24 +90,26 @@ typedef struct objc_class_tree {
|
||||||
struct objc_list *subclasses; /* `head' is pointer to an objc_class_tree */
|
struct objc_list *subclasses; /* `head' is pointer to an objc_class_tree */
|
||||||
} objc_class_tree;
|
} objc_class_tree;
|
||||||
|
|
||||||
/* This is a linked list of objc_class_tree trees. The head of these trees
|
/* This is a linked list of objc_class_tree trees. The head of these
|
||||||
are root classes (their super class is Nil). These different trees
|
trees are root classes (their super class is Nil). These different
|
||||||
represent different class hierarchies. */
|
trees represent different class hierarchies. */
|
||||||
static struct objc_list *__objc_class_tree_list = NULL;
|
static struct objc_list *__objc_class_tree_list = NULL;
|
||||||
|
|
||||||
/* Keeps the +load methods who have been already executed. This hash should
|
/* Keeps the +load methods who have been already executed. This hash
|
||||||
not be destroyed during the execution of the program. */
|
should not be destroyed during the execution of the program. */
|
||||||
static cache_ptr __objc_load_methods = NULL;
|
static cache_ptr __objc_load_methods = NULL;
|
||||||
|
|
||||||
/* Creates a tree of classes whose topmost class is directly inherited from
|
/* Creates a tree of classes whose topmost class is directly inherited
|
||||||
`upper' and the bottom class in this tree is `bottom_class'. The classes
|
from `upper' and the bottom class in this tree is
|
||||||
in this tree are super classes of `bottom_class'. `subclasses' member
|
`bottom_class'. The classes in this tree are super classes of
|
||||||
of each tree node point to the next subclass tree node. */
|
`bottom_class'. `subclasses' member of each tree node point to the
|
||||||
|
next subclass tree node. */
|
||||||
|
|
||||||
static objc_class_tree *
|
static objc_class_tree *
|
||||||
create_tree_of_subclasses_inherited_from (Class bottom_class, Class upper)
|
create_tree_of_subclasses_inherited_from (Class bottom_class, Class upper)
|
||||||
{
|
{
|
||||||
Class superclass = bottom_class->super_class ?
|
Class superclass = bottom_class->super_class ?
|
||||||
objc_lookup_class ((char*)bottom_class->super_class)
|
objc_lookup_class ((char *) bottom_class->super_class)
|
||||||
: Nil;
|
: Nil;
|
||||||
|
|
||||||
objc_class_tree *tree, *prev;
|
objc_class_tree *tree, *prev;
|
||||||
|
@ -126,7 +128,7 @@ create_tree_of_subclasses_inherited_from (Class bottom_class, Class upper)
|
||||||
tree->class = superclass;
|
tree->class = superclass;
|
||||||
tree->subclasses = list_cons (prev, tree->subclasses);
|
tree->subclasses = list_cons (prev, tree->subclasses);
|
||||||
superclass = (superclass->super_class ?
|
superclass = (superclass->super_class ?
|
||||||
objc_lookup_class ((char*)superclass->super_class)
|
objc_lookup_class ((char *) superclass->super_class)
|
||||||
: Nil);
|
: Nil);
|
||||||
prev = tree;
|
prev = tree;
|
||||||
}
|
}
|
||||||
|
@ -134,11 +136,13 @@ create_tree_of_subclasses_inherited_from (Class bottom_class, Class upper)
|
||||||
return tree;
|
return tree;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Insert the `class' into the proper place in the `tree' class hierarchy. This
|
/* Insert the `class' into the proper place in the `tree' class
|
||||||
function returns a new tree if the class has been successfully inserted into
|
hierarchy. This function returns a new tree if the class has been
|
||||||
the tree or NULL if the class is not part of the classes hierarchy described
|
successfully inserted into the tree or NULL if the class is not
|
||||||
by `tree'. This function is private to objc_tree_insert_class(), you should
|
part of the classes hierarchy described by `tree'. This function is
|
||||||
not call it directly. */
|
private to objc_tree_insert_class (), you should not call it
|
||||||
|
directly. */
|
||||||
|
|
||||||
static objc_class_tree *
|
static objc_class_tree *
|
||||||
__objc_tree_insert_class (objc_class_tree *tree, Class class)
|
__objc_tree_insert_class (objc_class_tree *tree, Class class)
|
||||||
{
|
{
|
||||||
|
@ -154,21 +158,21 @@ __objc_tree_insert_class (objc_class_tree *tree, Class class)
|
||||||
return tree;
|
return tree;
|
||||||
}
|
}
|
||||||
else if ((class->super_class ?
|
else if ((class->super_class ?
|
||||||
objc_lookup_class ((char*)class->super_class)
|
objc_lookup_class ((char *) class->super_class)
|
||||||
: Nil)
|
: Nil)
|
||||||
== tree->class)
|
== tree->class)
|
||||||
{
|
{
|
||||||
/* If class is a direct subclass of tree->class then add class to the
|
/* If class is a direct subclass of tree->class then add class to the
|
||||||
list of subclasses. First check to see if it wasn't already
|
list of subclasses. First check to see if it wasn't already
|
||||||
inserted. */
|
inserted. */
|
||||||
struct objc_list *list = tree->subclasses;
|
struct objc_list *list = tree->subclasses;
|
||||||
objc_class_tree *node;
|
objc_class_tree *node;
|
||||||
|
|
||||||
while (list)
|
while (list)
|
||||||
{
|
{
|
||||||
/* Class has been already inserted; do nothing just return
|
/* Class has been already inserted; do nothing just return
|
||||||
the tree. */
|
the tree. */
|
||||||
if (((objc_class_tree*)list->head)->class == class)
|
if (((objc_class_tree *) list->head)->class == class)
|
||||||
{
|
{
|
||||||
DEBUG_PRINTF ("2. class %s was previously inserted\n",
|
DEBUG_PRINTF ("2. class %s was previously inserted\n",
|
||||||
class->name);
|
class->name);
|
||||||
|
@ -186,24 +190,25 @@ __objc_tree_insert_class (objc_class_tree *tree, Class class)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* The class is not a direct subclass of tree->class. Search for class's
|
/* The class is not a direct subclass of tree->class. Search for
|
||||||
superclasses in the list of subclasses. */
|
class's superclasses in the list of subclasses. */
|
||||||
struct objc_list *subclasses = tree->subclasses;
|
struct objc_list *subclasses = tree->subclasses;
|
||||||
|
|
||||||
/* Precondition: the class must be a subclass of tree->class; otherwise
|
/* Precondition: the class must be a subclass of tree->class;
|
||||||
return NULL to indicate our caller that it must take the next tree. */
|
otherwise return NULL to indicate our caller that it must
|
||||||
if (!class_is_subclass_of_class (class, tree->class))
|
take the next tree. */
|
||||||
|
if (! class_is_subclass_of_class (class, tree->class))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
for (; subclasses != NULL; subclasses = subclasses->tail)
|
for (; subclasses != NULL; subclasses = subclasses->tail)
|
||||||
{
|
{
|
||||||
Class aClass = ((objc_class_tree*)(subclasses->head))->class;
|
Class aClass = ((objc_class_tree *) (subclasses->head))->class;
|
||||||
|
|
||||||
if (class_is_subclass_of_class (class, aClass))
|
if (class_is_subclass_of_class (class, aClass))
|
||||||
{
|
{
|
||||||
/* If we found one of class's superclasses we insert the class
|
/* If we found one of class's superclasses we insert the
|
||||||
into its subtree and return the original tree since nothing
|
class into its subtree and return the original tree
|
||||||
has been changed. */
|
since nothing has been changed. */
|
||||||
subclasses->head
|
subclasses->head
|
||||||
= __objc_tree_insert_class (subclasses->head, class);
|
= __objc_tree_insert_class (subclasses->head, class);
|
||||||
DEBUG_PRINTF ("4. class %s inserted\n", class->name);
|
DEBUG_PRINTF ("4. class %s inserted\n", class->name);
|
||||||
|
@ -211,12 +216,12 @@ __objc_tree_insert_class (objc_class_tree *tree, Class class)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We haven't found a subclass of `class' in the `subclasses' list.
|
/* We haven't found a subclass of `class' in the `subclasses'
|
||||||
Create a new tree of classes whose topmost class is a direct subclass
|
list. Create a new tree of classes whose topmost class is a
|
||||||
of tree->class. */
|
direct subclass of tree->class. */
|
||||||
{
|
{
|
||||||
objc_class_tree *new_tree
|
objc_class_tree *new_tree
|
||||||
= create_tree_of_subclasses_inherited_from (class, tree->class);
|
= create_tree_of_subclasses_inherited_from (class, tree->class);
|
||||||
tree->subclasses = list_cons (new_tree, tree->subclasses);
|
tree->subclasses = list_cons (new_tree, tree->subclasses);
|
||||||
DEBUG_PRINTF ("5. class %s inserted\n", class->name);
|
DEBUG_PRINTF ("5. class %s inserted\n", class->name);
|
||||||
return tree;
|
return tree;
|
||||||
|
@ -224,7 +229,8 @@ __objc_tree_insert_class (objc_class_tree *tree, Class class)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This function inserts `class' in the right tree hierarchy classes. */
|
/* This function inserts `class' in the right tree hierarchy classes. */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
objc_tree_insert_class (Class class)
|
objc_tree_insert_class (Class class)
|
||||||
{
|
{
|
||||||
|
@ -244,20 +250,21 @@ objc_tree_insert_class (Class class)
|
||||||
list_node = list_node->tail;
|
list_node = list_node->tail;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If the list was finished but the class hasn't been inserted, insert it
|
/* If the list was finished but the class hasn't been inserted,
|
||||||
here. */
|
insert it here. */
|
||||||
if (!list_node)
|
if (! list_node)
|
||||||
{
|
{
|
||||||
__objc_class_tree_list = list_cons (NULL, __objc_class_tree_list);
|
__objc_class_tree_list = list_cons (NULL, __objc_class_tree_list);
|
||||||
__objc_class_tree_list->head = __objc_tree_insert_class (NULL, class);
|
__objc_class_tree_list->head = __objc_tree_insert_class (NULL, class);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Traverse tree in preorder. Used to send +load. */
|
/* Traverse tree in preorder. Used to send +load. */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
objc_preorder_traverse (objc_class_tree *tree,
|
objc_preorder_traverse (objc_class_tree *tree,
|
||||||
int level,
|
int level,
|
||||||
void (*function)(objc_class_tree*, int))
|
void (*function) (objc_class_tree *, int))
|
||||||
{
|
{
|
||||||
struct objc_list *node;
|
struct objc_list *node;
|
||||||
|
|
||||||
|
@ -266,11 +273,12 @@ objc_preorder_traverse (objc_class_tree *tree,
|
||||||
objc_preorder_traverse (node->head, level + 1, function);
|
objc_preorder_traverse (node->head, level + 1, function);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Traverse tree in postorder. Used to destroy a tree. */
|
/* Traverse tree in postorder. Used to destroy a tree. */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
objc_postorder_traverse (objc_class_tree *tree,
|
objc_postorder_traverse (objc_class_tree *tree,
|
||||||
int level,
|
int level,
|
||||||
void (*function)(objc_class_tree*, int))
|
void (*function) (objc_class_tree *, int))
|
||||||
{
|
{
|
||||||
struct objc_list *node;
|
struct objc_list *node;
|
||||||
|
|
||||||
|
@ -279,7 +287,8 @@ objc_postorder_traverse (objc_class_tree *tree,
|
||||||
(*function) (tree, level);
|
(*function) (tree, level);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Used to print a tree class hierarchy. */
|
/* Used to print a tree class hierarchy. */
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
static void
|
static void
|
||||||
__objc_tree_print (objc_class_tree *tree, int level)
|
__objc_tree_print (objc_class_tree *tree, int level)
|
||||||
|
@ -292,35 +301,37 @@ __objc_tree_print (objc_class_tree *tree, int level)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Walks on a linked list of methods in the reverse order and executes all
|
/* Walks on a linked list of methods in the reverse order and executes
|
||||||
the methods corresponding to `op' selector. Walking in the reverse order
|
all the methods corresponding to `op' selector. Walking in the
|
||||||
assures the +load of class is executed first and then +load of categories
|
reverse order assures the +load of class is executed first and then
|
||||||
because of the way in which categories are added to the class methods. */
|
+load of categories because of the way in which categories are
|
||||||
|
added to the class methods. */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
__objc_send_message_in_list (MethodList_t method_list, Class class, SEL op)
|
__objc_send_message_in_list (MethodList_t method_list, Class class, SEL op)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (!method_list)
|
if (! method_list)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* First execute the `op' message in the following method lists */
|
/* First execute the `op' message in the following method lists */
|
||||||
__objc_send_message_in_list (method_list->method_next, class, op);
|
__objc_send_message_in_list (method_list->method_next, class, op);
|
||||||
|
|
||||||
/* Search the method list. */
|
/* Search the method list. */
|
||||||
for (i = 0; i < method_list->method_count; i++)
|
for (i = 0; i < method_list->method_count; i++)
|
||||||
{
|
{
|
||||||
Method_t mth = &method_list->method_list[i];
|
Method_t mth = &method_list->method_list[i];
|
||||||
|
|
||||||
if (mth->method_name && sel_eq (mth->method_name, op)
|
if (mth->method_name && sel_eq (mth->method_name, op)
|
||||||
&& !hash_is_key_in_hash (__objc_load_methods, mth->method_imp))
|
&& ! hash_is_key_in_hash (__objc_load_methods, mth->method_imp))
|
||||||
{
|
{
|
||||||
/* Add this method into the +load hash table */
|
/* Add this method into the +load hash table */
|
||||||
hash_add (&__objc_load_methods, mth->method_imp, mth->method_imp);
|
hash_add (&__objc_load_methods, mth->method_imp, mth->method_imp);
|
||||||
|
|
||||||
DEBUG_PRINTF ("sending +load in class: %s\n", class->name);
|
DEBUG_PRINTF ("sending +load in class: %s\n", class->name);
|
||||||
|
|
||||||
/* The method was found and wasn't previously executed. */
|
/* The method was found and wasn't previously executed. */
|
||||||
(*mth->method_imp) ((id)class, mth->method_name);
|
(*mth->method_imp) ((id)class, mth->method_name);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
@ -336,7 +347,7 @@ __objc_send_load (objc_class_tree *tree,
|
||||||
Class class = tree->class;
|
Class class = tree->class;
|
||||||
MethodList_t method_list = class->class_pointer->methods;
|
MethodList_t method_list = class->class_pointer->methods;
|
||||||
|
|
||||||
if (!load_sel)
|
if (! load_sel)
|
||||||
load_sel = sel_register_name ("load");
|
load_sel = sel_register_name ("load");
|
||||||
|
|
||||||
__objc_send_message_in_list (method_list, class, load_sel);
|
__objc_send_message_in_list (method_list, class, load_sel);
|
||||||
|
@ -349,8 +360,9 @@ __objc_destroy_class_tree_node (objc_class_tree *tree,
|
||||||
objc_free (tree);
|
objc_free (tree);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This is used to check if the relationship between two classes before the
|
/* This is used to check if the relationship between two classes
|
||||||
runtime completely installs the classes. */
|
before the runtime completely installs the classes. */
|
||||||
|
|
||||||
static BOOL
|
static BOOL
|
||||||
class_is_subclass_of_class (Class class, Class superclass)
|
class_is_subclass_of_class (Class class, Class superclass)
|
||||||
{
|
{
|
||||||
|
@ -359,19 +371,19 @@ class_is_subclass_of_class (Class class, Class superclass)
|
||||||
if (class == superclass)
|
if (class == superclass)
|
||||||
return YES;
|
return YES;
|
||||||
class = (class->super_class ?
|
class = (class->super_class ?
|
||||||
objc_lookup_class ((char*)class->super_class)
|
objc_lookup_class ((char *) class->super_class)
|
||||||
: Nil);
|
: Nil);
|
||||||
}
|
}
|
||||||
|
|
||||||
return NO;
|
return NO;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This list contains all the classes in the runtime system for whom their
|
/* This list contains all the classes in the runtime system for whom
|
||||||
superclasses are not yet know to the runtime. */
|
their superclasses are not yet known to the runtime. */
|
||||||
static struct objc_list* unresolved_classes = 0;
|
static struct objc_list *unresolved_classes = 0;
|
||||||
|
|
||||||
/* Extern function used to reference the Object and NXConstantString classes.
|
/* Extern function used to reference the Object and NXConstantString
|
||||||
*/
|
classes. */
|
||||||
|
|
||||||
extern void __objc_force_linking (void);
|
extern void __objc_force_linking (void);
|
||||||
|
|
||||||
|
@ -382,15 +394,16 @@ __objc_force_linking (void)
|
||||||
__objc_linking ();
|
__objc_linking ();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Run through the statics list, removing modules as soon as all its statics
|
/* Run through the statics list, removing modules as soon as all its
|
||||||
have been initialized. */
|
statics have been initialized. */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
objc_init_statics (void)
|
objc_init_statics (void)
|
||||||
{
|
{
|
||||||
struct objc_list **cell = &uninitialized_statics;
|
struct objc_list **cell = &uninitialized_statics;
|
||||||
struct objc_static_instances **statics_in_module;
|
struct objc_static_instances **statics_in_module;
|
||||||
|
|
||||||
objc_mutex_lock(__objc_runtime_mutex);
|
objc_mutex_lock (__objc_runtime_mutex);
|
||||||
|
|
||||||
while (*cell)
|
while (*cell)
|
||||||
{
|
{
|
||||||
|
@ -402,7 +415,7 @@ objc_init_statics (void)
|
||||||
struct objc_static_instances *statics = *statics_in_module;
|
struct objc_static_instances *statics = *statics_in_module;
|
||||||
Class class = objc_lookup_class (statics->class_name);
|
Class class = objc_lookup_class (statics->class_name);
|
||||||
|
|
||||||
if (!class)
|
if (! class)
|
||||||
module_initialized = 0;
|
module_initialized = 0;
|
||||||
/* Actually, the static's class_pointer will be NULL when we
|
/* Actually, the static's class_pointer will be NULL when we
|
||||||
haven't been here before. However, the comparison is to be
|
haven't been here before. However, the comparison is to be
|
||||||
|
@ -432,19 +445,19 @@ objc_init_statics (void)
|
||||||
/* Remove this module from the uninitialized list. */
|
/* Remove this module from the uninitialized list. */
|
||||||
struct objc_list *this = *cell;
|
struct objc_list *this = *cell;
|
||||||
*cell = this->tail;
|
*cell = this->tail;
|
||||||
objc_free(this);
|
objc_free (this);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
cell = &(*cell)->tail;
|
cell = &(*cell)->tail;
|
||||||
}
|
}
|
||||||
|
|
||||||
objc_mutex_unlock(__objc_runtime_mutex);
|
objc_mutex_unlock (__objc_runtime_mutex);
|
||||||
} /* objc_init_statics */
|
} /* objc_init_statics */
|
||||||
|
|
||||||
/* 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
|
||||||
gather the module pointers so that they may be processed by the
|
to gather the module pointers so that they may be processed by the
|
||||||
initialization routines as soon as possible */
|
initialization routines as soon as possible. */
|
||||||
|
|
||||||
void
|
void
|
||||||
__objc_exec_class (Module_t module)
|
__objc_exec_class (Module_t module)
|
||||||
|
@ -453,7 +466,7 @@ __objc_exec_class (Module_t module)
|
||||||
indicate that some global data structures need to be built. */
|
indicate that some global data structures need to be built. */
|
||||||
static BOOL previous_constructors = 0;
|
static BOOL previous_constructors = 0;
|
||||||
|
|
||||||
static struct objc_list* unclaimed_categories = 0;
|
static struct objc_list *unclaimed_categories = 0;
|
||||||
|
|
||||||
/* The symbol table (defined in objc-api.h) generated by gcc */
|
/* The symbol table (defined in objc-api.h) generated by gcc */
|
||||||
Symtab_t symtab = module->symtab;
|
Symtab_t symtab = module->symtab;
|
||||||
|
@ -463,7 +476,7 @@ __objc_exec_class (Module_t module)
|
||||||
= symtab->defs[symtab->cls_def_cnt + symtab->cat_def_cnt];
|
= symtab->defs[symtab->cls_def_cnt + symtab->cat_def_cnt];
|
||||||
|
|
||||||
/* Entry used to traverse hash lists */
|
/* Entry used to traverse hash lists */
|
||||||
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;
|
||||||
|
@ -474,19 +487,19 @@ __objc_exec_class (Module_t module)
|
||||||
DEBUG_PRINTF ("received module: %s\n", module->name);
|
DEBUG_PRINTF ("received module: %s\n", module->name);
|
||||||
|
|
||||||
/* check gcc version */
|
/* check gcc version */
|
||||||
init_check_module_version(module);
|
init_check_module_version (module);
|
||||||
|
|
||||||
/* On the first call of this routine, initialize some data structures. */
|
/* On the first call of this routine, initialize some data structures. */
|
||||||
if (!previous_constructors)
|
if (! previous_constructors)
|
||||||
{
|
{
|
||||||
/* Initialize thread-safe system */
|
/* Initialize thread-safe system */
|
||||||
__objc_init_thread_system();
|
__objc_init_thread_system ();
|
||||||
__objc_runtime_threads_alive = 1;
|
__objc_runtime_threads_alive = 1;
|
||||||
__objc_runtime_mutex = objc_mutex_allocate();
|
__objc_runtime_mutex = objc_mutex_allocate ();
|
||||||
|
|
||||||
__objc_init_selector_tables();
|
__objc_init_selector_tables ();
|
||||||
__objc_init_class_tables();
|
__objc_init_class_tables ();
|
||||||
__objc_init_dispatch_tables();
|
__objc_init_dispatch_tables ();
|
||||||
__objc_class_tree_list = list_cons (NULL, __objc_class_tree_list);
|
__objc_class_tree_list = list_cons (NULL, __objc_class_tree_list);
|
||||||
__objc_load_methods
|
__objc_load_methods
|
||||||
= hash_new (128, (hash_func_type)hash_ptr, compare_ptrs);
|
= hash_new (128, (hash_func_type)hash_ptr, compare_ptrs);
|
||||||
|
@ -494,8 +507,8 @@ __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_mutex_lock(__objc_runtime_mutex);
|
objc_mutex_lock (__objc_runtime_mutex);
|
||||||
__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. */
|
/* Replace referenced selectors from names to SEL's. */
|
||||||
if (selectors)
|
if (selectors)
|
||||||
|
@ -503,12 +516,12 @@ __objc_exec_class (Module_t module)
|
||||||
for (i = 0; selectors[i].sel_id; ++i)
|
for (i = 0; selectors[i].sel_id; ++i)
|
||||||
{
|
{
|
||||||
const char *name, *type;
|
const char *name, *type;
|
||||||
name = (char*)selectors[i].sel_id;
|
name = (char *) selectors[i].sel_id;
|
||||||
type = (char*)selectors[i].sel_types;
|
type = (char *) selectors[i].sel_types;
|
||||||
/* Constructors are constant static data so we can safely store
|
/* Constructors are constant static data so we can safely store
|
||||||
pointers to them in the runtime structures. is_const == YES */
|
pointers to them in the runtime structures. is_const == YES */
|
||||||
__sel_register_typed_name (name, type,
|
__sel_register_typed_name (name, type,
|
||||||
(struct objc_selector*)&(selectors[i]),
|
(struct objc_selector *) &(selectors[i]),
|
||||||
YES);
|
YES);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -518,15 +531,15 @@ __objc_exec_class (Module_t module)
|
||||||
for (i = 0; i < symtab->cls_def_cnt; ++i)
|
for (i = 0; i < symtab->cls_def_cnt; ++i)
|
||||||
{
|
{
|
||||||
Class class = (Class) symtab->defs[i];
|
Class class = (Class) symtab->defs[i];
|
||||||
const char* superclass = (char*)class->super_class;
|
const char *superclass = (char *) class->super_class;
|
||||||
|
|
||||||
/* Make sure we have what we think. */
|
/* Make sure we have what we think. */
|
||||||
assert (CLS_ISCLASS(class));
|
assert (CLS_ISCLASS (class));
|
||||||
assert (CLS_ISMETA(class->class_pointer));
|
assert (CLS_ISMETA (class->class_pointer));
|
||||||
DEBUG_PRINTF ("phase 1, processing class: %s\n", class->name);
|
DEBUG_PRINTF ("phase 1, processing class: %s\n", class->name);
|
||||||
|
|
||||||
/* Initialize the subclass list to be NULL.
|
/* Initialize the subclass list to be NULL.
|
||||||
In some cases it isn't and this crashes the program. */
|
In some cases it isn't and this crashes the program. */
|
||||||
class->subclass_list = NULL;
|
class->subclass_list = NULL;
|
||||||
|
|
||||||
/* Store the class in the class table and assign class numbers. */
|
/* Store the class in the class table and assign class numbers. */
|
||||||
|
@ -537,19 +550,19 @@ __objc_exec_class (Module_t module)
|
||||||
__objc_register_selectors_from_class ((Class) class->class_pointer);
|
__objc_register_selectors_from_class ((Class) class->class_pointer);
|
||||||
|
|
||||||
/* Install the fake dispatch tables */
|
/* Install the fake dispatch tables */
|
||||||
__objc_install_premature_dtable(class);
|
__objc_install_premature_dtable (class);
|
||||||
__objc_install_premature_dtable(class->class_pointer);
|
__objc_install_premature_dtable (class->class_pointer);
|
||||||
|
|
||||||
/* Register the instance methods as class methods, this is
|
/* Register the instance methods as class methods, this is
|
||||||
only done for root classes. */
|
only done for root classes. */
|
||||||
__objc_register_instance_methods_to_class(class);
|
__objc_register_instance_methods_to_class (class);
|
||||||
|
|
||||||
if (class->protocols)
|
if (class->protocols)
|
||||||
__objc_init_protocols (class->protocols);
|
__objc_init_protocols (class->protocols);
|
||||||
|
|
||||||
/* Check to see if the superclass is known in this point. If it's not
|
/* Check to see if the superclass is known in this point. If it's not
|
||||||
add the class to the unresolved_classes list. */
|
add the class to the unresolved_classes list. */
|
||||||
if (superclass && !objc_lookup_class (superclass))
|
if (superclass && ! objc_lookup_class (superclass))
|
||||||
unresolved_classes = list_cons (class, unresolved_classes);
|
unresolved_classes = list_cons (class, unresolved_classes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -583,14 +596,14 @@ __objc_exec_class (Module_t module)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Register the instance methods as class methods, this is
|
/* Register the instance methods as class methods, this is
|
||||||
only done for root classes. */
|
only done for root classes. */
|
||||||
__objc_register_instance_methods_to_class(class);
|
__objc_register_instance_methods_to_class (class);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* The object to which the category methods belong can't be found.
|
/* The object to which the category methods belong can't be found.
|
||||||
Save the information. */
|
Save the information. */
|
||||||
unclaimed_categories = list_cons(category, unclaimed_categories);
|
unclaimed_categories = list_cons (category, unclaimed_categories);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -627,8 +640,8 @@ __objc_exec_class (Module_t module)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Register the instance methods as class methods, this is
|
/* Register the instance methods as class methods, this is
|
||||||
only done for root classes. */
|
only done for root classes. */
|
||||||
__objc_register_instance_methods_to_class(class);
|
__objc_register_instance_methods_to_class (class);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
cell = &(*cell)->tail;
|
cell = &(*cell)->tail;
|
||||||
|
@ -636,30 +649,32 @@ __objc_exec_class (Module_t module)
|
||||||
|
|
||||||
if (unclaimed_proto_list && objc_lookup_class ("Protocol"))
|
if (unclaimed_proto_list && objc_lookup_class ("Protocol"))
|
||||||
{
|
{
|
||||||
list_mapcar (unclaimed_proto_list,(void(*)(void*))__objc_init_protocols);
|
list_mapcar (unclaimed_proto_list,
|
||||||
|
(void (*) (void *))__objc_init_protocols);
|
||||||
list_free (unclaimed_proto_list);
|
list_free (unclaimed_proto_list);
|
||||||
unclaimed_proto_list = 0;
|
unclaimed_proto_list = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
objc_send_load ();
|
objc_send_load ();
|
||||||
|
|
||||||
objc_mutex_unlock(__objc_runtime_mutex);
|
objc_mutex_unlock (__objc_runtime_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void objc_send_load (void)
|
static void
|
||||||
|
objc_send_load (void)
|
||||||
{
|
{
|
||||||
if (!__objc_module_list)
|
if (! __objc_module_list)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* Try to find out if all the classes loaded so far also have their
|
/* Try to find out if all the classes loaded so far also have their
|
||||||
superclasses known to the runtime. We suppose that the objects that are
|
superclasses known to the runtime. We suppose that the objects
|
||||||
allocated in the +load method are in general of a class declared in the
|
that are allocated in the +load method are in general of a class
|
||||||
same module. */
|
declared in the same module. */
|
||||||
if (unresolved_classes)
|
if (unresolved_classes)
|
||||||
{
|
{
|
||||||
Class class = unresolved_classes->head;
|
Class class = unresolved_classes->head;
|
||||||
|
|
||||||
while (objc_lookup_class ((char*)class->super_class))
|
while (objc_lookup_class ((char *) class->super_class))
|
||||||
{
|
{
|
||||||
list_remove_head (&unresolved_classes);
|
list_remove_head (&unresolved_classes);
|
||||||
if (unresolved_classes)
|
if (unresolved_classes)
|
||||||
|
@ -668,25 +683,25 @@ static void objc_send_load (void)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/* If we still have classes for whom we don't have yet their
|
||||||
* If we still have classes for whom we don't have yet their super
|
super classes known to the runtime we don't send the +load
|
||||||
* classes known to the runtime we don't send the +load messages.
|
messages. */
|
||||||
*/
|
|
||||||
if (unresolved_classes)
|
if (unresolved_classes)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Special check to allow creating and sending messages to constant strings
|
/* Special check to allow creating and sending messages to constant
|
||||||
in +load methods. If these classes are not yet known, even if all the
|
strings in +load methods. If these classes are not yet known,
|
||||||
other classes are known, delay sending of +load. */
|
even if all the other classes are known, delay sending of +load. */
|
||||||
if (!objc_lookup_class ("NXConstantString") ||
|
if (! objc_lookup_class ("NXConstantString") ||
|
||||||
!objc_lookup_class ("Object"))
|
! objc_lookup_class ("Object"))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* Iterate over all modules in the __objc_module_list and call on them the
|
/* Iterate over all modules in the __objc_module_list and call on
|
||||||
__objc_create_classes_tree function. This function creates a tree of
|
them the __objc_create_classes_tree function. This function
|
||||||
classes that resembles the class hierarchy. */
|
creates a tree of classes that resembles the class hierarchy. */
|
||||||
list_mapcar (__objc_module_list, (void(*)(void*))__objc_create_classes_tree);
|
list_mapcar (__objc_module_list,
|
||||||
|
(void (*) (void *)) __objc_create_classes_tree);
|
||||||
|
|
||||||
while (__objc_class_tree_list)
|
while (__objc_class_tree_list)
|
||||||
{
|
{
|
||||||
|
@ -701,7 +716,7 @@ static void objc_send_load (void)
|
||||||
list_remove_head (&__objc_class_tree_list);
|
list_remove_head (&__objc_class_tree_list);
|
||||||
}
|
}
|
||||||
|
|
||||||
list_mapcar (__objc_module_list, (void(*)(void*))__objc_call_callback);
|
list_mapcar (__objc_module_list, (void (*) (void *)) __objc_call_callback);
|
||||||
list_free (__objc_module_list);
|
list_free (__objc_module_list);
|
||||||
__objc_module_list = NULL;
|
__objc_module_list = NULL;
|
||||||
}
|
}
|
||||||
|
@ -714,8 +729,8 @@ __objc_create_classes_tree (Module_t module)
|
||||||
Symtab_t symtab = module->symtab;
|
Symtab_t symtab = module->symtab;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
/* Iterate thru classes defined in this module and insert them in the classes
|
/* Iterate thru classes defined in this module and insert them in
|
||||||
tree hierarchy. */
|
the classes tree hierarchy. */
|
||||||
for (i = 0; i < symtab->cls_def_cnt; i++)
|
for (i = 0; i < symtab->cls_def_cnt; i++)
|
||||||
{
|
{
|
||||||
Class class = (Class) symtab->defs[i];
|
Class class = (Class) symtab->defs[i];
|
||||||
|
@ -727,56 +742,58 @@ __objc_create_classes_tree (Module_t module)
|
||||||
static void
|
static void
|
||||||
__objc_call_callback (Module_t module)
|
__objc_call_callback (Module_t module)
|
||||||
{
|
{
|
||||||
/* The runtime mutex is locked in this point */
|
/* The runtime mutex is locked in this point. */
|
||||||
|
|
||||||
Symtab_t symtab = module->symtab;
|
Symtab_t symtab = module->symtab;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
/* Iterate thru classes defined in this module and call the callback for
|
/* Iterate thru classes defined in this module and call the callback
|
||||||
each one. */
|
for each one. */
|
||||||
for (i = 0; i < symtab->cls_def_cnt; i++)
|
for (i = 0; i < symtab->cls_def_cnt; i++)
|
||||||
{
|
{
|
||||||
Class class = (Class) symtab->defs[i];
|
Class class = (Class) symtab->defs[i];
|
||||||
|
|
||||||
/* Call the _objc_load_callback for this class. */
|
/* Call the _objc_load_callback for this class. */
|
||||||
if (_objc_load_callback)
|
if (_objc_load_callback)
|
||||||
_objc_load_callback(class, 0);
|
_objc_load_callback (class, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Call the _objc_load_callback for categories. Don't register the instance
|
/* Call the _objc_load_callback for categories. Don't register the
|
||||||
methods as class methods for categories to root classes since they were
|
instance methods as class methods for categories to root classes
|
||||||
already added in the class. */
|
since they were already added in the class. */
|
||||||
for (i = 0; i < symtab->cat_def_cnt; i++)
|
for (i = 0; i < symtab->cat_def_cnt; i++)
|
||||||
{
|
{
|
||||||
Category_t category = symtab->defs[i + symtab->cls_def_cnt];
|
Category_t category = symtab->defs[i + symtab->cls_def_cnt];
|
||||||
Class class = objc_lookup_class (category->class_name);
|
Class class = objc_lookup_class (category->class_name);
|
||||||
|
|
||||||
if (_objc_load_callback)
|
if (_objc_load_callback)
|
||||||
_objc_load_callback(class, category);
|
_objc_load_callback (class, category);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Sanity check the version of gcc used to compile `module'*/
|
/* Sanity check the version of gcc used to compile `module'. */
|
||||||
static void init_check_module_version(Module_t module)
|
|
||||||
|
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)))
|
||||||
{
|
{
|
||||||
int code;
|
int code;
|
||||||
|
|
||||||
if(module->version > OBJC_VERSION)
|
if (module->version > OBJC_VERSION)
|
||||||
code = OBJC_ERR_OBJC_VERSION;
|
code = OBJC_ERR_OBJC_VERSION;
|
||||||
else if (module->version < OBJC_VERSION)
|
else if (module->version < OBJC_VERSION)
|
||||||
code = OBJC_ERR_GCC_VERSION;
|
code = OBJC_ERR_GCC_VERSION;
|
||||||
else
|
else
|
||||||
code = OBJC_ERR_MODULE_SIZE;
|
code = OBJC_ERR_MODULE_SIZE;
|
||||||
|
|
||||||
objc_error(nil, code, "Module %s version %d doesn't match runtime %d\n",
|
objc_error (nil, code, "Module %s version %d doesn't match runtime %d\n",
|
||||||
module->name, (int)module->version, OBJC_VERSION);
|
module->name, (int)module->version, OBJC_VERSION);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
__objc_init_protocols (struct objc_protocol_list* protos)
|
__objc_init_protocols (struct objc_protocol_list *protos)
|
||||||
{
|
{
|
||||||
size_t i;
|
size_t i;
|
||||||
static Class proto_class = 0;
|
static Class proto_class = 0;
|
||||||
|
@ -784,15 +801,15 @@ __objc_init_protocols (struct objc_protocol_list* protos)
|
||||||
if (! protos)
|
if (! protos)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
objc_mutex_lock(__objc_runtime_mutex);
|
objc_mutex_lock (__objc_runtime_mutex);
|
||||||
|
|
||||||
if (!proto_class)
|
if (! proto_class)
|
||||||
proto_class = objc_lookup_class("Protocol");
|
proto_class = objc_lookup_class ("Protocol");
|
||||||
|
|
||||||
if (!proto_class)
|
if (! proto_class)
|
||||||
{
|
{
|
||||||
unclaimed_proto_list = list_cons (protos, unclaimed_proto_list);
|
unclaimed_proto_list = list_cons (protos, unclaimed_proto_list);
|
||||||
objc_mutex_unlock(__objc_runtime_mutex);
|
objc_mutex_unlock (__objc_runtime_mutex);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -800,9 +817,9 @@ __objc_init_protocols (struct objc_protocol_list* protos)
|
||||||
assert (protos->next == 0); /* only single ones allowed */
|
assert (protos->next == 0); /* only single ones allowed */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
for(i = 0; i < protos->count; i++)
|
for (i = 0; i < protos->count; i++)
|
||||||
{
|
{
|
||||||
struct objc_protocol* aProto = protos->list[i];
|
struct objc_protocol *aProto = protos->list[i];
|
||||||
if (((size_t)aProto->class_pointer) == PROTOCOL_VERSION)
|
if (((size_t)aProto->class_pointer) == PROTOCOL_VERSION)
|
||||||
{
|
{
|
||||||
/* assign class pointer */
|
/* assign class pointer */
|
||||||
|
@ -813,24 +830,25 @@ __objc_init_protocols (struct objc_protocol_list* protos)
|
||||||
}
|
}
|
||||||
else if (protos->list[i]->class_pointer != proto_class)
|
else if (protos->list[i]->class_pointer != proto_class)
|
||||||
{
|
{
|
||||||
objc_error(nil, OBJC_ERR_PROTOCOL_VERSION,
|
objc_error (nil, OBJC_ERR_PROTOCOL_VERSION,
|
||||||
"Version %d doesn't match runtime protocol version %d\n",
|
"Version %d doesn't match runtime protocol version %d\n",
|
||||||
(int)((char*)protos->list[i]->class_pointer-(char*)0),
|
(int) ((char *) protos->list[i]->class_pointer
|
||||||
|
- (char *) 0),
|
||||||
PROTOCOL_VERSION);
|
PROTOCOL_VERSION);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
objc_mutex_unlock(__objc_runtime_mutex);
|
objc_mutex_unlock (__objc_runtime_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __objc_class_add_protocols (Class class,
|
static void
|
||||||
struct objc_protocol_list* protos)
|
__objc_class_add_protocols (Class class, struct objc_protocol_list *protos)
|
||||||
{
|
{
|
||||||
/* Well... */
|
/* Well... */
|
||||||
if (! protos)
|
if (! protos)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* Add it... */
|
/* Add it... */
|
||||||
protos->next = class->protocols;
|
protos->next = class->protocols;
|
||||||
class->protocols = protos;
|
class->protocols = protos;
|
||||||
}
|
}
|
||||||
|
|
103
libobjc/misc.c
103
libobjc/misc.c
|
@ -1,5 +1,6 @@
|
||||||
/* GNU Objective C Runtime Miscellaneous
|
/* GNU Objective C Runtime Miscellaneous
|
||||||
Copyright (C) 1993, 1994, 1995, 1996, 1997 Free Software Foundation, Inc.
|
Copyright (C) 1993, 1994, 1995, 1996, 1997, 2002
|
||||||
|
Free Software Foundation, Inc.
|
||||||
Contributed by Kresten Krab Thorup
|
Contributed by Kresten Krab Thorup
|
||||||
|
|
||||||
This file is part of GNU CC.
|
This file is part of GNU CC.
|
||||||
|
@ -37,25 +38,25 @@ static objc_error_handler _objc_error_handler = NULL;
|
||||||
|
|
||||||
/* Trigger an objc error */
|
/* Trigger an objc error */
|
||||||
void
|
void
|
||||||
objc_error(id object, int code, const char* fmt, ...)
|
objc_error (id object, int code, const char *fmt, ...)
|
||||||
{
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
|
|
||||||
va_start(ap, fmt);
|
va_start (ap, fmt);
|
||||||
objc_verror(object, code, fmt, ap);
|
objc_verror (object, code, fmt, ap);
|
||||||
va_end(ap);
|
va_end (ap);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Trigger an objc error */
|
/* Trigger an objc error */
|
||||||
void
|
void
|
||||||
objc_verror(id object, int code, const char* fmt, va_list ap)
|
objc_verror (id object, int code, const char *fmt, va_list ap)
|
||||||
{
|
{
|
||||||
BOOL result = NO;
|
BOOL result = NO;
|
||||||
|
|
||||||
/* Call the error handler if its there
|
/* Call the error handler if its there
|
||||||
Otherwise print to stderr */
|
Otherwise print to stderr */
|
||||||
if (_objc_error_handler)
|
if (_objc_error_handler)
|
||||||
result = (*_objc_error_handler)(object, code, fmt, ap);
|
result = (*_objc_error_handler) (object, code, fmt, ap);
|
||||||
else
|
else
|
||||||
vfprintf (stderr, fmt, ap);
|
vfprintf (stderr, fmt, ap);
|
||||||
|
|
||||||
|
@ -64,12 +65,12 @@ objc_verror(id object, int code, const char* fmt, va_list ap)
|
||||||
if (result)
|
if (result)
|
||||||
return;
|
return;
|
||||||
else
|
else
|
||||||
abort();
|
abort ();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set the error handler */
|
/* Set the error handler */
|
||||||
objc_error_handler
|
objc_error_handler
|
||||||
objc_set_error_handler(objc_error_handler func)
|
objc_set_error_handler (objc_error_handler func)
|
||||||
{
|
{
|
||||||
objc_error_handler temp = _objc_error_handler;
|
objc_error_handler temp = _objc_error_handler;
|
||||||
_objc_error_handler = func;
|
_objc_error_handler = func;
|
||||||
|
@ -84,54 +85,54 @@ objc_set_error_handler(objc_error_handler func)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void *
|
void *
|
||||||
objc_malloc(size_t size)
|
objc_malloc (size_t size)
|
||||||
{
|
{
|
||||||
void* res = (void*) (*_objc_malloc)(size);
|
void *res = (void *) (*_objc_malloc) (size);
|
||||||
if(!res)
|
if (! res)
|
||||||
objc_error(nil, OBJC_ERR_MEMORY, "Virtual memory exhausted\n");
|
objc_error (nil, OBJC_ERR_MEMORY, "Virtual memory exhausted\n");
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
void *
|
void *
|
||||||
objc_atomic_malloc(size_t size)
|
objc_atomic_malloc (size_t size)
|
||||||
{
|
{
|
||||||
void* res = (void*) (*_objc_atomic_malloc)(size);
|
void *res = (void *) (*_objc_atomic_malloc) (size);
|
||||||
if(!res)
|
if (! res)
|
||||||
objc_error(nil, OBJC_ERR_MEMORY, "Virtual memory exhausted\n");
|
objc_error (nil, OBJC_ERR_MEMORY, "Virtual memory exhausted\n");
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
void *
|
void *
|
||||||
objc_valloc(size_t size)
|
objc_valloc (size_t size)
|
||||||
{
|
{
|
||||||
void* res = (void*) (*_objc_valloc)(size);
|
void *res = (void *) (*_objc_valloc) (size);
|
||||||
if(!res)
|
if (! res)
|
||||||
objc_error(nil, OBJC_ERR_MEMORY, "Virtual memory exhausted\n");
|
objc_error (nil, OBJC_ERR_MEMORY, "Virtual memory exhausted\n");
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
void *
|
void *
|
||||||
objc_realloc(void *mem, size_t size)
|
objc_realloc (void *mem, size_t size)
|
||||||
{
|
{
|
||||||
void* res = (void*) (*_objc_realloc)(mem, size);
|
void *res = (void *) (*_objc_realloc) (mem, size);
|
||||||
if(!res)
|
if (! res)
|
||||||
objc_error(nil, OBJC_ERR_MEMORY, "Virtual memory exhausted\n");
|
objc_error (nil, OBJC_ERR_MEMORY, "Virtual memory exhausted\n");
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
void *
|
void *
|
||||||
objc_calloc(size_t nelem, size_t size)
|
objc_calloc (size_t nelem, size_t size)
|
||||||
{
|
{
|
||||||
void* res = (void*) (*_objc_calloc)(nelem, size);
|
void *res = (void *) (*_objc_calloc) (nelem, size);
|
||||||
if(!res)
|
if (! res)
|
||||||
objc_error(nil, OBJC_ERR_MEMORY, "Virtual memory exhausted\n");
|
objc_error (nil, OBJC_ERR_MEMORY, "Virtual memory exhausted\n");
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
objc_free(void *mem)
|
objc_free (void *mem)
|
||||||
{
|
{
|
||||||
(*_objc_free)(mem);
|
(*_objc_free) (mem);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -148,33 +149,37 @@ objc_free(void *mem)
|
||||||
#if OBJC_WITH_GC
|
#if OBJC_WITH_GC
|
||||||
#include <gc.h>
|
#include <gc.h>
|
||||||
|
|
||||||
static void *GC_calloc (size_t nelem, size_t size)
|
static void *
|
||||||
|
GC_calloc (size_t nelem, size_t size)
|
||||||
{
|
{
|
||||||
void* p = GC_malloc (nelem * size);
|
void *p = GC_malloc (nelem * size);
|
||||||
if (!p)
|
if (! p)
|
||||||
objc_error (nil, OBJC_ERR_MEMORY, "Virtual memory exhausted!\n");
|
objc_error (nil, OBJC_ERR_MEMORY, "Virtual memory exhausted!\n");
|
||||||
|
|
||||||
memset (p, 0, nelem * size);
|
memset (p, 0, nelem * size);
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void noFree (void* p) {}
|
static void
|
||||||
|
noFree (void *p)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
void *(*_objc_malloc)(size_t) = GC_malloc;
|
void *(*_objc_malloc) (size_t) = GC_malloc;
|
||||||
void *(*_objc_atomic_malloc)(size_t) = GC_malloc_atomic;
|
void *(*_objc_atomic_malloc) (size_t) = GC_malloc_atomic;
|
||||||
void *(*_objc_valloc)(size_t) = GC_malloc;
|
void *(*_objc_valloc) (size_t) = GC_malloc;
|
||||||
void *(*_objc_realloc)(void *, size_t) = GC_realloc;
|
void *(*_objc_realloc) (void *, size_t) = GC_realloc;
|
||||||
void *(*_objc_calloc)(size_t, size_t) = GC_calloc;
|
void *(*_objc_calloc) (size_t, size_t) = GC_calloc;
|
||||||
void (*_objc_free)(void *) = noFree;
|
void (*_objc_free) (void *) = noFree;
|
||||||
|
|
||||||
#else
|
#else /* !OBJC_WITH_GC */
|
||||||
|
|
||||||
void *(*_objc_malloc)(size_t) = malloc;
|
void *(*_objc_malloc) (size_t) = malloc;
|
||||||
void *(*_objc_atomic_malloc)(size_t) = malloc;
|
void *(*_objc_atomic_malloc) (size_t) = malloc;
|
||||||
void *(*_objc_valloc)(size_t) = malloc;
|
void *(*_objc_valloc) (size_t) = malloc;
|
||||||
void *(*_objc_realloc)(void *, size_t) = realloc;
|
void *(*_objc_realloc) (void *, size_t) = realloc;
|
||||||
void *(*_objc_calloc)(size_t, size_t) = calloc;
|
void *(*_objc_calloc) (size_t, size_t) = calloc;
|
||||||
void (*_objc_free)(void *) = free;
|
void (*_objc_free) (void *) = free;
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif /* !OBJC_WITH_GC */
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/* GNU Objective C Runtime nil receiver function
|
/* GNU Objective C Runtime nil receiver function
|
||||||
Copyright (C) 1993, 1995, 1996 Free Software Foundation, Inc.
|
Copyright (C) 1993, 1995, 1996, 2002 Free Software Foundation, Inc.
|
||||||
Contributed by Kresten Krab Thorup
|
Contributed by Kresten Krab Thorup
|
||||||
|
|
||||||
This file is part of GNU CC.
|
This file is part of GNU CC.
|
||||||
|
@ -30,11 +30,7 @@ Boston, MA 02111-1307, USA. */
|
||||||
#include "runtime.h"
|
#include "runtime.h"
|
||||||
|
|
||||||
id
|
id
|
||||||
nil_method(id receiver, SEL op __attribute__ ((__unused__)), ...)
|
nil_method (id receiver, SEL op __attribute__ ((__unused__)), ...)
|
||||||
{
|
{
|
||||||
return receiver;
|
return receiver;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/* Encoding of types for Objective C.
|
/* Encoding of types for Objective C.
|
||||||
Copyright (C) 1993, 1997 Free Software Foundation, Inc.
|
Copyright (C) 1993, 1997, 2002 Free Software Foundation, Inc.
|
||||||
|
|
||||||
Author: Kresten Krab Thorup
|
Author: Kresten Krab Thorup
|
||||||
|
|
||||||
|
@ -50,30 +50,30 @@ Boston, MA 02111-1307, USA. */
|
||||||
#define _F_ONEWAY 0x10
|
#define _F_ONEWAY 0x10
|
||||||
#define _F_GCINVISIBLE 0x20
|
#define _F_GCINVISIBLE 0x20
|
||||||
|
|
||||||
int objc_aligned_size (const char* type);
|
int objc_aligned_size (const char *type);
|
||||||
int objc_sizeof_type (const char* type);
|
int objc_sizeof_type (const char *type);
|
||||||
int objc_alignof_type (const char* type);
|
int objc_alignof_type (const char *type);
|
||||||
int objc_aligned_size (const char* type);
|
int objc_aligned_size (const char *type);
|
||||||
int objc_promoted_size (const char* type);
|
int objc_promoted_size (const char *type);
|
||||||
|
|
||||||
const char* objc_skip_type_qualifiers (const char* type);
|
const char *objc_skip_type_qualifiers (const char *type);
|
||||||
const char* objc_skip_typespec (const char* type);
|
const char *objc_skip_typespec (const char *type);
|
||||||
const char* objc_skip_offset (const char* type);
|
const char *objc_skip_offset (const char *type);
|
||||||
const char* objc_skip_argspec (const char* type);
|
const char *objc_skip_argspec (const char *type);
|
||||||
int method_get_number_of_arguments (struct objc_method*);
|
int method_get_number_of_arguments (struct objc_method *);
|
||||||
int method_get_sizeof_arguments (struct objc_method*);
|
int method_get_sizeof_arguments (struct objc_method *);
|
||||||
|
|
||||||
char* method_get_first_argument (struct objc_method*,
|
char *method_get_first_argument (struct objc_method *,
|
||||||
arglist_t argframe,
|
arglist_t argframe,
|
||||||
const char** type);
|
const char **type);
|
||||||
char* method_get_next_argument (arglist_t argframe,
|
char *method_get_next_argument (arglist_t argframe,
|
||||||
const char **type);
|
const char **type);
|
||||||
char* method_get_nth_argument (struct objc_method* m,
|
char *method_get_nth_argument (struct objc_method *m,
|
||||||
arglist_t argframe,
|
arglist_t argframe,
|
||||||
int arg,
|
int arg,
|
||||||
const char **type);
|
const char **type);
|
||||||
|
|
||||||
unsigned objc_get_type_qualifiers (const char* type);
|
unsigned objc_get_type_qualifiers (const char *type);
|
||||||
|
|
||||||
|
|
||||||
struct objc_struct_layout
|
struct objc_struct_layout
|
||||||
|
|
|
@ -60,7 +60,7 @@ typedef struct cache_node
|
||||||
* typedef. Therefore, to remove compiler warnings the functions passed to
|
* typedef. Therefore, to remove compiler warnings the functions passed to
|
||||||
* hash_new will have to be casted to this type.
|
* hash_new will have to be casted to this type.
|
||||||
*/
|
*/
|
||||||
typedef unsigned int (*hash_func_type)(void *, const void *);
|
typedef unsigned int (*hash_func_type) (void *, const void *);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This data type is the function that compares two hash keys and returns an
|
* This data type is the function that compares two hash keys and returns an
|
||||||
|
@ -69,7 +69,7 @@ typedef unsigned int (*hash_func_type)(void *, const void *);
|
||||||
* second.
|
* second.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
typedef int (*compare_func_type)(const void *, const void *);
|
typedef int (*compare_func_type) (const void *, const void *);
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -174,8 +174,8 @@ hash_string (cache_ptr cache, const void *key)
|
||||||
unsigned int ctr = 0;
|
unsigned int ctr = 0;
|
||||||
|
|
||||||
|
|
||||||
while (*(char*)key) {
|
while (*(char *) key) {
|
||||||
ret ^= *(char*)key++ << ctr;
|
ret ^= *(char *) key++ << ctr;
|
||||||
ctr = (ctr + 1) % sizeof (void *);
|
ctr = (ctr + 1) % sizeof (void *);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -187,7 +187,7 @@ hash_string (cache_ptr cache, const void *key)
|
||||||
static inline int
|
static inline int
|
||||||
compare_ptrs (const void *k1, const void *k2)
|
compare_ptrs (const void *k1, const void *k2)
|
||||||
{
|
{
|
||||||
return !(k1 - k2);
|
return ! (k1 - k2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -200,7 +200,7 @@ compare_strings (const void *k1, const void *k2)
|
||||||
else if (k1 == 0 || k2 == 0)
|
else if (k1 == 0 || k2 == 0)
|
||||||
return 0;
|
return 0;
|
||||||
else
|
else
|
||||||
return !strcmp (k1, k2);
|
return ! strcmp (k1, k2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/* Thread and mutex controls for Objective C.
|
/* Thread and mutex controls for Objective C.
|
||||||
Copyright (C) 1996, 1997 Free Software Foundation, Inc.
|
Copyright (C) 1996, 1997, 2002 Free Software Foundation, Inc.
|
||||||
Contributed by Galen C. Hunt (gchunt@cs.rochester.edu)
|
Contributed by Galen C. Hunt (gchunt@cs.rochester.edu)
|
||||||
|
|
||||||
This file is part of GNU CC.
|
This file is part of GNU CC.
|
||||||
|
@ -74,30 +74,30 @@ struct objc_condition
|
||||||
typedef struct objc_condition *objc_condition_t;
|
typedef struct objc_condition *objc_condition_t;
|
||||||
|
|
||||||
/* Frontend mutex functions */
|
/* Frontend mutex functions */
|
||||||
objc_mutex_t objc_mutex_allocate(void);
|
objc_mutex_t objc_mutex_allocate (void);
|
||||||
int objc_mutex_deallocate(objc_mutex_t mutex);
|
int objc_mutex_deallocate (objc_mutex_t mutex);
|
||||||
int objc_mutex_lock(objc_mutex_t mutex);
|
int objc_mutex_lock (objc_mutex_t mutex);
|
||||||
int objc_mutex_unlock(objc_mutex_t mutex);
|
int objc_mutex_unlock (objc_mutex_t mutex);
|
||||||
int objc_mutex_trylock(objc_mutex_t mutex);
|
int objc_mutex_trylock (objc_mutex_t mutex);
|
||||||
|
|
||||||
/* Frontend condition mutex functions */
|
/* Frontend condition mutex functions */
|
||||||
objc_condition_t objc_condition_allocate(void);
|
objc_condition_t objc_condition_allocate (void);
|
||||||
int objc_condition_deallocate(objc_condition_t condition);
|
int objc_condition_deallocate (objc_condition_t condition);
|
||||||
int objc_condition_wait(objc_condition_t condition, objc_mutex_t mutex);
|
int objc_condition_wait (objc_condition_t condition, objc_mutex_t mutex);
|
||||||
int objc_condition_signal(objc_condition_t condition);
|
int objc_condition_signal (objc_condition_t condition);
|
||||||
int objc_condition_broadcast(objc_condition_t condition);
|
int objc_condition_broadcast (objc_condition_t condition);
|
||||||
|
|
||||||
/* Frontend thread functions */
|
/* Frontend thread functions */
|
||||||
objc_thread_t objc_thread_detach(SEL selector, id object, id argument);
|
objc_thread_t objc_thread_detach (SEL selector, id object, id argument);
|
||||||
void objc_thread_yield(void);
|
void objc_thread_yield (void);
|
||||||
int objc_thread_exit(void);
|
int objc_thread_exit (void);
|
||||||
int objc_thread_set_priority(int priority);
|
int objc_thread_set_priority (int priority);
|
||||||
int objc_thread_get_priority(void);
|
int objc_thread_get_priority (void);
|
||||||
void * objc_thread_get_data(void);
|
void * objc_thread_get_data (void);
|
||||||
int objc_thread_set_data(void *value);
|
int objc_thread_set_data (void *value);
|
||||||
objc_thread_t objc_thread_id(void);
|
objc_thread_t objc_thread_id (void);
|
||||||
void objc_thread_add(void);
|
void objc_thread_add (void);
|
||||||
void objc_thread_remove(void);
|
void objc_thread_remove (void);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Use this to set the hook function that will be called when the
|
Use this to set the hook function that will be called when the
|
||||||
|
@ -111,35 +111,35 @@ void objc_thread_remove(void);
|
||||||
it can be informed; for example, the GNUstep Base Library sets it
|
it can be informed; for example, the GNUstep Base Library sets it
|
||||||
so it can implement the NSBecomingMultiThreaded notification.
|
so it can implement the NSBecomingMultiThreaded notification.
|
||||||
*/
|
*/
|
||||||
typedef void (*objc_thread_callback)(void);
|
typedef void (*objc_thread_callback) (void);
|
||||||
objc_thread_callback objc_set_thread_callback(objc_thread_callback func);
|
objc_thread_callback objc_set_thread_callback (objc_thread_callback func);
|
||||||
|
|
||||||
/* Backend initialization functions */
|
/* Backend initialization functions */
|
||||||
int __objc_init_thread_system(void);
|
int __objc_init_thread_system (void);
|
||||||
int __objc_fini_thread_system(void);
|
int __objc_fini_thread_system (void);
|
||||||
|
|
||||||
/* Backend mutex functions */
|
/* Backend mutex functions */
|
||||||
int __objc_mutex_allocate(objc_mutex_t mutex);
|
int __objc_mutex_allocate (objc_mutex_t mutex);
|
||||||
int __objc_mutex_deallocate(objc_mutex_t mutex);
|
int __objc_mutex_deallocate (objc_mutex_t mutex);
|
||||||
int __objc_mutex_lock(objc_mutex_t mutex);
|
int __objc_mutex_lock (objc_mutex_t mutex);
|
||||||
int __objc_mutex_trylock(objc_mutex_t mutex);
|
int __objc_mutex_trylock (objc_mutex_t mutex);
|
||||||
int __objc_mutex_unlock(objc_mutex_t mutex);
|
int __objc_mutex_unlock (objc_mutex_t mutex);
|
||||||
|
|
||||||
/* Backend condition mutex functions */
|
/* Backend condition mutex functions */
|
||||||
int __objc_condition_allocate(objc_condition_t condition);
|
int __objc_condition_allocate (objc_condition_t condition);
|
||||||
int __objc_condition_deallocate(objc_condition_t condition);
|
int __objc_condition_deallocate (objc_condition_t condition);
|
||||||
int __objc_condition_wait(objc_condition_t condition, objc_mutex_t mutex);
|
int __objc_condition_wait (objc_condition_t condition, objc_mutex_t mutex);
|
||||||
int __objc_condition_broadcast(objc_condition_t condition);
|
int __objc_condition_broadcast (objc_condition_t condition);
|
||||||
int __objc_condition_signal(objc_condition_t condition);
|
int __objc_condition_signal (objc_condition_t condition);
|
||||||
|
|
||||||
/* Backend thread functions */
|
/* Backend thread functions */
|
||||||
objc_thread_t __objc_thread_detach(void (*func)(void *arg), void *arg);
|
objc_thread_t __objc_thread_detach (void (*func) (void *arg), void *arg);
|
||||||
int __objc_thread_set_priority(int priority);
|
int __objc_thread_set_priority (int priority);
|
||||||
int __objc_thread_get_priority(void);
|
int __objc_thread_get_priority (void);
|
||||||
void __objc_thread_yield(void);
|
void __objc_thread_yield (void);
|
||||||
int __objc_thread_exit(void);
|
int __objc_thread_exit (void);
|
||||||
objc_thread_t __objc_thread_id(void);
|
objc_thread_t __objc_thread_id (void);
|
||||||
int __objc_thread_set_data(void *value);
|
int __objc_thread_set_data (void *value);
|
||||||
void * __objc_thread_get_data(void);
|
void * __objc_thread_get_data (void);
|
||||||
|
|
||||||
#endif /* not __thread_INCLUDE_GNU */
|
#endif /* not __thread_INCLUDE_GNU */
|
||||||
|
|
|
@ -32,29 +32,29 @@ Boston, MA 02111-1307, USA. */
|
||||||
# include <gc.h>
|
# include <gc.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
id __objc_object_alloc(Class);
|
id __objc_object_alloc (Class);
|
||||||
id __objc_object_dispose(id);
|
id __objc_object_dispose (id);
|
||||||
id __objc_object_copy(id);
|
id __objc_object_copy (id);
|
||||||
|
|
||||||
id (*_objc_object_alloc)(Class) = __objc_object_alloc; /* !T:SINGLE */
|
id (*_objc_object_alloc) (Class) = __objc_object_alloc; /* !T:SINGLE */
|
||||||
id (*_objc_object_dispose)(id) = __objc_object_dispose; /* !T:SINGLE */
|
id (*_objc_object_dispose) (id) = __objc_object_dispose; /* !T:SINGLE */
|
||||||
id (*_objc_object_copy)(id) = __objc_object_copy; /* !T:SINGLE */
|
id (*_objc_object_copy) (id) = __objc_object_copy; /* !T:SINGLE */
|
||||||
|
|
||||||
id
|
id
|
||||||
class_create_instance(Class class)
|
class_create_instance (Class class)
|
||||||
{
|
{
|
||||||
id new = nil;
|
id new = nil;
|
||||||
|
|
||||||
#if OBJC_WITH_GC
|
#if OBJC_WITH_GC
|
||||||
if (CLS_ISCLASS(class))
|
if (CLS_ISCLASS (class))
|
||||||
new = (id)GC_malloc_explicitly_typed (class->instance_size,
|
new = (id) GC_malloc_explicitly_typed (class->instance_size,
|
||||||
class->gc_object_type);
|
class->gc_object_type);
|
||||||
#else
|
#else
|
||||||
if (CLS_ISCLASS(class))
|
if (CLS_ISCLASS (class))
|
||||||
new = (*_objc_object_alloc)(class);
|
new = (*_objc_object_alloc) (class);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (new!=nil)
|
if (new != nil)
|
||||||
{
|
{
|
||||||
memset (new, 0, class->instance_size);
|
memset (new, 0, class->instance_size);
|
||||||
new->class_pointer = class;
|
new->class_pointer = class;
|
||||||
|
@ -63,43 +63,41 @@ class_create_instance(Class class)
|
||||||
}
|
}
|
||||||
|
|
||||||
id
|
id
|
||||||
object_copy(id object)
|
object_copy (id object)
|
||||||
{
|
{
|
||||||
if ((object!=nil)&&CLS_ISCLASS(object->class_pointer))
|
if ((object != nil) && CLS_ISCLASS (object->class_pointer))
|
||||||
return (*_objc_object_copy)(object);
|
return (*_objc_object_copy) (object);
|
||||||
else
|
else
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
id
|
id
|
||||||
object_dispose(id object)
|
object_dispose (id object)
|
||||||
{
|
{
|
||||||
if ((object!=nil)&&CLS_ISCLASS(object->class_pointer))
|
if ((object != nil) && CLS_ISCLASS (object->class_pointer))
|
||||||
{
|
{
|
||||||
if (_objc_object_dispose)
|
if (_objc_object_dispose)
|
||||||
(*_objc_object_dispose)(object);
|
(*_objc_object_dispose) (object);
|
||||||
else
|
else
|
||||||
objc_free(object);
|
objc_free (object);
|
||||||
}
|
}
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
id __objc_object_alloc(Class class)
|
id __objc_object_alloc (Class class)
|
||||||
{
|
{
|
||||||
return (id)objc_malloc(class->instance_size);
|
return (id) objc_malloc (class->instance_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
id __objc_object_dispose(id object)
|
id __objc_object_dispose (id object)
|
||||||
{
|
{
|
||||||
objc_free(object);
|
objc_free (object);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
id __objc_object_copy(id object)
|
id __objc_object_copy (id object)
|
||||||
{
|
{
|
||||||
id copy = class_create_instance(object->class_pointer);
|
id copy = class_create_instance (object->class_pointer);
|
||||||
memcpy(copy, object, object->class_pointer->instance_size);
|
memcpy (copy, object, object->class_pointer->instance_size);
|
||||||
return copy;
|
return copy;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
245
libobjc/sarray.c
245
libobjc/sarray.c
|
@ -1,5 +1,5 @@
|
||||||
/* Sparse Arrays for Objective C dispatch tables
|
/* Sparse Arrays for Objective C dispatch tables
|
||||||
Copyright (C) 1993, 1995, 1996 Free Software Foundation, Inc.
|
Copyright (C) 1993, 1995, 1996, 2002 Free Software Foundation, Inc.
|
||||||
|
|
||||||
This file is part of GNU CC.
|
This file is part of GNU CC.
|
||||||
|
|
||||||
|
@ -34,36 +34,36 @@ int nindices = 0; /* !T:MUTEX */
|
||||||
int narrays = 0; /* !T:MUTEX */
|
int narrays = 0; /* !T:MUTEX */
|
||||||
int idxsize = 0; /* !T:MUTEX */
|
int idxsize = 0; /* !T:MUTEX */
|
||||||
|
|
||||||
static void * first_free_data = NULL; /* !T:MUTEX */
|
static void *first_free_data = NULL; /* !T:MUTEX */
|
||||||
|
|
||||||
#ifdef OBJC_SPARSE2
|
#ifdef OBJC_SPARSE2
|
||||||
const char* __objc_sparse2_id = "2 level sparse indices";
|
const char *__objc_sparse2_id = "2 level sparse indices";
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef OBJC_SPARSE3
|
#ifdef OBJC_SPARSE3
|
||||||
const char* __objc_sparse3_id = "3 level sparse indices";
|
const char *__objc_sparse3_id = "3 level sparse indices";
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* This function removes any structures left over from free operations
|
/* This function removes any structures left over from free operations
|
||||||
that were not safe in a multi-threaded environment. */
|
that were not safe in a multi-threaded environment. */
|
||||||
void
|
void
|
||||||
sarray_remove_garbage(void)
|
sarray_remove_garbage (void)
|
||||||
{
|
{
|
||||||
void **vp;
|
void **vp;
|
||||||
void *np;
|
void *np;
|
||||||
|
|
||||||
objc_mutex_lock(__objc_runtime_mutex);
|
objc_mutex_lock (__objc_runtime_mutex);
|
||||||
|
|
||||||
vp = first_free_data;
|
vp = first_free_data;
|
||||||
first_free_data = NULL;
|
first_free_data = NULL;
|
||||||
|
|
||||||
while (vp) {
|
while (vp) {
|
||||||
np = *vp;
|
np = *vp;
|
||||||
objc_free(vp);
|
objc_free (vp);
|
||||||
vp = np;
|
vp = np;
|
||||||
}
|
}
|
||||||
|
|
||||||
objc_mutex_unlock(__objc_runtime_mutex);
|
objc_mutex_unlock (__objc_runtime_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Free a block of dynamically allocated memory. If we are in multi-threaded
|
/* Free a block of dynamically allocated memory. If we are in multi-threaded
|
||||||
|
@ -71,33 +71,33 @@ sarray_remove_garbage(void)
|
||||||
freed later. */
|
freed later. */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
sarray_free_garbage(void *vp)
|
sarray_free_garbage (void *vp)
|
||||||
{
|
{
|
||||||
objc_mutex_lock(__objc_runtime_mutex);
|
objc_mutex_lock (__objc_runtime_mutex);
|
||||||
|
|
||||||
if (__objc_runtime_threads_alive == 1) {
|
if (__objc_runtime_threads_alive == 1) {
|
||||||
objc_free(vp);
|
objc_free (vp);
|
||||||
if (first_free_data)
|
if (first_free_data)
|
||||||
sarray_remove_garbage();
|
sarray_remove_garbage ();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
*(void **)vp = first_free_data;
|
*(void **)vp = first_free_data;
|
||||||
first_free_data = vp;
|
first_free_data = vp;
|
||||||
}
|
}
|
||||||
|
|
||||||
objc_mutex_unlock(__objc_runtime_mutex);
|
objc_mutex_unlock (__objc_runtime_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* sarray_at_put : copies data in such a way as to be thread reader safe. */
|
/* sarray_at_put : copies data in such a way as to be thread reader safe. */
|
||||||
void
|
void
|
||||||
sarray_at_put(struct sarray* array, sidx index, void* element)
|
sarray_at_put (struct sarray *array, sidx index, void *element)
|
||||||
{
|
{
|
||||||
#ifdef OBJC_SPARSE3
|
#ifdef OBJC_SPARSE3
|
||||||
struct sindex** the_index;
|
struct sindex **the_index;
|
||||||
struct sindex* new_index;
|
struct sindex *new_index;
|
||||||
#endif
|
#endif
|
||||||
struct sbucket** the_bucket;
|
struct sbucket **the_bucket;
|
||||||
struct sbucket* new_bucket;
|
struct sbucket *new_bucket;
|
||||||
#ifdef OBJC_SPARSE3
|
#ifdef OBJC_SPARSE3
|
||||||
size_t ioffset;
|
size_t ioffset;
|
||||||
#endif
|
#endif
|
||||||
|
@ -122,7 +122,7 @@ sarray_at_put(struct sarray* array, sidx index, void* element)
|
||||||
#endif
|
#endif
|
||||||
#endif /* not PRECOMPUTE_SELECTORS */
|
#endif /* not PRECOMPUTE_SELECTORS */
|
||||||
|
|
||||||
assert(soffset_decode(index) < array->capacity); /* Range check */
|
assert (soffset_decode (index) < array->capacity); /* Range check */
|
||||||
|
|
||||||
#ifdef OBJC_SPARSE3
|
#ifdef OBJC_SPARSE3
|
||||||
the_index = &(array->indices[ioffset]);
|
the_index = &(array->indices[ioffset]);
|
||||||
|
@ -141,8 +141,8 @@ sarray_at_put(struct sarray* array, sidx index, void* element)
|
||||||
if ((*the_index) == array->empty_index) {
|
if ((*the_index) == array->empty_index) {
|
||||||
|
|
||||||
/* The index was previously empty, allocate a new */
|
/* The index was previously empty, allocate a new */
|
||||||
new_index = (struct sindex*)objc_malloc(sizeof(struct sindex));
|
new_index = (struct sindex *) objc_malloc (sizeof (struct sindex));
|
||||||
memcpy(new_index, array->empty_index, sizeof(struct sindex));
|
memcpy (new_index, array->empty_index, sizeof (struct sindex));
|
||||||
new_index->version.version = array->version.version;
|
new_index->version.version = array->version.version;
|
||||||
*the_index = new_index; /* Prepared for install. */
|
*the_index = new_index; /* Prepared for install. */
|
||||||
the_bucket = &((*the_index)->buckets[boffset]);
|
the_bucket = &((*the_index)->buckets[boffset]);
|
||||||
|
@ -151,9 +151,9 @@ sarray_at_put(struct sarray* array, sidx index, void* element)
|
||||||
} else if ((*the_index)->version.version != array->version.version) {
|
} else if ((*the_index)->version.version != array->version.version) {
|
||||||
|
|
||||||
/* This index must be lazy copied */
|
/* This index must be lazy copied */
|
||||||
struct sindex* old_index = *the_index;
|
struct sindex *old_index = *the_index;
|
||||||
new_index = (struct sindex*)objc_malloc(sizeof(struct sindex));
|
new_index = (struct sindex *) objc_malloc (sizeof (struct sindex));
|
||||||
memcpy( new_index, old_index, sizeof(struct sindex));
|
memcpy (new_index, old_index, sizeof (struct sindex));
|
||||||
new_index->version.version = array->version.version;
|
new_index->version.version = array->version.version;
|
||||||
*the_index = new_index; /* Prepared for install. */
|
*the_index = new_index; /* Prepared for install. */
|
||||||
the_bucket = &((*the_index)->buckets[boffset]);
|
the_bucket = &((*the_index)->buckets[boffset]);
|
||||||
|
@ -169,9 +169,9 @@ 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 */
|
||||||
new_bucket = (struct sbucket*)objc_malloc(sizeof(struct sbucket));
|
new_bucket = (struct sbucket *) objc_malloc (sizeof (struct sbucket));
|
||||||
memcpy((void *) new_bucket, (const void*)array->empty_bucket,
|
memcpy ((void *) new_bucket, (const void *) array->empty_bucket,
|
||||||
sizeof(struct sbucket));
|
sizeof (struct sbucket));
|
||||||
new_bucket->version.version = array->version.version;
|
new_bucket->version.version = array->version.version;
|
||||||
*the_bucket = new_bucket; /* Prepared for install. */
|
*the_bucket = new_bucket; /* Prepared for install. */
|
||||||
|
|
||||||
|
@ -180,9 +180,9 @@ sarray_at_put(struct sarray* array, sidx index, void* element)
|
||||||
} else if ((*the_bucket)->version.version != array->version.version) {
|
} else if ((*the_bucket)->version.version != array->version.version) {
|
||||||
|
|
||||||
/* Perform lazy copy. */
|
/* Perform lazy copy. */
|
||||||
struct sbucket* old_bucket = *the_bucket;
|
struct sbucket *old_bucket = *the_bucket;
|
||||||
new_bucket = (struct sbucket*)objc_malloc(sizeof(struct sbucket));
|
new_bucket = (struct sbucket *) objc_malloc (sizeof (struct sbucket));
|
||||||
memcpy( new_bucket, old_bucket, sizeof(struct sbucket));
|
memcpy (new_bucket, old_bucket, sizeof (struct sbucket));
|
||||||
new_bucket->version.version = array->version.version;
|
new_bucket->version.version = array->version.version;
|
||||||
*the_bucket = new_bucket; /* Prepared for install. */
|
*the_bucket = new_bucket; /* Prepared for install. */
|
||||||
|
|
||||||
|
@ -193,39 +193,39 @@ sarray_at_put(struct sarray* array, sidx index, void* element)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
sarray_at_put_safe(struct sarray* array, sidx index, void* element)
|
sarray_at_put_safe (struct sarray *array, sidx index, void *element)
|
||||||
{
|
{
|
||||||
if(soffset_decode(index) >= array->capacity)
|
if (soffset_decode (index) >= array->capacity)
|
||||||
sarray_realloc(array, soffset_decode(index)+1);
|
sarray_realloc (array, soffset_decode (index) + 1);
|
||||||
sarray_at_put(array, index, element);
|
sarray_at_put (array, index, element);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct sarray*
|
struct sarray *
|
||||||
sarray_new (int size, void* default_element)
|
sarray_new (int size, void *default_element)
|
||||||
{
|
{
|
||||||
struct sarray* arr;
|
struct sarray *arr;
|
||||||
#ifdef OBJC_SPARSE3
|
#ifdef OBJC_SPARSE3
|
||||||
size_t num_indices = ((size-1)/(INDEX_CAPACITY))+1;
|
size_t num_indices = ((size - 1)/(INDEX_CAPACITY)) + 1;
|
||||||
struct sindex ** new_indices;
|
struct sindex **new_indices;
|
||||||
#else /* OBJC_SPARSE2 */
|
#else /* OBJC_SPARSE2 */
|
||||||
size_t num_indices = ((size-1)/BUCKET_SIZE)+1;
|
size_t num_indices = ((size - 1)/BUCKET_SIZE) + 1;
|
||||||
struct sbucket ** new_buckets;
|
struct sbucket **new_buckets;
|
||||||
#endif
|
#endif
|
||||||
size_t counter;
|
size_t counter;
|
||||||
|
|
||||||
assert(size > 0);
|
assert (size > 0);
|
||||||
|
|
||||||
/* Allocate core array */
|
/* Allocate core array */
|
||||||
arr = (struct sarray*) objc_malloc(sizeof(struct sarray));
|
arr = (struct sarray *) objc_malloc (sizeof (struct sarray));
|
||||||
arr->version.version = 0;
|
arr->version.version = 0;
|
||||||
|
|
||||||
/* Initialize members */
|
/* Initialize members */
|
||||||
#ifdef OBJC_SPARSE3
|
#ifdef OBJC_SPARSE3
|
||||||
arr->capacity = num_indices*INDEX_CAPACITY;
|
arr->capacity = num_indices*INDEX_CAPACITY;
|
||||||
new_indices = (struct sindex**)
|
new_indices = (struct sindex **)
|
||||||
objc_malloc(sizeof(struct sindex*)*num_indices);
|
objc_malloc (sizeof (struct sindex *) * num_indices);
|
||||||
|
|
||||||
arr->empty_index = (struct sindex*) objc_malloc(sizeof(struct sindex));
|
arr->empty_index = (struct sindex *) objc_malloc (sizeof (struct sindex));
|
||||||
arr->empty_index->version.version = 0;
|
arr->empty_index->version.version = 0;
|
||||||
|
|
||||||
narrays += 1;
|
narrays += 1;
|
||||||
|
@ -234,35 +234,35 @@ sarray_new (int size, void* default_element)
|
||||||
|
|
||||||
#else /* OBJC_SPARSE2 */
|
#else /* OBJC_SPARSE2 */
|
||||||
arr->capacity = num_indices*BUCKET_SIZE;
|
arr->capacity = num_indices*BUCKET_SIZE;
|
||||||
new_buckets = (struct sbucket**)
|
new_buckets = (struct sbucket **)
|
||||||
objc_malloc(sizeof(struct sbucket*)*num_indices);
|
objc_malloc (sizeof (struct sbucket *) * num_indices);
|
||||||
|
|
||||||
narrays += 1;
|
narrays += 1;
|
||||||
idxsize += num_indices;
|
idxsize += num_indices;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
arr->empty_bucket = (struct sbucket*) objc_malloc(sizeof(struct sbucket));
|
arr->empty_bucket = (struct sbucket *) objc_malloc (sizeof (struct sbucket));
|
||||||
arr->empty_bucket->version.version = 0;
|
arr->empty_bucket->version.version = 0;
|
||||||
|
|
||||||
nbuckets += 1;
|
nbuckets += 1;
|
||||||
|
|
||||||
arr->ref_count = 1;
|
arr->ref_count = 1;
|
||||||
arr->is_copy_of = (struct sarray*)0;
|
arr->is_copy_of = (struct sarray *) 0;
|
||||||
|
|
||||||
for (counter=0; counter<BUCKET_SIZE; counter++)
|
for (counter = 0; counter < BUCKET_SIZE; counter++)
|
||||||
arr->empty_bucket->elems[counter] = default_element;
|
arr->empty_bucket->elems[counter] = default_element;
|
||||||
|
|
||||||
#ifdef OBJC_SPARSE3
|
#ifdef OBJC_SPARSE3
|
||||||
for (counter=0; counter<INDEX_SIZE; counter++)
|
for (counter = 0; counter < INDEX_SIZE; counter++)
|
||||||
arr->empty_index->buckets[counter] = arr->empty_bucket;
|
arr->empty_index->buckets[counter] = arr->empty_bucket;
|
||||||
|
|
||||||
for (counter=0; counter<num_indices; counter++)
|
for (counter = 0; counter < num_indices; counter++)
|
||||||
new_indices[counter] = arr->empty_index;
|
new_indices[counter] = arr->empty_index;
|
||||||
|
|
||||||
#else /* OBJC_SPARSE2 */
|
#else /* OBJC_SPARSE2 */
|
||||||
|
|
||||||
for (counter=0; counter<num_indices; counter++)
|
for (counter = 0; counter < num_indices; counter++)
|
||||||
new_buckets[counter] = arr->empty_bucket;
|
new_buckets[counter] = arr->empty_bucket;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -282,48 +282,48 @@ sarray_new (int size, void* default_element)
|
||||||
any concurrent readers notice the update. */
|
any concurrent readers notice the update. */
|
||||||
|
|
||||||
void
|
void
|
||||||
sarray_realloc(struct sarray* array, int newsize)
|
sarray_realloc (struct sarray *array, int newsize)
|
||||||
{
|
{
|
||||||
#ifdef OBJC_SPARSE3
|
#ifdef OBJC_SPARSE3
|
||||||
size_t old_max_index = (array->capacity-1)/INDEX_CAPACITY;
|
size_t old_max_index = (array->capacity - 1)/INDEX_CAPACITY;
|
||||||
size_t new_max_index = ((newsize-1)/INDEX_CAPACITY);
|
size_t new_max_index = ((newsize - 1)/INDEX_CAPACITY);
|
||||||
size_t rounded_size = (new_max_index+1)*INDEX_CAPACITY;
|
size_t rounded_size = (new_max_index + 1) * INDEX_CAPACITY;
|
||||||
|
|
||||||
struct sindex ** new_indices;
|
struct sindex **new_indices;
|
||||||
struct sindex ** old_indices;
|
struct sindex **old_indices;
|
||||||
|
|
||||||
#else /* OBJC_SPARSE2 */
|
#else /* OBJC_SPARSE2 */
|
||||||
size_t old_max_index = (array->capacity-1)/BUCKET_SIZE;
|
size_t old_max_index = (array->capacity - 1)/BUCKET_SIZE;
|
||||||
size_t new_max_index = ((newsize-1)/BUCKET_SIZE);
|
size_t new_max_index = ((newsize - 1)/BUCKET_SIZE);
|
||||||
size_t rounded_size = (new_max_index+1)*BUCKET_SIZE;
|
size_t rounded_size = (new_max_index + 1) * BUCKET_SIZE;
|
||||||
|
|
||||||
struct sbucket ** new_buckets;
|
struct sbucket **new_buckets;
|
||||||
struct sbucket ** old_buckets;
|
struct sbucket **old_buckets;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
size_t counter;
|
size_t counter;
|
||||||
|
|
||||||
assert(newsize > 0);
|
assert (newsize > 0);
|
||||||
|
|
||||||
/* The size is the same, just ignore the request */
|
/* The size is the same, just ignore the request */
|
||||||
if(rounded_size <= array->capacity)
|
if (rounded_size <= array->capacity)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
assert(array->ref_count == 1); /* stop if lazy copied... */
|
assert (array->ref_count == 1); /* stop if lazy copied... */
|
||||||
|
|
||||||
/* We are asked to extend the array -- allocate new bucket table, */
|
/* We are asked to extend the array -- allocate new bucket table, */
|
||||||
/* and insert empty_bucket in newly allocated places. */
|
/* and insert empty_bucket in newly allocated places. */
|
||||||
if(rounded_size > array->capacity)
|
if (rounded_size > array->capacity)
|
||||||
{
|
{
|
||||||
|
|
||||||
#ifdef OBJC_SPARSE3
|
#ifdef OBJC_SPARSE3
|
||||||
new_max_index += 4;
|
new_max_index += 4;
|
||||||
rounded_size = (new_max_index+1)*INDEX_CAPACITY;
|
rounded_size = (new_max_index + 1) * INDEX_CAPACITY;
|
||||||
|
|
||||||
#else /* OBJC_SPARSE2 */
|
#else /* OBJC_SPARSE2 */
|
||||||
new_max_index += 4;
|
new_max_index += 4;
|
||||||
rounded_size = (new_max_index+1)*BUCKET_SIZE;
|
rounded_size = (new_max_index + 1) * BUCKET_SIZE;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* update capacity */
|
/* update capacity */
|
||||||
|
@ -332,16 +332,16 @@ sarray_realloc(struct sarray* array, int newsize)
|
||||||
#ifdef OBJC_SPARSE3
|
#ifdef OBJC_SPARSE3
|
||||||
/* alloc to force re-read by any concurrent readers. */
|
/* alloc to force re-read by any concurrent readers. */
|
||||||
old_indices = array->indices;
|
old_indices = array->indices;
|
||||||
new_indices = (struct sindex**)
|
new_indices = (struct sindex **)
|
||||||
objc_malloc((new_max_index+1)*sizeof(struct sindex*));
|
objc_malloc ((new_max_index + 1) * sizeof (struct sindex *));
|
||||||
#else /* OBJC_SPARSE2 */
|
#else /* OBJC_SPARSE2 */
|
||||||
old_buckets = array->buckets;
|
old_buckets = array->buckets;
|
||||||
new_buckets = (struct sbucket**)
|
new_buckets = (struct sbucket **)
|
||||||
objc_malloc((new_max_index+1)*sizeof(struct sbucket*));
|
objc_malloc ((new_max_index + 1) * sizeof (struct sbucket *));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* copy buckets below old_max_index (they are still valid) */
|
/* copy buckets below old_max_index (they are still valid) */
|
||||||
for(counter = 0; counter <= old_max_index; counter++ ) {
|
for (counter = 0; counter <= old_max_index; counter++ ) {
|
||||||
#ifdef OBJC_SPARSE3
|
#ifdef OBJC_SPARSE3
|
||||||
new_indices[counter] = old_indices[counter];
|
new_indices[counter] = old_indices[counter];
|
||||||
#else /* OBJC_SPARSE2 */
|
#else /* OBJC_SPARSE2 */
|
||||||
|
@ -351,11 +351,11 @@ sarray_realloc(struct sarray* array, int newsize)
|
||||||
|
|
||||||
#ifdef OBJC_SPARSE3
|
#ifdef OBJC_SPARSE3
|
||||||
/* reset entries above old_max_index to empty_bucket */
|
/* reset entries above old_max_index to empty_bucket */
|
||||||
for(counter = old_max_index+1; counter <= new_max_index; counter++)
|
for (counter = old_max_index + 1; counter <= new_max_index; counter++)
|
||||||
new_indices[counter] = array->empty_index;
|
new_indices[counter] = array->empty_index;
|
||||||
#else /* OBJC_SPARSE2 */
|
#else /* OBJC_SPARSE2 */
|
||||||
/* reset entries above old_max_index to empty_bucket */
|
/* reset entries above old_max_index to empty_bucket */
|
||||||
for(counter = old_max_index+1; counter <= new_max_index; counter++)
|
for (counter = old_max_index + 1; counter <= new_max_index; counter++)
|
||||||
new_buckets[counter] = array->empty_bucket;
|
new_buckets[counter] = array->empty_bucket;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -368,9 +368,9 @@ sarray_realloc(struct sarray* array, int newsize)
|
||||||
|
|
||||||
#ifdef OBJC_SPARSE3
|
#ifdef OBJC_SPARSE3
|
||||||
/* free the old indices */
|
/* free the old indices */
|
||||||
sarray_free_garbage(old_indices);
|
sarray_free_garbage (old_indices);
|
||||||
#else /* OBJC_SPARSE2 */
|
#else /* OBJC_SPARSE2 */
|
||||||
sarray_free_garbage(old_buckets);
|
sarray_free_garbage (old_buckets);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
idxsize += (new_max_index-old_max_index);
|
idxsize += (new_max_index-old_max_index);
|
||||||
|
@ -382,20 +382,19 @@ sarray_realloc(struct sarray* array, int newsize)
|
||||||
/* Free a sparse array allocated with sarray_new */
|
/* Free a sparse array allocated with sarray_new */
|
||||||
|
|
||||||
void
|
void
|
||||||
sarray_free(struct sarray* array)
|
sarray_free (struct sarray *array) {
|
||||||
{
|
|
||||||
#ifdef OBJC_SPARSE3
|
#ifdef OBJC_SPARSE3
|
||||||
size_t old_max_index = (array->capacity-1)/INDEX_CAPACITY;
|
size_t old_max_index = (array->capacity - 1)/INDEX_CAPACITY;
|
||||||
struct sindex ** old_indices;
|
struct sindex **old_indices;
|
||||||
#else
|
#else
|
||||||
size_t old_max_index = (array->capacity-1)/BUCKET_SIZE;
|
size_t old_max_index = (array->capacity - 1)/BUCKET_SIZE;
|
||||||
struct sbucket ** old_buckets;
|
struct sbucket **old_buckets;
|
||||||
#endif
|
#endif
|
||||||
size_t counter = 0;
|
size_t counter = 0;
|
||||||
|
|
||||||
assert(array->ref_count != 0); /* Freed multiple times!!! */
|
assert (array->ref_count != 0); /* Freed multiple times!!! */
|
||||||
|
|
||||||
if(--(array->ref_count) != 0) /* There exists copies of me */
|
if (--(array->ref_count) != 0) /* There exists copies of me */
|
||||||
return;
|
return;
|
||||||
|
|
||||||
#ifdef OBJC_SPARSE3
|
#ifdef OBJC_SPARSE3
|
||||||
|
@ -404,34 +403,34 @@ sarray_free(struct sarray* array)
|
||||||
old_buckets = array->buckets;
|
old_buckets = array->buckets;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if((array->is_copy_of) && ((array->is_copy_of->ref_count - 1) == 0))
|
if ((array->is_copy_of) && ((array->is_copy_of->ref_count - 1) == 0))
|
||||||
sarray_free(array->is_copy_of);
|
sarray_free (array->is_copy_of);
|
||||||
|
|
||||||
/* Free all entries that do not point to empty_bucket */
|
/* Free all entries that do not point to empty_bucket */
|
||||||
for(counter = 0; counter <= old_max_index; counter++ ) {
|
for (counter = 0; counter <= old_max_index; counter++ ) {
|
||||||
#ifdef OBJC_SPARSE3
|
#ifdef OBJC_SPARSE3
|
||||||
struct sindex* idx = old_indices[counter];
|
struct sindex *idx = old_indices[counter];
|
||||||
if((idx != array->empty_index) &&
|
if ((idx != array->empty_index) &&
|
||||||
(idx->version.version == array->version.version)) {
|
(idx->version.version == array->version.version)) {
|
||||||
int c2;
|
int c2;
|
||||||
for(c2=0; c2<INDEX_SIZE; c2++) {
|
for (c2 = 0; c2 < INDEX_SIZE; c2++) {
|
||||||
struct sbucket* bkt = idx->buckets[c2];
|
struct sbucket *bkt = idx->buckets[c2];
|
||||||
if((bkt != array->empty_bucket) &&
|
if ((bkt != array->empty_bucket) &&
|
||||||
(bkt->version.version == array->version.version))
|
(bkt->version.version == array->version.version))
|
||||||
{
|
{
|
||||||
sarray_free_garbage(bkt);
|
sarray_free_garbage (bkt);
|
||||||
nbuckets -= 1;
|
nbuckets -= 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sarray_free_garbage(idx);
|
sarray_free_garbage (idx);
|
||||||
nindices -= 1;
|
nindices -= 1;
|
||||||
}
|
}
|
||||||
#else /* OBJC_SPARSE2 */
|
#else /* OBJC_SPARSE2 */
|
||||||
struct sbucket* bkt = array->buckets[counter];
|
struct sbucket *bkt = array->buckets[counter];
|
||||||
if ((bkt != array->empty_bucket) &&
|
if ((bkt != array->empty_bucket) &&
|
||||||
(bkt->version.version == array->version.version))
|
(bkt->version.version == array->version.version))
|
||||||
{
|
{
|
||||||
sarray_free_garbage(bkt);
|
sarray_free_garbage (bkt);
|
||||||
nbuckets -= 1;
|
nbuckets -= 1;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -439,52 +438,52 @@ sarray_free(struct sarray* array)
|
||||||
|
|
||||||
#ifdef OBJC_SPARSE3
|
#ifdef OBJC_SPARSE3
|
||||||
/* free empty_index */
|
/* free empty_index */
|
||||||
if(array->empty_index->version.version == array->version.version) {
|
if (array->empty_index->version.version == array->version.version) {
|
||||||
sarray_free_garbage(array->empty_index);
|
sarray_free_garbage (array->empty_index);
|
||||||
nindices -= 1;
|
nindices -= 1;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* free empty_bucket */
|
/* free empty_bucket */
|
||||||
if(array->empty_bucket->version.version == array->version.version) {
|
if (array->empty_bucket->version.version == array->version.version) {
|
||||||
sarray_free_garbage(array->empty_bucket);
|
sarray_free_garbage (array->empty_bucket);
|
||||||
nbuckets -= 1;
|
nbuckets -= 1;
|
||||||
}
|
}
|
||||||
idxsize -= (old_max_index+1);
|
idxsize -= (old_max_index + 1);
|
||||||
narrays -= 1;
|
narrays -= 1;
|
||||||
|
|
||||||
#ifdef OBJC_SPARSE3
|
#ifdef OBJC_SPARSE3
|
||||||
/* free bucket table */
|
/* free bucket table */
|
||||||
sarray_free_garbage(array->indices);
|
sarray_free_garbage (array->indices);
|
||||||
|
|
||||||
#else
|
#else
|
||||||
/* free bucket table */
|
/* free bucket table */
|
||||||
sarray_free_garbage(array->buckets);
|
sarray_free_garbage (array->buckets);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* free array */
|
/* free array */
|
||||||
sarray_free_garbage(array);
|
sarray_free_garbage (array);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This is a lazy copy. Only the core of the structure is actually */
|
/* This is a lazy copy. Only the core of the structure is actually */
|
||||||
/* copied. */
|
/* copied. */
|
||||||
|
|
||||||
struct sarray*
|
struct sarray *
|
||||||
sarray_lazy_copy(struct sarray* oarr)
|
sarray_lazy_copy (struct sarray *oarr)
|
||||||
{
|
{
|
||||||
struct sarray* arr;
|
struct sarray *arr;
|
||||||
|
|
||||||
#ifdef OBJC_SPARSE3
|
#ifdef OBJC_SPARSE3
|
||||||
size_t num_indices = ((oarr->capacity-1)/INDEX_CAPACITY)+1;
|
size_t num_indices = ((oarr->capacity - 1)/INDEX_CAPACITY) + 1;
|
||||||
struct sindex ** new_indices;
|
struct sindex **new_indices;
|
||||||
#else /* OBJC_SPARSE2 */
|
#else /* OBJC_SPARSE2 */
|
||||||
size_t num_indices = ((oarr->capacity-1)/BUCKET_SIZE)+1;
|
size_t num_indices = ((oarr->capacity - 1)/BUCKET_SIZE) + 1;
|
||||||
struct sbucket ** new_buckets;
|
struct sbucket **new_buckets;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Allocate core array */
|
/* Allocate core array */
|
||||||
arr = (struct sarray*) objc_malloc(sizeof(struct sarray)); /* !!! */
|
arr = (struct sarray *) objc_malloc (sizeof (struct sarray)); /* !!! */
|
||||||
arr->version.version = oarr->version.version + 1;
|
arr->version.version = oarr->version.version + 1;
|
||||||
#ifdef OBJC_SPARSE3
|
#ifdef OBJC_SPARSE3
|
||||||
arr->empty_index = oarr->empty_index;
|
arr->empty_index = oarr->empty_index;
|
||||||
|
@ -497,17 +496,15 @@ sarray_lazy_copy(struct sarray* oarr)
|
||||||
|
|
||||||
#ifdef OBJC_SPARSE3
|
#ifdef OBJC_SPARSE3
|
||||||
/* Copy bucket table */
|
/* Copy bucket table */
|
||||||
new_indices = (struct sindex**)
|
new_indices = (struct sindex **)
|
||||||
objc_malloc(sizeof(struct sindex*)*num_indices);
|
objc_malloc (sizeof (struct sindex *) * num_indices);
|
||||||
memcpy( new_indices,oarr->indices,
|
memcpy (new_indices, oarr->indices, sizeof (struct sindex *) * num_indices);
|
||||||
sizeof(struct sindex*)*num_indices);
|
|
||||||
arr->indices = new_indices;
|
arr->indices = new_indices;
|
||||||
#else
|
#else
|
||||||
/* Copy bucket table */
|
/* Copy bucket table */
|
||||||
new_buckets = (struct sbucket**)
|
new_buckets = (struct sbucket **)
|
||||||
objc_malloc(sizeof(struct sbucket*)*num_indices);
|
objc_malloc (sizeof (struct sbucket *) * num_indices);
|
||||||
memcpy( new_buckets,oarr->buckets,
|
memcpy (new_buckets, oarr->buckets, sizeof (struct sbucket *) * num_indices);
|
||||||
sizeof(struct sbucket*)*num_indices);
|
|
||||||
arr->buckets = new_buckets;
|
arr->buckets = new_buckets;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -31,16 +31,16 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||||
#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 -> sel !T:MUTEX */
|
static struct sarray *__objc_selector_array = 0; /* uid -> sel !T:MUTEX */
|
||||||
static struct sarray* __objc_selector_names = 0; /* uid -> name !T:MUTEX */
|
static struct sarray *__objc_selector_names = 0; /* uid -> name !T:MUTEX */
|
||||||
static cache_ptr __objc_selector_hash = 0; /* name -> uid !T:MUTEX */
|
static cache_ptr __objc_selector_hash = 0; /* name -> uid !T:MUTEX */
|
||||||
|
|
||||||
static void register_selectors_from_list(MethodList_t);
|
static void register_selectors_from_list (MethodList_t);
|
||||||
|
|
||||||
/* Number of selectors stored in each of the above tables */
|
/* Number of selectors stored in each of the above tables */
|
||||||
unsigned int __objc_selector_max_index = 0; /* !T:MUTEX */
|
unsigned int __objc_selector_max_index = 0; /* !T:MUTEX */
|
||||||
|
|
||||||
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_names = sarray_new (SELECTOR_HASH_SIZE, 0);
|
||||||
|
@ -81,15 +81,15 @@ register_selectors_from_list (MethodList_t method_list)
|
||||||
{
|
{
|
||||||
Method_t method = &method_list->method_list[i];
|
Method_t method = &method_list->method_list[i];
|
||||||
method->method_name
|
method->method_name
|
||||||
= sel_register_typed_name ((const char*)method->method_name,
|
= sel_register_typed_name ((const char *) method->method_name,
|
||||||
method->method_types);
|
method->method_types);
|
||||||
i += 1;
|
i += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Register instance methods as class methods for root classes */
|
/* Register instance methods as class methods for root classes */
|
||||||
void __objc_register_instance_methods_to_class(Class class)
|
void __objc_register_instance_methods_to_class (Class class)
|
||||||
{
|
{
|
||||||
MethodList_t method_list;
|
MethodList_t method_list;
|
||||||
MethodList_t class_method_list;
|
MethodList_t class_method_list;
|
||||||
|
@ -98,12 +98,12 @@ void __objc_register_instance_methods_to_class(Class class)
|
||||||
Method_t curr_method;
|
Method_t curr_method;
|
||||||
|
|
||||||
/* Only if a root class. */
|
/* Only if a root class. */
|
||||||
if(class->super_class)
|
if (class->super_class)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* Allocate a method list to hold the new class methods */
|
/* Allocate a method list to hold the new class methods */
|
||||||
new_list = objc_calloc(sizeof(struct objc_method_list)
|
new_list = objc_calloc (sizeof (struct objc_method_list)
|
||||||
+ sizeof(struct objc_method[max_methods_no]), 1);
|
+ sizeof (struct objc_method[max_methods_no]), 1);
|
||||||
method_list = class->methods;
|
method_list = class->methods;
|
||||||
class_method_list = class->class_pointer->methods;
|
class_method_list = class->class_pointer->methods;
|
||||||
curr_method = &new_list->method_list[0];
|
curr_method = &new_list->method_list[0];
|
||||||
|
@ -118,7 +118,7 @@ void __objc_register_instance_methods_to_class(Class class)
|
||||||
{
|
{
|
||||||
Method_t mth = &method_list->method_list[i];
|
Method_t mth = &method_list->method_list[i];
|
||||||
if (mth->method_name
|
if (mth->method_name
|
||||||
&& !search_for_method_in_list (class_method_list,
|
&& ! search_for_method_in_list (class_method_list,
|
||||||
mth->method_name))
|
mth->method_name))
|
||||||
{
|
{
|
||||||
/* This instance method isn't a class method.
|
/* This instance method isn't a class method.
|
||||||
|
@ -126,10 +126,10 @@ void __objc_register_instance_methods_to_class(Class class)
|
||||||
*curr_method = *mth;
|
*curr_method = *mth;
|
||||||
|
|
||||||
/* Reallocate the method list if necessary */
|
/* Reallocate the method list if necessary */
|
||||||
if(++new_list->method_count == max_methods_no)
|
if (++new_list->method_count == max_methods_no)
|
||||||
new_list =
|
new_list =
|
||||||
objc_realloc(new_list, sizeof(struct objc_method_list)
|
objc_realloc (new_list, sizeof (struct objc_method_list)
|
||||||
+ sizeof(struct
|
+ sizeof (struct
|
||||||
objc_method[max_methods_no += 16]));
|
objc_method[max_methods_no += 16]));
|
||||||
curr_method = &new_list->method_list[new_list->method_count];
|
curr_method = &new_list->method_list[new_list->method_count];
|
||||||
}
|
}
|
||||||
|
@ -143,8 +143,8 @@ void __objc_register_instance_methods_to_class(Class class)
|
||||||
if (new_list->method_count)
|
if (new_list->method_count)
|
||||||
{
|
{
|
||||||
new_list =
|
new_list =
|
||||||
objc_realloc(new_list, sizeof(struct objc_method_list)
|
objc_realloc (new_list, sizeof (struct objc_method_list)
|
||||||
+ sizeof(struct objc_method[new_list->method_count]));
|
+ sizeof (struct objc_method[new_list->method_count]));
|
||||||
new_list->method_next = class->class_pointer->methods;
|
new_list->method_next = class->class_pointer->methods;
|
||||||
class->class_pointer->methods = new_list;
|
class->class_pointer->methods = new_list;
|
||||||
}
|
}
|
||||||
|
@ -156,21 +156,21 @@ void __objc_register_instance_methods_to_class(Class class)
|
||||||
/* Returns YES iff t1 and t2 have same method types, but we ignore
|
/* Returns YES iff t1 and t2 have same method types, but we ignore
|
||||||
the argframe layout */
|
the argframe layout */
|
||||||
BOOL
|
BOOL
|
||||||
sel_types_match (const char* t1, const char* t2)
|
sel_types_match (const char *t1, const char *t2)
|
||||||
{
|
{
|
||||||
if (!t1 || !t2)
|
if (! t1 || ! t2)
|
||||||
return NO;
|
return NO;
|
||||||
while (*t1 && *t2)
|
while (*t1 && *t2)
|
||||||
{
|
{
|
||||||
if (*t1 == '+') t1++;
|
if (*t1 == '+') t1++;
|
||||||
if (*t2 == '+') t2++;
|
if (*t2 == '+') t2++;
|
||||||
while (isdigit((unsigned char)*t1)) t1++;
|
while (isdigit ((unsigned char) *t1)) t1++;
|
||||||
while (isdigit((unsigned char)*t2)) t2++;
|
while (isdigit ((unsigned char) *t2)) t2++;
|
||||||
/* xxx Remove these next two lines when qualifiers are put in
|
/* xxx Remove these next two lines when qualifiers are put in
|
||||||
all selectors, not just Protocol selectors. */
|
all selectors, not just Protocol selectors. */
|
||||||
t1 = objc_skip_type_qualifiers(t1);
|
t1 = objc_skip_type_qualifiers (t1);
|
||||||
t2 = objc_skip_type_qualifiers(t2);
|
t2 = objc_skip_type_qualifiers (t2);
|
||||||
if (!*t1 && !*t2)
|
if (! *t1 && ! *t2)
|
||||||
return YES;
|
return YES;
|
||||||
if (*t1 != *t2)
|
if (*t1 != *t2)
|
||||||
return NO;
|
return NO;
|
||||||
|
@ -187,35 +187,35 @@ sel_get_typed_uid (const char *name, const char *types)
|
||||||
struct objc_list *l;
|
struct objc_list *l;
|
||||||
sidx i;
|
sidx i;
|
||||||
|
|
||||||
objc_mutex_lock(__objc_runtime_mutex);
|
objc_mutex_lock (__objc_runtime_mutex);
|
||||||
|
|
||||||
i = (sidx) hash_value_for_key (__objc_selector_hash, name);
|
i = (sidx) hash_value_for_key (__objc_selector_hash, name);
|
||||||
if (i == 0)
|
if (i == 0)
|
||||||
{
|
{
|
||||||
objc_mutex_unlock(__objc_runtime_mutex);
|
objc_mutex_unlock (__objc_runtime_mutex);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (l = (struct objc_list*)sarray_get_safe (__objc_selector_array, i);
|
for (l = (struct objc_list *) sarray_get_safe (__objc_selector_array, i);
|
||||||
l; l = l->tail)
|
l; l = l->tail)
|
||||||
{
|
{
|
||||||
SEL s = (SEL)l->head;
|
SEL s = (SEL) l->head;
|
||||||
if (types == 0 || s->sel_types == 0)
|
if (types == 0 || s->sel_types == 0)
|
||||||
{
|
{
|
||||||
if (s->sel_types == types)
|
if (s->sel_types == types)
|
||||||
{
|
{
|
||||||
objc_mutex_unlock(__objc_runtime_mutex);
|
objc_mutex_unlock (__objc_runtime_mutex);
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (sel_types_match (s->sel_types, types))
|
else if (sel_types_match (s->sel_types, types))
|
||||||
{
|
{
|
||||||
objc_mutex_unlock(__objc_runtime_mutex);
|
objc_mutex_unlock (__objc_runtime_mutex);
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
objc_mutex_unlock(__objc_runtime_mutex);
|
objc_mutex_unlock (__objc_runtime_mutex);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -227,27 +227,27 @@ sel_get_any_typed_uid (const char *name)
|
||||||
sidx i;
|
sidx i;
|
||||||
SEL s = NULL;
|
SEL s = NULL;
|
||||||
|
|
||||||
objc_mutex_lock(__objc_runtime_mutex);
|
objc_mutex_lock (__objc_runtime_mutex);
|
||||||
|
|
||||||
i = (sidx) hash_value_for_key (__objc_selector_hash, name);
|
i = (sidx) hash_value_for_key (__objc_selector_hash, name);
|
||||||
if (i == 0)
|
if (i == 0)
|
||||||
{
|
{
|
||||||
objc_mutex_unlock(__objc_runtime_mutex);
|
objc_mutex_unlock (__objc_runtime_mutex);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (l = (struct objc_list*)sarray_get_safe (__objc_selector_array, i);
|
for (l = (struct objc_list *) sarray_get_safe (__objc_selector_array, i);
|
||||||
l; l = l->tail)
|
l; l = l->tail)
|
||||||
{
|
{
|
||||||
s = (SEL) l->head;
|
s = (SEL) l->head;
|
||||||
if (s->sel_types)
|
if (s->sel_types)
|
||||||
{
|
{
|
||||||
objc_mutex_unlock(__objc_runtime_mutex);
|
objc_mutex_unlock (__objc_runtime_mutex);
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
objc_mutex_unlock(__objc_runtime_mutex);
|
objc_mutex_unlock (__objc_runtime_mutex);
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -258,22 +258,22 @@ sel_get_any_uid (const char *name)
|
||||||
struct objc_list *l;
|
struct objc_list *l;
|
||||||
sidx i;
|
sidx i;
|
||||||
|
|
||||||
objc_mutex_lock(__objc_runtime_mutex);
|
objc_mutex_lock (__objc_runtime_mutex);
|
||||||
|
|
||||||
i = (sidx) hash_value_for_key (__objc_selector_hash, name);
|
i = (sidx) hash_value_for_key (__objc_selector_hash, name);
|
||||||
if (soffset_decode (i) == 0)
|
if (soffset_decode (i) == 0)
|
||||||
{
|
{
|
||||||
objc_mutex_unlock(__objc_runtime_mutex);
|
objc_mutex_unlock (__objc_runtime_mutex);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
l = (struct objc_list*)sarray_get_safe (__objc_selector_array, i);
|
l = (struct objc_list *) sarray_get_safe (__objc_selector_array, i);
|
||||||
objc_mutex_unlock(__objc_runtime_mutex);
|
objc_mutex_unlock (__objc_runtime_mutex);
|
||||||
|
|
||||||
if (l == 0)
|
if (l == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return (SEL)l->head;
|
return (SEL) l->head;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* return selector representing name */
|
/* return selector representing name */
|
||||||
|
@ -285,18 +285,17 @@ sel_get_uid (const char *name)
|
||||||
|
|
||||||
/* Get name of selector. If selector is unknown, the empty string ""
|
/* Get name of selector. If selector is unknown, the empty string ""
|
||||||
is returned */
|
is returned */
|
||||||
const char*
|
const char *sel_get_name (SEL selector)
|
||||||
sel_get_name (SEL selector)
|
|
||||||
{
|
{
|
||||||
const char *ret;
|
const char *ret;
|
||||||
|
|
||||||
objc_mutex_lock(__objc_runtime_mutex);
|
objc_mutex_lock (__objc_runtime_mutex);
|
||||||
if ((soffset_decode((sidx)selector->sel_id) > 0)
|
if ((soffset_decode ((sidx)selector->sel_id) > 0)
|
||||||
&& (soffset_decode((sidx)selector->sel_id) <= __objc_selector_max_index))
|
&& (soffset_decode ((sidx)selector->sel_id) <= __objc_selector_max_index))
|
||||||
ret = sarray_get_safe (__objc_selector_names, (sidx) selector->sel_id);
|
ret = sarray_get_safe (__objc_selector_names, (sidx) selector->sel_id);
|
||||||
else
|
else
|
||||||
ret = 0;
|
ret = 0;
|
||||||
objc_mutex_unlock(__objc_runtime_mutex);
|
objc_mutex_unlock (__objc_runtime_mutex);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -308,8 +307,7 @@ sel_is_mapped (SEL selector)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const char*
|
const char *sel_get_type (SEL selector)
|
||||||
sel_get_type (SEL selector)
|
|
||||||
{
|
{
|
||||||
if (selector)
|
if (selector)
|
||||||
return selector->sel_types;
|
return selector->sel_types;
|
||||||
|
@ -318,7 +316,7 @@ sel_get_type (SEL selector)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 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).
|
||||||
|
@ -331,35 +329,35 @@ SEL
|
||||||
__sel_register_typed_name (const char *name, const char *types,
|
__sel_register_typed_name (const char *name, const char *types,
|
||||||
struct objc_selector *orig, BOOL is_const)
|
struct objc_selector *orig, BOOL is_const)
|
||||||
{
|
{
|
||||||
struct objc_selector* j;
|
struct objc_selector *j;
|
||||||
sidx i;
|
sidx i;
|
||||||
struct objc_list *l;
|
struct objc_list *l;
|
||||||
|
|
||||||
i = (sidx) hash_value_for_key (__objc_selector_hash, name);
|
i = (sidx) hash_value_for_key (__objc_selector_hash, name);
|
||||||
if (soffset_decode (i) != 0)
|
if (soffset_decode (i) != 0)
|
||||||
{
|
{
|
||||||
for (l = (struct objc_list*)sarray_get_safe (__objc_selector_array, i);
|
for (l = (struct objc_list *) sarray_get_safe (__objc_selector_array, i);
|
||||||
l; l = l->tail)
|
l; l = l->tail)
|
||||||
{
|
{
|
||||||
SEL s = (SEL)l->head;
|
SEL s = (SEL) l->head;
|
||||||
if (types == 0 || s->sel_types == 0)
|
if (types == 0 || s->sel_types == 0)
|
||||||
{
|
{
|
||||||
if (s->sel_types == types)
|
if (s->sel_types == types)
|
||||||
{
|
{
|
||||||
if (orig)
|
if (orig)
|
||||||
{
|
{
|
||||||
orig->sel_id = (void*)i;
|
orig->sel_id = (void *) i;
|
||||||
return orig;
|
return orig;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (!strcmp (s->sel_types, types))
|
else if (! strcmp (s->sel_types, types))
|
||||||
{
|
{
|
||||||
if (orig)
|
if (orig)
|
||||||
{
|
{
|
||||||
orig->sel_id = (void*)i;
|
orig->sel_id = (void *) i;
|
||||||
return orig;
|
return orig;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -371,32 +369,32 @@ __sel_register_typed_name (const char *name, const char *types,
|
||||||
else
|
else
|
||||||
j = objc_malloc (sizeof (struct objc_selector));
|
j = objc_malloc (sizeof (struct objc_selector));
|
||||||
|
|
||||||
j->sel_id = (void*)i;
|
j->sel_id = (void *) i;
|
||||||
/* Can we use the pointer or must copy types? Don't copy if NULL */
|
/* Can we use the pointer or must copy types? Don't copy if NULL */
|
||||||
if ((is_const) || (types == 0))
|
if ((is_const) || (types == 0))
|
||||||
j->sel_types = (const char*)types;
|
j->sel_types = (const char *) types;
|
||||||
else {
|
else {
|
||||||
j->sel_types = (char *) objc_malloc(strlen(types)+1);
|
j->sel_types = (char *) objc_malloc (strlen (types) + 1);
|
||||||
strcpy((char *)j->sel_types, types);
|
strcpy ((char *) j->sel_types, types);
|
||||||
}
|
}
|
||||||
l = (struct objc_list*)sarray_get_safe (__objc_selector_array, i);
|
l = (struct objc_list *) sarray_get_safe (__objc_selector_array, i);
|
||||||
}
|
}
|
||||||
else
|
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)
|
if (orig)
|
||||||
j = orig;
|
j = orig;
|
||||||
else
|
else
|
||||||
j = objc_malloc (sizeof (struct objc_selector));
|
j = objc_malloc (sizeof (struct objc_selector));
|
||||||
|
|
||||||
j->sel_id = (void*)i;
|
j->sel_id = (void *) i;
|
||||||
/* Can we use the pointer or must copy types? Don't copy if NULL */
|
/* Can we use the pointer or must copy types? Don't copy if NULL */
|
||||||
if ((is_const) || (types == 0))
|
if ((is_const) || (types == 0))
|
||||||
j->sel_types = (const char*)types;
|
j->sel_types = (const char *) types;
|
||||||
else {
|
else {
|
||||||
j->sel_types = (char *) objc_malloc(strlen(types)+1);
|
j->sel_types = (char *) objc_malloc (strlen (types) + 1);
|
||||||
strcpy((char *)j->sel_types, types);
|
strcpy ((char *) j->sel_types, types);
|
||||||
}
|
}
|
||||||
l = 0;
|
l = 0;
|
||||||
}
|
}
|
||||||
|
@ -412,18 +410,18 @@ __sel_register_typed_name (const char *name, const char *types,
|
||||||
if ((is_const) || (name == 0))
|
if ((is_const) || (name == 0))
|
||||||
new_name = name;
|
new_name = name;
|
||||||
else {
|
else {
|
||||||
new_name = (char *) objc_malloc(strlen(name)+1);
|
new_name = (char *) objc_malloc (strlen (name) + 1);
|
||||||
strcpy((char *)new_name, name);
|
strcpy ((char *) new_name, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
l = list_cons ((void*)j, l);
|
l = list_cons ((void *) j, l);
|
||||||
sarray_at_put_safe (__objc_selector_names, i, (void *) new_name);
|
sarray_at_put_safe (__objc_selector_names, i, (void *) new_name);
|
||||||
sarray_at_put_safe (__objc_selector_array, i, (void *) l);
|
sarray_at_put_safe (__objc_selector_array, i, (void *) l);
|
||||||
if (is_new)
|
if (is_new)
|
||||||
hash_add (&__objc_selector_hash, (void *) new_name, (void *) i);
|
hash_add (&__objc_selector_hash, (void *) new_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) j;
|
return (SEL) j;
|
||||||
}
|
}
|
||||||
|
@ -433,11 +431,11 @@ sel_register_name (const char *name)
|
||||||
{
|
{
|
||||||
SEL ret;
|
SEL ret;
|
||||||
|
|
||||||
objc_mutex_lock(__objc_runtime_mutex);
|
objc_mutex_lock (__objc_runtime_mutex);
|
||||||
/* Assume that name is not constant static memory and needs to be
|
/* Assume that name is not constant static memory and needs to be
|
||||||
copied before put into a runtime structure. is_const == NO */
|
copied before put into a runtime structure. is_const == NO */
|
||||||
ret = __sel_register_typed_name (name, 0, 0, NO);
|
ret = __sel_register_typed_name (name, 0, 0, NO);
|
||||||
objc_mutex_unlock(__objc_runtime_mutex);
|
objc_mutex_unlock (__objc_runtime_mutex);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -447,12 +445,11 @@ sel_register_typed_name (const char *name, const char *type)
|
||||||
{
|
{
|
||||||
SEL ret;
|
SEL ret;
|
||||||
|
|
||||||
objc_mutex_lock(__objc_runtime_mutex);
|
objc_mutex_lock (__objc_runtime_mutex);
|
||||||
/* Assume that name and type are not constant static memory and need to
|
/* Assume that name and type are not constant static memory and need to
|
||||||
be copied before put into a runtime structure. is_const == NO */
|
be copied before put into a runtime structure. is_const == NO */
|
||||||
ret = __sel_register_typed_name (name, type, 0, NO);
|
ret = __sel_register_typed_name (name, type, 0, NO);
|
||||||
objc_mutex_unlock(__objc_runtime_mutex);
|
objc_mutex_unlock (__objc_runtime_mutex);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* GNU Objective C Runtime message lookup
|
/* GNU Objective C Runtime message lookup
|
||||||
Copyright (C) 1993, 1995, 1996, 1997, 1998,
|
Copyright (C) 1993, 1995, 1996, 1997, 1998,
|
||||||
2001 Free Software Foundation, Inc.
|
2001, 2002 Free Software Foundation, Inc.
|
||||||
Contributed by Kresten Krab Thorup
|
Contributed by Kresten Krab Thorup
|
||||||
|
|
||||||
This file is part of GNU CC.
|
This file is part of GNU CC.
|
||||||
|
@ -37,27 +37,27 @@ Boston, MA 02111-1307, USA. */
|
||||||
#define gen_rtx_REG(args...) 1
|
#define gen_rtx_REG(args...) 1
|
||||||
#define rtx int
|
#define rtx int
|
||||||
|
|
||||||
#if !defined(STRUCT_VALUE) || STRUCT_VALUE == 0
|
#if ! defined (STRUCT_VALUE) || STRUCT_VALUE == 0
|
||||||
#define INVISIBLE_STRUCT_RETURN 1
|
#define INVISIBLE_STRUCT_RETURN 1
|
||||||
#else
|
#else
|
||||||
#define INVISIBLE_STRUCT_RETURN 0
|
#define INVISIBLE_STRUCT_RETURN 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* The uninstalled dispatch table */
|
/* The uninstalled dispatch table */
|
||||||
struct sarray* __objc_uninstalled_dtable = 0; /* !T:MUTEX */
|
struct sarray *__objc_uninstalled_dtable = 0; /* !T:MUTEX */
|
||||||
|
|
||||||
/* Hook for method forwarding. If it is set, is invoked to return a
|
/* Hook for method forwarding. If it is set, is invoked to return a
|
||||||
function that performs the real forwarding. Otherwise the libgcc
|
function that performs the real forwarding. Otherwise the libgcc
|
||||||
based functions (__builtin_apply and friends) are used. */
|
based functions (__builtin_apply and friends) are used. */
|
||||||
IMP (*__objc_msg_forward)(SEL) = NULL;
|
IMP (*__objc_msg_forward) (SEL) = NULL;
|
||||||
|
|
||||||
/* Send +initialize to class */
|
/* Send +initialize to class */
|
||||||
static void __objc_send_initialize(Class);
|
static void __objc_send_initialize (Class);
|
||||||
|
|
||||||
static void __objc_install_dispatch_table_for_class (Class);
|
static void __objc_install_dispatch_table_for_class (Class);
|
||||||
|
|
||||||
/* Forward declare some functions */
|
/* Forward declare some functions */
|
||||||
static void __objc_init_install_dtable(id, SEL);
|
static void __objc_init_install_dtable (id, SEL);
|
||||||
|
|
||||||
/* Various forwarding functions that are used based upon the
|
/* Various forwarding functions that are used based upon the
|
||||||
return type for the selector.
|
return type for the selector.
|
||||||
|
@ -65,76 +65,76 @@ static void __objc_init_install_dtable(id, SEL);
|
||||||
__objc_double_forward for floats/doubles.
|
__objc_double_forward for floats/doubles.
|
||||||
__objc_word_forward for pointers or types that fit in registers.
|
__objc_word_forward for pointers or types that fit in registers.
|
||||||
*/
|
*/
|
||||||
static double __objc_double_forward(id, SEL, ...);
|
static double __objc_double_forward (id, SEL, ...);
|
||||||
static id __objc_word_forward(id, SEL, ...);
|
static id __objc_word_forward (id, SEL, ...);
|
||||||
typedef struct { id many[8]; } __big;
|
typedef struct { id many[8]; } __big;
|
||||||
#if INVISIBLE_STRUCT_RETURN
|
#if INVISIBLE_STRUCT_RETURN
|
||||||
static __big
|
static __big
|
||||||
#else
|
#else
|
||||||
static id
|
static id
|
||||||
#endif
|
#endif
|
||||||
__objc_block_forward(id, SEL, ...);
|
__objc_block_forward (id, SEL, ...);
|
||||||
static Method_t search_for_method_in_hierarchy (Class class, SEL sel);
|
static Method_t search_for_method_in_hierarchy (Class class, SEL sel);
|
||||||
Method_t search_for_method_in_list(MethodList_t list, SEL op);
|
Method_t search_for_method_in_list (MethodList_t list, SEL op);
|
||||||
id nil_method(id, SEL, ...);
|
id nil_method (id, SEL, ...);
|
||||||
|
|
||||||
/* Given a selector, return the proper forwarding implementation. */
|
/* Given a selector, return the proper forwarding implementation. */
|
||||||
__inline__
|
__inline__
|
||||||
IMP
|
IMP
|
||||||
__objc_get_forward_imp (SEL sel)
|
__objc_get_forward_imp (SEL sel)
|
||||||
{
|
{
|
||||||
/* If a custom forwarding hook was registered, try getting a forwarding
|
/* If a custom forwarding hook was registered, try getting a forwarding
|
||||||
* function from it. */
|
* function from it. */
|
||||||
if (__objc_msg_forward)
|
if (__objc_msg_forward)
|
||||||
{
|
{
|
||||||
IMP result;
|
IMP result;
|
||||||
if ((result = __objc_msg_forward (sel)) != NULL)
|
if ((result = __objc_msg_forward (sel)) != NULL)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* In all other cases, use the default forwarding functions built using
|
/* In all other cases, use the default forwarding functions built using
|
||||||
* __builtin_apply and friends. */
|
* __builtin_apply and friends. */
|
||||||
{
|
{
|
||||||
const char *t = sel->sel_types;
|
const char *t = sel->sel_types;
|
||||||
|
|
||||||
if (t && (*t == '[' || *t == '(' || *t == '{')
|
if (t && (*t == '[' || *t == '(' || *t == '{')
|
||||||
#ifdef OBJC_MAX_STRUCT_BY_VALUE
|
#ifdef OBJC_MAX_STRUCT_BY_VALUE
|
||||||
&& objc_sizeof_type(t) > OBJC_MAX_STRUCT_BY_VALUE
|
&& objc_sizeof_type (t) > OBJC_MAX_STRUCT_BY_VALUE
|
||||||
#endif
|
#endif
|
||||||
)
|
)
|
||||||
return (IMP)__objc_block_forward;
|
return (IMP)__objc_block_forward;
|
||||||
else if (t && (*t == 'f' || *t == 'd'))
|
else if (t && (*t == 'f' || *t == 'd'))
|
||||||
return (IMP)__objc_double_forward;
|
return (IMP)__objc_double_forward;
|
||||||
else
|
else
|
||||||
return (IMP)__objc_word_forward;
|
return (IMP)__objc_word_forward;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Given a class and selector, return the selector's implementation. */
|
/* Given a class and selector, return the selector's implementation. */
|
||||||
__inline__
|
__inline__
|
||||||
IMP
|
IMP
|
||||||
get_imp (Class class, SEL sel)
|
get_imp (Class class, SEL sel)
|
||||||
{
|
{
|
||||||
void* res = sarray_get_safe (class->dtable, (size_t) sel->sel_id);
|
void *res = sarray_get_safe (class->dtable, (size_t) sel->sel_id);
|
||||||
if (res == 0)
|
if (res == 0)
|
||||||
{
|
{
|
||||||
/* Not a valid method */
|
/* Not a valid method */
|
||||||
if(class->dtable == __objc_uninstalled_dtable)
|
if (class->dtable == __objc_uninstalled_dtable)
|
||||||
{
|
{
|
||||||
/* The dispatch table needs to be installed. */
|
/* The dispatch table needs to be installed. */
|
||||||
objc_mutex_lock(__objc_runtime_mutex);
|
objc_mutex_lock (__objc_runtime_mutex);
|
||||||
__objc_install_dispatch_table_for_class (class);
|
__objc_install_dispatch_table_for_class (class);
|
||||||
objc_mutex_unlock(__objc_runtime_mutex);
|
objc_mutex_unlock (__objc_runtime_mutex);
|
||||||
/* Call ourselves with the installed dispatch table
|
/* Call ourselves with the installed dispatch table
|
||||||
and get the real method */
|
and get the real method */
|
||||||
res = get_imp(class, sel);
|
res = get_imp (class, sel);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* The dispatch table has been installed so the
|
/* The dispatch table has been installed so the
|
||||||
method just doesn't exist for the class.
|
method just doesn't exist for the class.
|
||||||
Return the forwarding implementation. */
|
Return the forwarding implementation. */
|
||||||
res = __objc_get_forward_imp(sel);
|
res = __objc_get_forward_imp (sel);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
|
@ -147,14 +147,14 @@ __inline__
|
||||||
BOOL
|
BOOL
|
||||||
__objc_responds_to (id object, SEL sel)
|
__objc_responds_to (id object, SEL sel)
|
||||||
{
|
{
|
||||||
void* res;
|
void *res;
|
||||||
|
|
||||||
/* Install dispatch table if need be */
|
/* Install dispatch table if need be */
|
||||||
if (object->class_pointer->dtable == __objc_uninstalled_dtable)
|
if (object->class_pointer->dtable == __objc_uninstalled_dtable)
|
||||||
{
|
{
|
||||||
objc_mutex_lock(__objc_runtime_mutex);
|
objc_mutex_lock (__objc_runtime_mutex);
|
||||||
__objc_install_dispatch_table_for_class (object->class_pointer);
|
__objc_install_dispatch_table_for_class (object->class_pointer);
|
||||||
objc_mutex_unlock(__objc_runtime_mutex);
|
objc_mutex_unlock (__objc_runtime_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get the method from the dispatch table */
|
/* Get the method from the dispatch table */
|
||||||
|
@ -167,31 +167,31 @@ __objc_responds_to (id object, SEL sel)
|
||||||
needs to be installed or it doesn't exist and forwarding is attempted. */
|
needs to be installed or it doesn't exist and forwarding is attempted. */
|
||||||
__inline__
|
__inline__
|
||||||
IMP
|
IMP
|
||||||
objc_msg_lookup(id receiver, SEL op)
|
objc_msg_lookup (id receiver, SEL op)
|
||||||
{
|
{
|
||||||
IMP result;
|
IMP result;
|
||||||
if(receiver)
|
if (receiver)
|
||||||
{
|
{
|
||||||
result = sarray_get_safe (receiver->class_pointer->dtable,
|
result = sarray_get_safe (receiver->class_pointer->dtable,
|
||||||
(sidx)op->sel_id);
|
(sidx)op->sel_id);
|
||||||
if (result == 0)
|
if (result == 0)
|
||||||
{
|
{
|
||||||
/* Not a valid method */
|
/* Not a valid method */
|
||||||
if(receiver->class_pointer->dtable == __objc_uninstalled_dtable)
|
if (receiver->class_pointer->dtable == __objc_uninstalled_dtable)
|
||||||
{
|
{
|
||||||
/* The dispatch table needs to be installed.
|
/* The dispatch table needs to be installed.
|
||||||
This happens on the very first method call to the class. */
|
This happens on the very first method call to the class. */
|
||||||
__objc_init_install_dtable(receiver, op);
|
__objc_init_install_dtable (receiver, op);
|
||||||
|
|
||||||
/* Get real method for this in newly installed dtable */
|
/* Get real method for this in newly installed dtable */
|
||||||
result = get_imp(receiver->class_pointer, op);
|
result = get_imp (receiver->class_pointer, op);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* The dispatch table has been installed so the
|
/* The dispatch table has been installed so the
|
||||||
method just doesn't exist for the class.
|
method just doesn't exist for the class.
|
||||||
Attempt to forward the method. */
|
Attempt to forward the method. */
|
||||||
result = __objc_get_forward_imp(op);
|
result = __objc_get_forward_imp (op);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
|
@ -209,93 +209,92 @@ objc_msg_lookup_super (Super_t super, SEL sel)
|
||||||
return nil_method;
|
return nil_method;
|
||||||
}
|
}
|
||||||
|
|
||||||
int method_get_sizeof_arguments (Method*);
|
int method_get_sizeof_arguments (Method *);
|
||||||
|
|
||||||
retval_t
|
retval_t
|
||||||
objc_msg_sendv(id object, SEL op, arglist_t arg_frame)
|
objc_msg_sendv (id object, SEL op, arglist_t arg_frame)
|
||||||
{
|
{
|
||||||
Method* m = class_get_instance_method(object->class_pointer, op);
|
Method *m = class_get_instance_method (object->class_pointer, op);
|
||||||
const char *type;
|
const char *type;
|
||||||
*((id*)method_get_first_argument (m, arg_frame, &type)) = object;
|
*((id *) method_get_first_argument (m, arg_frame, &type)) = object;
|
||||||
*((SEL*)method_get_next_argument (arg_frame, &type)) = op;
|
*((SEL *) method_get_next_argument (arg_frame, &type)) = op;
|
||||||
return __builtin_apply((apply_t)m->method_imp,
|
return __builtin_apply ((apply_t) m->method_imp,
|
||||||
arg_frame,
|
arg_frame,
|
||||||
method_get_sizeof_arguments (m));
|
method_get_sizeof_arguments (m));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
__objc_init_dispatch_tables()
|
__objc_init_dispatch_tables ()
|
||||||
{
|
{
|
||||||
__objc_uninstalled_dtable
|
__objc_uninstalled_dtable = sarray_new (200, 0);
|
||||||
= sarray_new(200, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This function is called by objc_msg_lookup when the
|
/* This function is called by objc_msg_lookup when the
|
||||||
dispatch table needs to be installed; thus it is called once
|
dispatch table needs to be installed; thus it is called once
|
||||||
for each class, namely when the very first message is sent to it. */
|
for each class, namely when the very first message is sent to it. */
|
||||||
static void
|
static void
|
||||||
__objc_init_install_dtable(id receiver, SEL op __attribute__ ((__unused__)))
|
__objc_init_install_dtable (id receiver, SEL op __attribute__ ((__unused__)))
|
||||||
{
|
{
|
||||||
/* This may happen, if the programmer has taken the address of a
|
/* This may happen, if the programmer has taken the address of a
|
||||||
method before the dtable was initialized... too bad for him! */
|
method before the dtable was initialized... too bad for him! */
|
||||||
if(receiver->class_pointer->dtable != __objc_uninstalled_dtable)
|
if (receiver->class_pointer->dtable != __objc_uninstalled_dtable)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
objc_mutex_lock(__objc_runtime_mutex);
|
objc_mutex_lock (__objc_runtime_mutex);
|
||||||
|
|
||||||
if(CLS_ISCLASS(receiver->class_pointer))
|
if (CLS_ISCLASS (receiver->class_pointer))
|
||||||
{
|
{
|
||||||
/* receiver is an ordinary object */
|
/* receiver is an ordinary object */
|
||||||
assert(CLS_ISCLASS(receiver->class_pointer));
|
assert (CLS_ISCLASS (receiver->class_pointer));
|
||||||
|
|
||||||
/* install instance methods table */
|
/* install instance methods table */
|
||||||
__objc_install_dispatch_table_for_class (receiver->class_pointer);
|
__objc_install_dispatch_table_for_class (receiver->class_pointer);
|
||||||
|
|
||||||
/* call +initialize -- this will in turn install the factory
|
/* call +initialize -- this will in turn install the factory
|
||||||
dispatch table if not already done :-) */
|
dispatch table if not already done :-) */
|
||||||
__objc_send_initialize(receiver->class_pointer);
|
__objc_send_initialize (receiver->class_pointer);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* receiver is a class object */
|
/* receiver is a class object */
|
||||||
assert(CLS_ISCLASS((Class)receiver));
|
assert (CLS_ISCLASS ((Class)receiver));
|
||||||
assert(CLS_ISMETA(receiver->class_pointer));
|
assert (CLS_ISMETA (receiver->class_pointer));
|
||||||
|
|
||||||
/* Install real dtable for factory methods */
|
/* Install real dtable for factory methods */
|
||||||
__objc_install_dispatch_table_for_class (receiver->class_pointer);
|
__objc_install_dispatch_table_for_class (receiver->class_pointer);
|
||||||
|
|
||||||
__objc_send_initialize((Class)receiver);
|
__objc_send_initialize ((Class)receiver);
|
||||||
}
|
}
|
||||||
objc_mutex_unlock(__objc_runtime_mutex);
|
objc_mutex_unlock (__objc_runtime_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Install dummy table for class which causes the first message to
|
/* Install dummy table for class which causes the first message to
|
||||||
that class (or instances hereof) to be initialized properly */
|
that class (or instances hereof) to be initialized properly */
|
||||||
void
|
void
|
||||||
__objc_install_premature_dtable(Class class)
|
__objc_install_premature_dtable (Class class)
|
||||||
{
|
{
|
||||||
assert(__objc_uninstalled_dtable);
|
assert (__objc_uninstalled_dtable);
|
||||||
class->dtable = __objc_uninstalled_dtable;
|
class->dtable = __objc_uninstalled_dtable;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Send +initialize to class if not already done */
|
/* Send +initialize to class if not already done */
|
||||||
static void
|
static void
|
||||||
__objc_send_initialize(Class class)
|
__objc_send_initialize (Class class)
|
||||||
{
|
{
|
||||||
/* This *must* be a class object */
|
/* This *must* be a class object */
|
||||||
assert(CLS_ISCLASS(class));
|
assert (CLS_ISCLASS (class));
|
||||||
assert(!CLS_ISMETA(class));
|
assert (! CLS_ISMETA (class));
|
||||||
|
|
||||||
if (!CLS_ISINITIALIZED(class))
|
if (! CLS_ISINITIALIZED (class))
|
||||||
{
|
{
|
||||||
CLS_SETINITIALIZED(class);
|
CLS_SETINITIALIZED (class);
|
||||||
CLS_SETINITIALIZED(class->class_pointer);
|
CLS_SETINITIALIZED (class->class_pointer);
|
||||||
|
|
||||||
/* Create the garbage collector type memory description */
|
/* Create the garbage collector type memory description */
|
||||||
__objc_generate_gc_type_description (class);
|
__objc_generate_gc_type_description (class);
|
||||||
|
|
||||||
if(class->super_class)
|
if (class->super_class)
|
||||||
__objc_send_initialize(class->super_class);
|
__objc_send_initialize (class->super_class);
|
||||||
|
|
||||||
{
|
{
|
||||||
SEL op = sel_register_name ("initialize");
|
SEL op = sel_register_name ("initialize");
|
||||||
|
@ -306,7 +305,7 @@ __objc_send_initialize(Class class)
|
||||||
int i;
|
int i;
|
||||||
Method_t method;
|
Method_t method;
|
||||||
|
|
||||||
for (i = 0; i< method_list->method_count; i++) {
|
for (i = 0; i < method_list->method_count; i++) {
|
||||||
method = &(method_list->method_list[i]);
|
method = &(method_list->method_list[i]);
|
||||||
if (method->method_name
|
if (method->method_name
|
||||||
&& method->method_name->sel_id == op->sel_id) {
|
&& method->method_name->sel_id == op->sel_id) {
|
||||||
|
@ -322,7 +321,7 @@ __objc_send_initialize(Class class)
|
||||||
|
|
||||||
}
|
}
|
||||||
if (imp)
|
if (imp)
|
||||||
(*imp)((id)class, op);
|
(*imp) ((id) class, op);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -339,7 +338,7 @@ __objc_install_methods_in_dtable (Class class, MethodList_t method_list)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (!method_list)
|
if (! method_list)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (method_list->method_next)
|
if (method_list->method_next)
|
||||||
|
@ -362,8 +361,8 @@ __objc_install_dispatch_table_for_class (Class class)
|
||||||
|
|
||||||
/* If the class has not yet had its class links resolved, we must
|
/* If the class has not yet had its class links resolved, we must
|
||||||
re-compute all class links */
|
re-compute all class links */
|
||||||
if(!CLS_ISRESOLV(class))
|
if (! CLS_ISRESOLV (class))
|
||||||
__objc_resolve_class_links();
|
__objc_resolve_class_links ();
|
||||||
|
|
||||||
super = class->super_class;
|
super = class->super_class;
|
||||||
|
|
||||||
|
@ -373,9 +372,9 @@ __objc_install_dispatch_table_for_class (Class class)
|
||||||
/* Allocate dtable if necessary */
|
/* Allocate dtable if necessary */
|
||||||
if (super == 0)
|
if (super == 0)
|
||||||
{
|
{
|
||||||
objc_mutex_lock(__objc_runtime_mutex);
|
objc_mutex_lock (__objc_runtime_mutex);
|
||||||
class->dtable = sarray_new (__objc_selector_max_index, 0);
|
class->dtable = sarray_new (__objc_selector_max_index, 0);
|
||||||
objc_mutex_unlock(__objc_runtime_mutex);
|
objc_mutex_unlock (__objc_runtime_mutex);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
class->dtable = sarray_lazy_copy (super->dtable);
|
class->dtable = sarray_lazy_copy (super->dtable);
|
||||||
|
@ -393,7 +392,7 @@ __objc_update_dispatch_table_for_class (Class class)
|
||||||
if (class->dtable == __objc_uninstalled_dtable)
|
if (class->dtable == __objc_uninstalled_dtable)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
objc_mutex_lock(__objc_runtime_mutex);
|
objc_mutex_lock (__objc_runtime_mutex);
|
||||||
|
|
||||||
arr = class->dtable;
|
arr = class->dtable;
|
||||||
__objc_install_premature_dtable (class); /* someone might require it... */
|
__objc_install_premature_dtable (class); /* someone might require it... */
|
||||||
|
@ -406,7 +405,7 @@ __objc_update_dispatch_table_for_class (Class class)
|
||||||
for (next = class->subclass_list; next; next = next->sibling_class)
|
for (next = class->subclass_list; next; next = next->sibling_class)
|
||||||
__objc_update_dispatch_table_for_class (next);
|
__objc_update_dispatch_table_for_class (next);
|
||||||
|
|
||||||
objc_mutex_unlock(__objc_runtime_mutex);
|
objc_mutex_unlock (__objc_runtime_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -423,7 +422,7 @@ class_add_method_list (Class class, MethodList_t list)
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
/* Passing of a linked list is not allowed. Do multiple calls. */
|
/* Passing of a linked list is not allowed. Do multiple calls. */
|
||||||
assert (!list->method_next);
|
assert (! list->method_next);
|
||||||
|
|
||||||
/* Check for duplicates. */
|
/* Check for duplicates. */
|
||||||
for (i = 0; i < list->method_count; ++i)
|
for (i = 0; i < list->method_count; ++i)
|
||||||
|
@ -434,7 +433,7 @@ class_add_method_list (Class class, MethodList_t list)
|
||||||
{
|
{
|
||||||
/* This is where selector names are transmogrified to SEL's */
|
/* This is where selector names are transmogrified to SEL's */
|
||||||
method->method_name =
|
method->method_name =
|
||||||
sel_register_typed_name ((const char*)method->method_name,
|
sel_register_typed_name ((const char *) method->method_name,
|
||||||
method->method_types);
|
method->method_types);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -448,15 +447,15 @@ class_add_method_list (Class class, MethodList_t list)
|
||||||
}
|
}
|
||||||
|
|
||||||
Method_t
|
Method_t
|
||||||
class_get_instance_method(Class class, SEL op)
|
class_get_instance_method (Class class, SEL op)
|
||||||
{
|
{
|
||||||
return search_for_method_in_hierarchy(class, op);
|
return search_for_method_in_hierarchy (class, op);
|
||||||
}
|
}
|
||||||
|
|
||||||
Method_t
|
Method_t
|
||||||
class_get_class_method(MetaClass class, SEL op)
|
class_get_class_method (MetaClass class, SEL op)
|
||||||
{
|
{
|
||||||
return search_for_method_in_hierarchy(class, op);
|
return search_for_method_in_hierarchy (class, op);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -580,13 +579,13 @@ __objc_forward (id object, SEL sel, arglist_t args)
|
||||||
SEL err_sel;
|
SEL err_sel;
|
||||||
|
|
||||||
/* first try if the object understands forward:: */
|
/* first try if the object understands forward:: */
|
||||||
if (!frwd_sel)
|
if (! frwd_sel)
|
||||||
frwd_sel = sel_get_any_uid("forward::");
|
frwd_sel = sel_get_any_uid ("forward::");
|
||||||
|
|
||||||
if (__objc_responds_to (object, frwd_sel))
|
if (__objc_responds_to (object, frwd_sel))
|
||||||
{
|
{
|
||||||
imp = get_imp(object->class_pointer, frwd_sel);
|
imp = get_imp (object->class_pointer, frwd_sel);
|
||||||
return (*imp)(object, frwd_sel, sel, args);
|
return (*imp) (object, frwd_sel, sel, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If the object recognizes the doesNotRecognize: method then we're going
|
/* If the object recognizes the doesNotRecognize: method then we're going
|
||||||
|
@ -601,11 +600,11 @@ __objc_forward (id object, SEL sel, arglist_t args)
|
||||||
/* The object doesn't recognize the method. Check for responding to
|
/* The object doesn't recognize the method. Check for responding to
|
||||||
error:. If it does then sent it. */
|
error:. If it does then sent it. */
|
||||||
{
|
{
|
||||||
char msg[256 + strlen ((const char*)sel_get_name (sel))
|
char msg[256 + strlen ((const char *) sel_get_name (sel))
|
||||||
+ strlen ((const char*)object->class_pointer->name)];
|
+ strlen ((const char *) object->class_pointer->name)];
|
||||||
|
|
||||||
sprintf (msg, "(%s) %s does not recognize %s",
|
sprintf (msg, "(%s) %s does not recognize %s",
|
||||||
(CLS_ISMETA(object->class_pointer)
|
(CLS_ISMETA (object->class_pointer)
|
||||||
? "class"
|
? "class"
|
||||||
: "instance" ),
|
: "instance" ),
|
||||||
object->class_pointer->name, sel_get_name (sel));
|
object->class_pointer->name, sel_get_name (sel));
|
||||||
|
@ -626,40 +625,41 @@ __objc_forward (id object, SEL sel, arglist_t args)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
__objc_print_dtable_stats()
|
__objc_print_dtable_stats ()
|
||||||
{
|
{
|
||||||
int total = 0;
|
int total = 0;
|
||||||
|
|
||||||
objc_mutex_lock(__objc_runtime_mutex);
|
objc_mutex_lock (__objc_runtime_mutex);
|
||||||
|
|
||||||
#ifdef OBJC_SPARSE2
|
#ifdef OBJC_SPARSE2
|
||||||
printf("memory usage: (%s)\n", "2-level sparse arrays");
|
printf ("memory usage: (%s)\n", "2-level sparse arrays");
|
||||||
#else
|
#else
|
||||||
printf("memory usage: (%s)\n", "3-level sparse arrays");
|
printf ("memory usage: (%s)\n", "3-level sparse arrays");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
printf("arrays: %d = %ld bytes\n", narrays,
|
printf ("arrays: %d = %ld bytes\n", narrays,
|
||||||
(long)narrays*sizeof(struct sarray));
|
(long) narrays * sizeof (struct sarray));
|
||||||
total += narrays*sizeof(struct sarray);
|
total += narrays * sizeof (struct sarray);
|
||||||
printf("buckets: %d = %ld bytes\n", nbuckets,
|
printf ("buckets: %d = %ld bytes\n", nbuckets,
|
||||||
(long)nbuckets*sizeof(struct sbucket));
|
(long) nbuckets * sizeof (struct sbucket));
|
||||||
total += nbuckets*sizeof(struct sbucket);
|
total += nbuckets * sizeof (struct sbucket);
|
||||||
|
|
||||||
printf("idxtables: %d = %ld bytes\n", idxsize, (long)idxsize*sizeof(void*));
|
printf ("idxtables: %d = %ld bytes\n",
|
||||||
total += idxsize*sizeof(void*);
|
idxsize, (long) idxsize * sizeof (void *));
|
||||||
printf("-----------------------------------\n");
|
total += idxsize * sizeof (void *);
|
||||||
printf("total: %d bytes\n", total);
|
printf ("-----------------------------------\n");
|
||||||
printf("===================================\n");
|
printf ("total: %d bytes\n", total);
|
||||||
|
printf ("===================================\n");
|
||||||
|
|
||||||
objc_mutex_unlock(__objc_runtime_mutex);
|
objc_mutex_unlock (__objc_runtime_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Returns the uninstalled dispatch table indicator.
|
/* Returns the uninstalled dispatch table indicator.
|
||||||
If a class' dispatch table points to __objc_uninstalled_dtable
|
If a class' dispatch table points to __objc_uninstalled_dtable
|
||||||
then that means it needs its dispatch table to be installed. */
|
then that means it needs its dispatch table to be installed. */
|
||||||
__inline__
|
__inline__
|
||||||
struct sarray*
|
struct sarray *
|
||||||
objc_get_uninstalled_dtable()
|
objc_get_uninstalled_dtable ()
|
||||||
{
|
{
|
||||||
return __objc_uninstalled_dtable;
|
return __objc_uninstalled_dtable;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/* GNU Objective C Runtime Thread Implementation
|
/* GNU Objective C Runtime Thread Implementation
|
||||||
Copyright (C) 1996, 1997 Free Software Foundation, Inc.
|
Copyright (C) 1996, 1997, 2002 Free Software Foundation, Inc.
|
||||||
Contributed by Galen C. Hunt (gchunt@cs.rochester.edu)
|
Contributed by Galen C. Hunt (gchunt@cs.rochester.edu)
|
||||||
Modified for Mach threads by Bill Bumgarner <bbum@friday.com>
|
Modified for Mach threads by Bill Bumgarner <bbum@friday.com>
|
||||||
Condition functions added by Mircea Oancea <mircea@first.elcom.pub.ro>
|
Condition functions added by Mircea Oancea <mircea@first.elcom.pub.ro>
|
||||||
|
@ -37,7 +37,8 @@ Boston, MA 02111-1307, USA. */
|
||||||
maximum priority downward only-- cannot be raised without superuser
|
maximum priority downward only-- cannot be raised without superuser
|
||||||
privileges. Once lowered, it cannot be raised.
|
privileges. Once lowered, it cannot be raised.
|
||||||
*/
|
*/
|
||||||
static int __mach_get_max_thread_priority(cthread_t t, int *base)
|
static int
|
||||||
|
__mach_get_max_thread_priority (cthread_t t, int *base)
|
||||||
{
|
{
|
||||||
thread_t threadP;
|
thread_t threadP;
|
||||||
kern_return_t error;
|
kern_return_t error;
|
||||||
|
@ -47,10 +48,10 @@ static int __mach_get_max_thread_priority(cthread_t t, int *base)
|
||||||
if (t == NULL)
|
if (t == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
threadP = cthread_thread(t); /* get thread underlying */
|
threadP = cthread_thread (t); /* get thread underlying */
|
||||||
|
|
||||||
error=thread_info(threadP, THREAD_SCHED_INFO,
|
error = thread_info (threadP, THREAD_SCHED_INFO,
|
||||||
(thread_info_t)&info, &info_count);
|
(thread_info_t) &info, &info_count);
|
||||||
|
|
||||||
if (error != KERN_SUCCESS)
|
if (error != KERN_SUCCESS)
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -65,14 +66,14 @@ static int __mach_get_max_thread_priority(cthread_t t, int *base)
|
||||||
|
|
||||||
/* Initialize the threads subsystem. */
|
/* Initialize the threads subsystem. */
|
||||||
int
|
int
|
||||||
__objc_init_thread_system(void)
|
__objc_init_thread_system (void)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Close the threads subsystem. */
|
/* Close the threads subsystem. */
|
||||||
int
|
int
|
||||||
__objc_close_thread_system(void)
|
__objc_close_thread_system (void)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -81,19 +82,19 @@ __objc_close_thread_system(void)
|
||||||
|
|
||||||
/* Create a new thread of execution. */
|
/* Create a new thread of execution. */
|
||||||
objc_thread_t
|
objc_thread_t
|
||||||
__objc_thread_detach(void (*func)(void *arg), void *arg)
|
__objc_thread_detach (void (*func) (void *arg), void *arg)
|
||||||
{
|
{
|
||||||
objc_thread_t thread_id;
|
objc_thread_t thread_id;
|
||||||
cthread_t new_thread_handle;
|
cthread_t new_thread_handle;
|
||||||
|
|
||||||
/* create thread */
|
/* create thread */
|
||||||
new_thread_handle = cthread_fork((cthread_fn_t)func, arg);
|
new_thread_handle = cthread_fork ((cthread_fn_t) func, arg);
|
||||||
|
|
||||||
if(new_thread_handle)
|
if (new_thread_handle)
|
||||||
{
|
{
|
||||||
/* this is not terribly portable */
|
/* this is not terribly portable */
|
||||||
thread_id = *(objc_thread_t *)&new_thread_handle;
|
thread_id = *(objc_thread_t *) &new_thread_handle;
|
||||||
cthread_detach(new_thread_handle);
|
cthread_detach (new_thread_handle);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
thread_id = NULL;
|
thread_id = NULL;
|
||||||
|
@ -103,11 +104,11 @@ __objc_thread_detach(void (*func)(void *arg), void *arg)
|
||||||
|
|
||||||
/* Set the current thread's priority. */
|
/* Set the current thread's priority. */
|
||||||
int
|
int
|
||||||
__objc_thread_set_priority(int priority)
|
__objc_thread_set_priority (int priority)
|
||||||
{
|
{
|
||||||
objc_thread_t *t = objc_thread_id();
|
objc_thread_t *t = objc_thread_id ();
|
||||||
cthread_t cT = (cthread_t) t;
|
cthread_t cT = (cthread_t) t;
|
||||||
int maxPriority = __mach_get_max_thread_priority(cT, NULL);
|
int maxPriority = __mach_get_max_thread_priority (cT, NULL);
|
||||||
int sys_priority = 0;
|
int sys_priority = 0;
|
||||||
|
|
||||||
if (maxPriority == -1)
|
if (maxPriority == -1)
|
||||||
|
@ -132,7 +133,7 @@ __objc_thread_set_priority(int priority)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
/* Change the priority */
|
/* Change the priority */
|
||||||
if (cthread_priority(cT, sys_priority, 0) == KERN_SUCCESS)
|
if (cthread_priority (cT, sys_priority, 0) == KERN_SUCCESS)
|
||||||
return 0;
|
return 0;
|
||||||
else
|
else
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -140,19 +141,19 @@ __objc_thread_set_priority(int priority)
|
||||||
|
|
||||||
/* Return the current thread's priority. */
|
/* Return the current thread's priority. */
|
||||||
int
|
int
|
||||||
__objc_thread_get_priority(void)
|
__objc_thread_get_priority (void)
|
||||||
{
|
{
|
||||||
objc_thread_t *t = objc_thread_id();
|
objc_thread_t *t = objc_thread_id ();
|
||||||
cthread_t cT = (cthread_t) t; /* see objc_thread_id() */
|
cthread_t cT = (cthread_t) t; /* see objc_thread_id () */
|
||||||
int basePriority;
|
int basePriority;
|
||||||
int maxPriority;
|
int maxPriority;
|
||||||
int sys_priority = 0;
|
int sys_priority = 0;
|
||||||
|
|
||||||
int interactiveT, backgroundT, lowT; /* thresholds */
|
int interactiveT, backgroundT, lowT; /* thresholds */
|
||||||
|
|
||||||
maxPriority = __mach_get_max_thread_priority(cT, &basePriority);
|
maxPriority = __mach_get_max_thread_priority (cT, &basePriority);
|
||||||
|
|
||||||
if(maxPriority == -1)
|
if (maxPriority == -1)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (basePriority > ( (maxPriority * 2) / 3))
|
if (basePriority > ( (maxPriority * 2) / 3))
|
||||||
|
@ -166,17 +167,17 @@ __objc_thread_get_priority(void)
|
||||||
|
|
||||||
/* Yield our process time to another thread. */
|
/* Yield our process time to another thread. */
|
||||||
void
|
void
|
||||||
__objc_thread_yield(void)
|
__objc_thread_yield (void)
|
||||||
{
|
{
|
||||||
cthread_yield();
|
cthread_yield ();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Terminate the current thread. */
|
/* Terminate the current thread. */
|
||||||
int
|
int
|
||||||
__objc_thread_exit(void)
|
__objc_thread_exit (void)
|
||||||
{
|
{
|
||||||
/* exit the thread */
|
/* exit the thread */
|
||||||
cthread_exit(&__objc_thread_exit_status);
|
cthread_exit (&__objc_thread_exit_status);
|
||||||
|
|
||||||
/* Failed if we reached here */
|
/* Failed if we reached here */
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -184,42 +185,42 @@ __objc_thread_exit(void)
|
||||||
|
|
||||||
/* Returns an integer value which uniquely describes a thread. */
|
/* Returns an integer value which uniquely describes a thread. */
|
||||||
objc_thread_t
|
objc_thread_t
|
||||||
__objc_thread_id(void)
|
__objc_thread_id (void)
|
||||||
{
|
{
|
||||||
cthread_t self = cthread_self();
|
cthread_t self = cthread_self ();
|
||||||
|
|
||||||
return *(objc_thread_t *)&self;
|
return *(objc_thread_t *) &self;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Sets the thread's local storage pointer. */
|
/* Sets the thread's local storage pointer. */
|
||||||
int
|
int
|
||||||
__objc_thread_set_data(void *value)
|
__objc_thread_set_data (void *value)
|
||||||
{
|
{
|
||||||
cthread_set_data(cthread_self(), (any_t) value);
|
cthread_set_data (cthread_self (), (any_t) value);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Returns the thread's local storage pointer. */
|
/* Returns the thread's local storage pointer. */
|
||||||
void *
|
void *
|
||||||
__objc_thread_get_data(void)
|
__objc_thread_get_data (void)
|
||||||
{
|
{
|
||||||
return (void *) cthread_data(cthread_self());
|
return (void *) cthread_data (cthread_self ());
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Backend mutex functions */
|
/* Backend mutex functions */
|
||||||
|
|
||||||
/* Allocate a mutex. */
|
/* Allocate a mutex. */
|
||||||
int
|
int
|
||||||
__objc_mutex_allocate(objc_mutex_t mutex)
|
__objc_mutex_allocate (objc_mutex_t mutex)
|
||||||
{
|
{
|
||||||
int err = 0;
|
int err = 0;
|
||||||
mutex->backend = objc_malloc(sizeof(struct mutex));
|
mutex->backend = objc_malloc (sizeof (struct mutex));
|
||||||
|
|
||||||
err = mutex_init((mutex_t)(mutex->backend));
|
err = mutex_init ((mutex_t) (mutex->backend));
|
||||||
|
|
||||||
if (err != 0)
|
if (err != 0)
|
||||||
{
|
{
|
||||||
objc_free(mutex->backend);
|
objc_free (mutex->backend);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -228,28 +229,28 @@ __objc_mutex_allocate(objc_mutex_t mutex)
|
||||||
|
|
||||||
/* Deallocate a mutex. */
|
/* Deallocate a mutex. */
|
||||||
int
|
int
|
||||||
__objc_mutex_deallocate(objc_mutex_t mutex)
|
__objc_mutex_deallocate (objc_mutex_t mutex)
|
||||||
{
|
{
|
||||||
mutex_clear((mutex_t)(mutex->backend));
|
mutex_clear ((mutex_t) (mutex->backend));
|
||||||
|
|
||||||
objc_free(mutex->backend);
|
objc_free (mutex->backend);
|
||||||
mutex->backend = NULL;
|
mutex->backend = NULL;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Grab a lock on a mutex. */
|
/* Grab a lock on a mutex. */
|
||||||
int
|
int
|
||||||
__objc_mutex_lock(objc_mutex_t mutex)
|
__objc_mutex_lock (objc_mutex_t mutex)
|
||||||
{
|
{
|
||||||
mutex_lock((mutex_t)(mutex->backend));
|
mutex_lock ((mutex_t) (mutex->backend));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Try to grab a lock on a mutex. */
|
/* Try to grab a lock on a mutex. */
|
||||||
int
|
int
|
||||||
__objc_mutex_trylock(objc_mutex_t mutex)
|
__objc_mutex_trylock (objc_mutex_t mutex)
|
||||||
{
|
{
|
||||||
if (mutex_try_lock((mutex_t)(mutex->backend)) == 0)
|
if (mutex_try_lock ((mutex_t) (mutex->backend)) == 0)
|
||||||
return -1;
|
return -1;
|
||||||
else
|
else
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -257,9 +258,9 @@ __objc_mutex_trylock(objc_mutex_t mutex)
|
||||||
|
|
||||||
/* Unlock the mutex */
|
/* Unlock the mutex */
|
||||||
int
|
int
|
||||||
__objc_mutex_unlock(objc_mutex_t mutex)
|
__objc_mutex_unlock (objc_mutex_t mutex)
|
||||||
{
|
{
|
||||||
mutex_unlock((mutex_t)(mutex->backend));
|
mutex_unlock ((mutex_t) (mutex->backend));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -267,45 +268,45 @@ __objc_mutex_unlock(objc_mutex_t mutex)
|
||||||
|
|
||||||
/* Allocate a condition. */
|
/* Allocate a condition. */
|
||||||
int
|
int
|
||||||
__objc_condition_allocate(objc_condition_t condition)
|
__objc_condition_allocate (objc_condition_t condition)
|
||||||
{
|
{
|
||||||
condition->backend = objc_malloc(sizeof(struct condition));
|
condition->backend = objc_malloc (sizeof (struct condition));
|
||||||
condition_init((condition_t)(condition->backend));
|
condition_init ((condition_t) (condition->backend));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Deallocate a condition. */
|
/* Deallocate a condition. */
|
||||||
int
|
int
|
||||||
__objc_condition_deallocate(objc_condition_t condition)
|
__objc_condition_deallocate (objc_condition_t condition)
|
||||||
{
|
{
|
||||||
condition_clear((condition_t)(condition->backend));
|
condition_clear ((condition_t) (condition->backend));
|
||||||
objc_free(condition->backend);
|
objc_free (condition->backend);
|
||||||
condition->backend = NULL;
|
condition->backend = NULL;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Wait on the condition */
|
/* Wait on the condition */
|
||||||
int
|
int
|
||||||
__objc_condition_wait(objc_condition_t condition, objc_mutex_t mutex)
|
__objc_condition_wait (objc_condition_t condition, objc_mutex_t mutex)
|
||||||
{
|
{
|
||||||
condition_wait((condition_t)(condition->backend),
|
condition_wait ((condition_t) (condition->backend),
|
||||||
(mutex_t)(mutex->backend));
|
(mutex_t) (mutex->backend));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Wake up all threads waiting on this condition. */
|
/* Wake up all threads waiting on this condition. */
|
||||||
int
|
int
|
||||||
__objc_condition_broadcast(objc_condition_t condition)
|
__objc_condition_broadcast (objc_condition_t condition)
|
||||||
{
|
{
|
||||||
condition_broadcast((condition_t)(condition->backend));
|
condition_broadcast ((condition_t) (condition->backend));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Wake up one thread waiting on this condition. */
|
/* Wake up one thread waiting on this condition. */
|
||||||
int
|
int
|
||||||
__objc_condition_signal(objc_condition_t condition)
|
__objc_condition_signal (objc_condition_t condition)
|
||||||
{
|
{
|
||||||
condition_signal((condition_t)(condition->backend));
|
condition_signal ((condition_t) (condition->backend));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
178
libobjc/thr.c
178
libobjc/thr.c
|
@ -48,7 +48,7 @@ objc_thread_callback _objc_became_multi_threaded = NULL;
|
||||||
it can be informed; for example, the GNUstep Base Library sets it
|
it can be informed; for example, the GNUstep Base Library sets it
|
||||||
so it can implement the NSBecomingMultiThreaded notification.
|
so it can implement the NSBecomingMultiThreaded notification.
|
||||||
*/
|
*/
|
||||||
objc_thread_callback objc_set_thread_callback(objc_thread_callback func)
|
objc_thread_callback objc_set_thread_callback (objc_thread_callback func)
|
||||||
{
|
{
|
||||||
objc_thread_callback temp = _objc_became_multi_threaded;
|
objc_thread_callback temp = _objc_became_multi_threaded;
|
||||||
_objc_became_multi_threaded = func;
|
_objc_became_multi_threaded = func;
|
||||||
|
@ -76,44 +76,44 @@ struct __objc_thread_start_state
|
||||||
};
|
};
|
||||||
|
|
||||||
static volatile void
|
static volatile void
|
||||||
__objc_thread_detach_function(struct __objc_thread_start_state *istate)
|
__objc_thread_detach_function (struct __objc_thread_start_state *istate)
|
||||||
{
|
{
|
||||||
/* Valid state? */
|
/* Valid state? */
|
||||||
if (istate) {
|
if (istate) {
|
||||||
id (*imp)(id,SEL,id);
|
id (*imp) (id, SEL, id);
|
||||||
SEL selector = istate->selector;
|
SEL selector = istate->selector;
|
||||||
id object = istate->object;
|
id object = istate->object;
|
||||||
id argument = istate->argument;
|
id argument = istate->argument;
|
||||||
|
|
||||||
/* Don't need anymore so free it */
|
/* Don't need anymore so free it */
|
||||||
objc_free(istate);
|
objc_free (istate);
|
||||||
|
|
||||||
/* Clear out the thread local storage */
|
/* Clear out the thread local storage */
|
||||||
objc_thread_set_data(NULL);
|
objc_thread_set_data (NULL);
|
||||||
|
|
||||||
/* Check to see if we just became multi threaded */
|
/* Check to see if we just became multi threaded */
|
||||||
if (!__objc_is_multi_threaded)
|
if (! __objc_is_multi_threaded)
|
||||||
{
|
{
|
||||||
__objc_is_multi_threaded = 1;
|
__objc_is_multi_threaded = 1;
|
||||||
|
|
||||||
/* Call the hook function */
|
/* Call the hook function */
|
||||||
if (_objc_became_multi_threaded != NULL)
|
if (_objc_became_multi_threaded != NULL)
|
||||||
(*_objc_became_multi_threaded)();
|
(*_objc_became_multi_threaded) ();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Call the method */
|
/* Call the method */
|
||||||
if ((imp = (id(*)(id, SEL, id))objc_msg_lookup(object, selector)))
|
if ((imp = (id (*) (id, SEL, id))objc_msg_lookup (object, selector)))
|
||||||
(*imp)(object, selector, argument);
|
(*imp) (object, selector, argument);
|
||||||
else
|
else
|
||||||
objc_error(object, OBJC_ERR_UNIMPLEMENTED,
|
objc_error (object, OBJC_ERR_UNIMPLEMENTED,
|
||||||
"objc_thread_detach called with bad selector.\n");
|
"objc_thread_detach called with bad selector.\n");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
objc_error(nil, OBJC_ERR_BAD_STATE,
|
objc_error (nil, OBJC_ERR_BAD_STATE,
|
||||||
"objc_thread_detach called with NULL state.\n");
|
"objc_thread_detach called with NULL state.\n");
|
||||||
|
|
||||||
/* Exit the thread */
|
/* Exit the thread */
|
||||||
objc_thread_exit();
|
objc_thread_exit ();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -131,14 +131,14 @@ __objc_thread_detach_function(struct __objc_thread_start_state *istate)
|
||||||
takes a single argument.
|
takes a single argument.
|
||||||
*/
|
*/
|
||||||
objc_thread_t
|
objc_thread_t
|
||||||
objc_thread_detach(SEL selector, id object, id argument)
|
objc_thread_detach (SEL selector, id object, id argument)
|
||||||
{
|
{
|
||||||
struct __objc_thread_start_state *istate;
|
struct __objc_thread_start_state *istate;
|
||||||
objc_thread_t thread_id = NULL;
|
objc_thread_t thread_id = NULL;
|
||||||
|
|
||||||
/* Allocate the state structure */
|
/* Allocate the state structure */
|
||||||
if (!(istate = (struct __objc_thread_start_state *)
|
if (! (istate = (struct __objc_thread_start_state *)
|
||||||
objc_malloc(sizeof(*istate))))
|
objc_malloc (sizeof (*istate))))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
/* Initialize the state structure */
|
/* Initialize the state structure */
|
||||||
|
@ -147,39 +147,39 @@ objc_thread_detach(SEL selector, id object, id argument)
|
||||||
istate->argument = argument;
|
istate->argument = argument;
|
||||||
|
|
||||||
/* lock access */
|
/* lock access */
|
||||||
objc_mutex_lock(__objc_runtime_mutex);
|
objc_mutex_lock (__objc_runtime_mutex);
|
||||||
|
|
||||||
/* Call the backend to spawn the thread */
|
/* Call the backend to spawn the thread */
|
||||||
if ((thread_id = __objc_thread_detach((void *)__objc_thread_detach_function,
|
if ((thread_id = __objc_thread_detach ((void *)__objc_thread_detach_function,
|
||||||
istate)) == NULL)
|
istate)) == NULL)
|
||||||
{
|
{
|
||||||
/* failed! */
|
/* failed! */
|
||||||
objc_mutex_unlock(__objc_runtime_mutex);
|
objc_mutex_unlock (__objc_runtime_mutex);
|
||||||
objc_free(istate);
|
objc_free (istate);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Increment our thread counter */
|
/* Increment our thread counter */
|
||||||
__objc_runtime_threads_alive++;
|
__objc_runtime_threads_alive++;
|
||||||
objc_mutex_unlock(__objc_runtime_mutex);
|
objc_mutex_unlock (__objc_runtime_mutex);
|
||||||
|
|
||||||
return thread_id;
|
return thread_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set the current thread's priority. */
|
/* Set the current thread's priority. */
|
||||||
int
|
int
|
||||||
objc_thread_set_priority(int priority)
|
objc_thread_set_priority (int priority)
|
||||||
{
|
{
|
||||||
/* Call the backend */
|
/* Call the backend */
|
||||||
return __objc_thread_set_priority(priority);
|
return __objc_thread_set_priority (priority);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return the current thread's priority. */
|
/* Return the current thread's priority. */
|
||||||
int
|
int
|
||||||
objc_thread_get_priority(void)
|
objc_thread_get_priority (void)
|
||||||
{
|
{
|
||||||
/* Call the backend */
|
/* Call the backend */
|
||||||
return __objc_thread_get_priority();
|
return __objc_thread_get_priority ();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -188,10 +188,10 @@ objc_thread_get_priority(void)
|
||||||
make progress even on a lazy uniprocessor system.
|
make progress even on a lazy uniprocessor system.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
objc_thread_yield(void)
|
objc_thread_yield (void)
|
||||||
{
|
{
|
||||||
/* Call the backend */
|
/* Call the backend */
|
||||||
__objc_thread_yield();
|
__objc_thread_yield ();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -199,15 +199,15 @@ objc_thread_yield(void)
|
||||||
Actually, if it failed returns -1.
|
Actually, if it failed returns -1.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
objc_thread_exit(void)
|
objc_thread_exit (void)
|
||||||
{
|
{
|
||||||
/* Decrement our counter of the number of threads alive */
|
/* Decrement our counter of the number of threads alive */
|
||||||
objc_mutex_lock(__objc_runtime_mutex);
|
objc_mutex_lock (__objc_runtime_mutex);
|
||||||
__objc_runtime_threads_alive--;
|
__objc_runtime_threads_alive--;
|
||||||
objc_mutex_unlock(__objc_runtime_mutex);
|
objc_mutex_unlock (__objc_runtime_mutex);
|
||||||
|
|
||||||
/* Call the backend to terminate the thread */
|
/* Call the backend to terminate the thread */
|
||||||
return __objc_thread_exit();
|
return __objc_thread_exit ();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -215,10 +215,10 @@ objc_thread_exit(void)
|
||||||
NULL which is reserved as a marker for "no thread".
|
NULL which is reserved as a marker for "no thread".
|
||||||
*/
|
*/
|
||||||
objc_thread_t
|
objc_thread_t
|
||||||
objc_thread_id(void)
|
objc_thread_id (void)
|
||||||
{
|
{
|
||||||
/* Call the backend */
|
/* Call the backend */
|
||||||
return __objc_thread_id();
|
return __objc_thread_id ();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -226,20 +226,20 @@ objc_thread_id(void)
|
||||||
Returns 0 if successful or -1 if failed.
|
Returns 0 if successful or -1 if failed.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
objc_thread_set_data(void *value)
|
objc_thread_set_data (void *value)
|
||||||
{
|
{
|
||||||
/* Call the backend */
|
/* Call the backend */
|
||||||
return __objc_thread_set_data(value);
|
return __objc_thread_set_data (value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Returns the thread's local storage pointer. Returns NULL on failure.
|
Returns the thread's local storage pointer. Returns NULL on failure.
|
||||||
*/
|
*/
|
||||||
void *
|
void *
|
||||||
objc_thread_get_data(void)
|
objc_thread_get_data (void)
|
||||||
{
|
{
|
||||||
/* Call the backend */
|
/* Call the backend */
|
||||||
return __objc_thread_get_data();
|
return __objc_thread_get_data ();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Frontend mutex functions */
|
/* Frontend mutex functions */
|
||||||
|
@ -249,19 +249,19 @@ objc_thread_get_data(void)
|
||||||
allocation failed for any reason.
|
allocation failed for any reason.
|
||||||
*/
|
*/
|
||||||
objc_mutex_t
|
objc_mutex_t
|
||||||
objc_mutex_allocate(void)
|
objc_mutex_allocate (void)
|
||||||
{
|
{
|
||||||
objc_mutex_t mutex;
|
objc_mutex_t mutex;
|
||||||
|
|
||||||
/* Allocate the mutex structure */
|
/* Allocate the mutex structure */
|
||||||
if (!(mutex = (objc_mutex_t)objc_malloc(sizeof(struct objc_mutex))))
|
if (! (mutex = (objc_mutex_t)objc_malloc (sizeof (struct objc_mutex))))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
/* Call backend to create the mutex */
|
/* Call backend to create the mutex */
|
||||||
if (__objc_mutex_allocate(mutex))
|
if (__objc_mutex_allocate (mutex))
|
||||||
{
|
{
|
||||||
/* failed! */
|
/* failed! */
|
||||||
objc_free(mutex);
|
objc_free (mutex);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -279,23 +279,23 @@ objc_mutex_allocate(void)
|
||||||
Returns the number of locks on the thread. (1 for deallocate).
|
Returns the number of locks on the thread. (1 for deallocate).
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
objc_mutex_deallocate(objc_mutex_t mutex)
|
objc_mutex_deallocate (objc_mutex_t mutex)
|
||||||
{
|
{
|
||||||
int depth;
|
int depth;
|
||||||
|
|
||||||
/* Valid mutex? */
|
/* Valid mutex? */
|
||||||
if (!mutex)
|
if (! mutex)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
/* Acquire lock on mutex */
|
/* Acquire lock on mutex */
|
||||||
depth = objc_mutex_lock(mutex);
|
depth = objc_mutex_lock (mutex);
|
||||||
|
|
||||||
/* Call backend to destroy mutex */
|
/* Call backend to destroy mutex */
|
||||||
if (__objc_mutex_deallocate(mutex))
|
if (__objc_mutex_deallocate (mutex))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
/* Free the mutex structure */
|
/* Free the mutex structure */
|
||||||
objc_free(mutex);
|
objc_free (mutex);
|
||||||
|
|
||||||
/* Return last depth */
|
/* Return last depth */
|
||||||
return depth;
|
return depth;
|
||||||
|
@ -308,22 +308,22 @@ objc_mutex_deallocate(objc_mutex_t mutex)
|
||||||
Returns the lock count on the mutex held by this thread.
|
Returns the lock count on the mutex held by this thread.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
objc_mutex_lock(objc_mutex_t mutex)
|
objc_mutex_lock (objc_mutex_t mutex)
|
||||||
{
|
{
|
||||||
objc_thread_t thread_id;
|
objc_thread_t thread_id;
|
||||||
int status;
|
int status;
|
||||||
|
|
||||||
/* Valid mutex? */
|
/* Valid mutex? */
|
||||||
if (!mutex)
|
if (! mutex)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
/* If we already own the lock then increment depth */
|
/* If we already own the lock then increment depth */
|
||||||
thread_id = __objc_thread_id();
|
thread_id = __objc_thread_id ();
|
||||||
if (mutex->owner == thread_id)
|
if (mutex->owner == thread_id)
|
||||||
return ++mutex->depth;
|
return ++mutex->depth;
|
||||||
|
|
||||||
/* Call the backend to lock the mutex */
|
/* Call the backend to lock the mutex */
|
||||||
status = __objc_mutex_lock(mutex);
|
status = __objc_mutex_lock (mutex);
|
||||||
|
|
||||||
/* Failed? */
|
/* Failed? */
|
||||||
if (status)
|
if (status)
|
||||||
|
@ -340,22 +340,22 @@ objc_mutex_lock(objc_mutex_t mutex)
|
||||||
thread has a lock on the mutex returns -1.
|
thread has a lock on the mutex returns -1.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
objc_mutex_trylock(objc_mutex_t mutex)
|
objc_mutex_trylock (objc_mutex_t mutex)
|
||||||
{
|
{
|
||||||
objc_thread_t thread_id;
|
objc_thread_t thread_id;
|
||||||
int status;
|
int status;
|
||||||
|
|
||||||
/* Valid mutex? */
|
/* Valid mutex? */
|
||||||
if (!mutex)
|
if (! mutex)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
/* If we already own the lock then increment depth */
|
/* If we already own the lock then increment depth */
|
||||||
thread_id = __objc_thread_id();
|
thread_id = __objc_thread_id ();
|
||||||
if (mutex->owner == thread_id)
|
if (mutex->owner == thread_id)
|
||||||
return ++mutex->depth;
|
return ++mutex->depth;
|
||||||
|
|
||||||
/* Call the backend to try to lock the mutex */
|
/* Call the backend to try to lock the mutex */
|
||||||
status = __objc_mutex_trylock(mutex);
|
status = __objc_mutex_trylock (mutex);
|
||||||
|
|
||||||
/* Failed? */
|
/* Failed? */
|
||||||
if (status)
|
if (status)
|
||||||
|
@ -375,17 +375,17 @@ objc_mutex_trylock(objc_mutex_t mutex)
|
||||||
doesn't hold in which case return -1 and the mutex is unaffected.
|
doesn't hold in which case return -1 and the mutex is unaffected.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
objc_mutex_unlock(objc_mutex_t mutex)
|
objc_mutex_unlock (objc_mutex_t mutex)
|
||||||
{
|
{
|
||||||
objc_thread_t thread_id;
|
objc_thread_t thread_id;
|
||||||
int status;
|
int status;
|
||||||
|
|
||||||
/* Valid mutex? */
|
/* Valid mutex? */
|
||||||
if (!mutex)
|
if (! mutex)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
/* If another thread owns the lock then abort */
|
/* If another thread owns the lock then abort */
|
||||||
thread_id = __objc_thread_id();
|
thread_id = __objc_thread_id ();
|
||||||
if (mutex->owner != thread_id)
|
if (mutex->owner != thread_id)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
@ -398,7 +398,7 @@ objc_mutex_unlock(objc_mutex_t mutex)
|
||||||
mutex->owner = NULL;
|
mutex->owner = NULL;
|
||||||
|
|
||||||
/* Have the backend unlock the mutex */
|
/* Have the backend unlock the mutex */
|
||||||
status = __objc_mutex_unlock(mutex);
|
status = __objc_mutex_unlock (mutex);
|
||||||
|
|
||||||
/* Failed? */
|
/* Failed? */
|
||||||
if (status)
|
if (status)
|
||||||
|
@ -414,20 +414,20 @@ objc_mutex_unlock(objc_mutex_t mutex)
|
||||||
if the allocation failed for any reason.
|
if the allocation failed for any reason.
|
||||||
*/
|
*/
|
||||||
objc_condition_t
|
objc_condition_t
|
||||||
objc_condition_allocate(void)
|
objc_condition_allocate (void)
|
||||||
{
|
{
|
||||||
objc_condition_t condition;
|
objc_condition_t condition;
|
||||||
|
|
||||||
/* Allocate the condition mutex structure */
|
/* Allocate the condition mutex structure */
|
||||||
if (!(condition =
|
if (! (condition =
|
||||||
(objc_condition_t)objc_malloc(sizeof(struct objc_condition))))
|
(objc_condition_t) objc_malloc (sizeof (struct objc_condition))))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
/* Call the backend to create the condition mutex */
|
/* Call the backend to create the condition mutex */
|
||||||
if (__objc_condition_allocate(condition))
|
if (__objc_condition_allocate (condition))
|
||||||
{
|
{
|
||||||
/* failed! */
|
/* failed! */
|
||||||
objc_free(condition);
|
objc_free (condition);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -443,41 +443,41 @@ objc_condition_allocate(void)
|
||||||
waiting but just wake them up.
|
waiting but just wake them up.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
objc_condition_deallocate(objc_condition_t condition)
|
objc_condition_deallocate (objc_condition_t condition)
|
||||||
{
|
{
|
||||||
/* Broadcast the condition */
|
/* Broadcast the condition */
|
||||||
if (objc_condition_broadcast(condition))
|
if (objc_condition_broadcast (condition))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
/* Call the backend to destroy */
|
/* Call the backend to destroy */
|
||||||
if (__objc_condition_deallocate(condition))
|
if (__objc_condition_deallocate (condition))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
/* Free the condition mutex structure */
|
/* Free the condition mutex structure */
|
||||||
objc_free(condition);
|
objc_free (condition);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Wait on the condition unlocking the mutex until objc_condition_signal()
|
Wait on the condition unlocking the mutex until objc_condition_signal ()
|
||||||
or objc_condition_broadcast() are called for the same condition. The
|
or objc_condition_broadcast () are called for the same condition. The
|
||||||
given mutex *must* have the depth set to 1 so that it can be unlocked
|
given mutex *must* have the depth set to 1 so that it can be unlocked
|
||||||
here, so that someone else can lock it and signal/broadcast the condition.
|
here, so that someone else can lock it and signal/broadcast the condition.
|
||||||
The mutex is used to lock access to the shared data that make up the
|
The mutex is used to lock access to the shared data that make up the
|
||||||
"condition" predicate.
|
"condition" predicate.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
objc_condition_wait(objc_condition_t condition, objc_mutex_t mutex)
|
objc_condition_wait (objc_condition_t condition, objc_mutex_t mutex)
|
||||||
{
|
{
|
||||||
objc_thread_t thread_id;
|
objc_thread_t thread_id;
|
||||||
|
|
||||||
/* Valid arguments? */
|
/* Valid arguments? */
|
||||||
if (!mutex || !condition)
|
if (! mutex || ! condition)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
/* Make sure we are owner of mutex */
|
/* Make sure we are owner of mutex */
|
||||||
thread_id = __objc_thread_id();
|
thread_id = __objc_thread_id ();
|
||||||
if (mutex->owner != thread_id)
|
if (mutex->owner != thread_id)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
@ -490,7 +490,7 @@ objc_condition_wait(objc_condition_t condition, objc_mutex_t mutex)
|
||||||
mutex->owner = (objc_thread_t)NULL;
|
mutex->owner = (objc_thread_t)NULL;
|
||||||
|
|
||||||
/* Call the backend to wait */
|
/* Call the backend to wait */
|
||||||
__objc_condition_wait(condition, mutex);
|
__objc_condition_wait (condition, mutex);
|
||||||
|
|
||||||
/* Make ourselves owner of the mutex */
|
/* Make ourselves owner of the mutex */
|
||||||
mutex->owner = thread_id;
|
mutex->owner = thread_id;
|
||||||
|
@ -506,13 +506,13 @@ objc_condition_wait(objc_condition_t condition, objc_mutex_t mutex)
|
||||||
right away after this call.
|
right away after this call.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
objc_condition_broadcast(objc_condition_t condition)
|
objc_condition_broadcast (objc_condition_t condition)
|
||||||
{
|
{
|
||||||
/* Valid condition mutex? */
|
/* Valid condition mutex? */
|
||||||
if (!condition)
|
if (! condition)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
return __objc_condition_broadcast(condition);
|
return __objc_condition_broadcast (condition);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -522,42 +522,42 @@ objc_condition_broadcast(objc_condition_t condition)
|
||||||
right away after this call.
|
right away after this call.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
objc_condition_signal(objc_condition_t condition)
|
objc_condition_signal (objc_condition_t condition)
|
||||||
{
|
{
|
||||||
/* Valid condition mutex? */
|
/* Valid condition mutex? */
|
||||||
if (!condition)
|
if (! condition)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
return __objc_condition_signal(condition);
|
return __objc_condition_signal (condition);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Make the objc thread system aware that a thread which is managed
|
/* Make the objc thread system aware that a thread which is managed
|
||||||
(started, stopped) by external code could access objc facilities
|
(started, stopped) by external code could access objc facilities
|
||||||
from now on. This is used when you are interfacing with some
|
from now on. This is used when you are interfacing with some
|
||||||
external non-objc-based environment/system - you must call
|
external non-objc-based environment/system - you must call
|
||||||
objc_thread_add() before an alien thread makes any calls to
|
objc_thread_add () before an alien thread makes any calls to
|
||||||
Objective-C. Do not cause the _objc_became_multi_threaded hook to
|
Objective-C. Do not cause the _objc_became_multi_threaded hook to
|
||||||
be executed. */
|
be executed. */
|
||||||
void
|
void
|
||||||
objc_thread_add(void)
|
objc_thread_add (void)
|
||||||
{
|
{
|
||||||
objc_mutex_lock(__objc_runtime_mutex);
|
objc_mutex_lock (__objc_runtime_mutex);
|
||||||
__objc_is_multi_threaded = 1;
|
__objc_is_multi_threaded = 1;
|
||||||
__objc_runtime_threads_alive++;
|
__objc_runtime_threads_alive++;
|
||||||
objc_mutex_unlock(__objc_runtime_mutex);
|
objc_mutex_unlock (__objc_runtime_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Make the objc thread system aware that a thread managed (started,
|
/* Make the objc thread system aware that a thread managed (started,
|
||||||
stopped) by some external code will no longer access objc and thus
|
stopped) by some external code will no longer access objc and thus
|
||||||
can be forgotten by the objc thread system. Call
|
can be forgotten by the objc thread system. Call
|
||||||
objc_thread_remove() when your alien thread is done with making
|
objc_thread_remove () when your alien thread is done with making
|
||||||
calls to Objective-C. */
|
calls to Objective-C. */
|
||||||
void
|
void
|
||||||
objc_thread_remove(void)
|
objc_thread_remove (void)
|
||||||
{
|
{
|
||||||
objc_mutex_lock(__objc_runtime_mutex);
|
objc_mutex_lock (__objc_runtime_mutex);
|
||||||
__objc_runtime_threads_alive--;
|
__objc_runtime_threads_alive--;
|
||||||
objc_mutex_unlock(__objc_runtime_mutex);
|
objc_mutex_unlock (__objc_runtime_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* End of File */
|
/* End of File */
|
||||||
|
|
Loading…
Reference in New Issue