Commit a39d31bc by Kresten Krab Thorup

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

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

From-SVN: r7622
parent 7a1dd323
/* Interface for the Object class for Objective-C. /* Interface for the Object class for Objective-C.
Copyright (C) 1993 Free Software Foundation, Inc. Copyright (C) 1993, 1994 Free Software Foundation, Inc.
This file is part of GNU CC. This file is part of GNU CC.
...@@ -93,8 +93,8 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ ...@@ -93,8 +93,8 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
- - perform:(SEL)aSel with:anObject1 with:anObject2; - - perform:(SEL)aSel with:anObject1 with:anObject2;
/* Forwarding */ /* Forwarding */
- - forward:(SEL)aSel :(arglist_t)argFrame; - (retval_t)forward:(SEL)aSel :(arglist_t)argFrame;
- - performv:(SEL)aSel :(arglist_t)argFrame; - (retval_t)performv:(SEL)aSel :(arglist_t)argFrame;
/* Posing */ /* Posing */
+ + poseAs:(Class*)aClassObject; + + poseAs:(Class*)aClassObject;
...@@ -112,14 +112,10 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ ...@@ -112,14 +112,10 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
/* Archiving */ /* Archiving */
+ (int)version; + (int)version;
+ + setVersion:(int)aVersion; + + setVersion:(int)aVersion;
#ifndef __alpha__ /* TypedStream not supported on alpha yet. */
+ (int)streamVersion: (TypedStream*)aStream; + (int)streamVersion: (TypedStream*)aStream;
- - read: (TypedStream*)aStream; - - read: (TypedStream*)aStream;
- - write: (TypedStream*)aStream; - - write: (TypedStream*)aStream;
#endif
- - awake; - - awake;
@end @end
......
...@@ -24,14 +24,18 @@ You should have received a copy of the GNU General Public License along with ...@@ -24,14 +24,18 @@ You should have received a copy of the GNU General Public License along with
however invalidate any other reasons why the executable file might be however invalidate any other reasons why the executable file might be
covered by the GNU General Public License. */ covered by the GNU General Public License. */
/*
** Note: This version assumes that int and longs are both 32bit.
*/
#ifndef __alpha__
#include "runtime.h" #include "runtime.h"
#include "typedstream.h" #include "typedstream.h"
#include "encoding.h"
extern int fflush(FILE*);
#define ROUND(V, A) \
({ typeof(V) __v=(V); typeof(A) __a=(A); \
__a*((__v+__a-1)/__a); })
#define PTR2LONG(P) (((char*)(P))-(char*)0)
#define LONG2PTR(L) (((char*)0)+(L))
#define __objc_fatal(format, args...) \ #define __objc_fatal(format, args...) \
{ fprintf(stderr, "archiving: "); \ { fprintf(stderr, "archiving: "); \
...@@ -43,22 +47,20 @@ You should have received a copy of the GNU General Public License along with ...@@ -43,22 +47,20 @@ You should have received a copy of the GNU General Public License along with
static int static int
objc_read_class (struct objc_typed_stream* stream, Class** class); objc_read_class (struct objc_typed_stream* stream, Class** class);
static int int objc_sizeof_type(const char* type);
objc_sizeof_type(const char* type);
static int static int
objc_write_use_common (struct objc_typed_stream* stream, unsigned int key); objc_write_use_common (struct objc_typed_stream* stream, unsigned long key);
static int static int
objc_write_register_common (struct objc_typed_stream* stream, objc_write_register_common (struct objc_typed_stream* stream,
unsigned int key); unsigned long key);
static int static int
objc_write_class (struct objc_typed_stream* stream, objc_write_class (struct objc_typed_stream* stream,
struct objc_class* class); struct objc_class* class);
static const char* const char* objc_skip_type (const char* type);
__objc_skip_type (const char* type);
static void __objc_finish_write_root_object(struct objc_typed_stream*); static void __objc_finish_write_root_object(struct objc_typed_stream*);
static void __objc_finish_read_root_object(struct objc_typed_stream*); static void __objc_finish_read_root_object(struct objc_typed_stream*);
...@@ -112,15 +114,29 @@ objc_write_char (struct objc_typed_stream* stream, char value) ...@@ -112,15 +114,29 @@ objc_write_char (struct objc_typed_stream* stream, char value)
static __inline__ int static __inline__ int
__objc_code_unsigned_short (unsigned char* buf, unsigned short val) __objc_code_unsigned_short (unsigned char* buf, unsigned short val)
{ {
if (val <= 0xffU) if ((val&_B_VALUE) == val)
return __objc_code_unsigned_char (buf, val); {
buf[0] = val|_B_SINT;
return 1;
}
else else
{ {
buf[0] = _B_NINT|0x02; int c, b;
buf[1] = val/0x100;
buf[2] = val%0x100; buf[0] = _B_NINT;
return 3;
for (c= sizeof(short); c != 0; c -= 1)
if (((val>>(8*(c-1)))%0x100) != 0)
break;
buf[0] |= c;
for (b = 1; c != 0; c--, b++)
{
buf[b] = (val >> (8*(c-1)))%0x100;
}
return b;
} }
} }
...@@ -135,18 +151,11 @@ objc_write_unsigned_short (struct objc_typed_stream* stream, unsigned short valu ...@@ -135,18 +151,11 @@ objc_write_unsigned_short (struct objc_typed_stream* stream, unsigned short valu
static __inline__ int static __inline__ int
__objc_code_short (unsigned char* buf, short val) __objc_code_short (unsigned char* buf, short val)
{ {
if (val > 0) int sign = (val < 0);
return __objc_code_unsigned_short (buf, val); int size = __objc_code_unsigned_short (buf, sign ? -val : val);
if (sign)
if (val > -0x7f) /* val > -128 */ buf[0] |= _B_SIGN;
return __objc_code_char (buf, val); return size;
else
{
int len = __objc_code_unsigned_short (buf, -val);
buf[0] |= _B_SIGN;
return len;
}
} }
int int
...@@ -161,26 +170,29 @@ objc_write_short (struct objc_typed_stream* stream, short value) ...@@ -161,26 +170,29 @@ objc_write_short (struct objc_typed_stream* stream, short value)
static __inline__ int static __inline__ int
__objc_code_unsigned_int (unsigned char* buf, unsigned int val) __objc_code_unsigned_int (unsigned char* buf, unsigned int val)
{ {
if (val < 0x10000) if ((val&_B_VALUE) == val)
return __objc_code_unsigned_short (buf, val%0x10000);
else if (val < 0x1000000)
{ {
buf[0] = _B_NINT|3; buf[0] = val|_B_SINT;
buf[1] = val/0x10000; return 1;
buf[2] = (val%0x10000)/0x100;
buf[3] = val%0x100;
return 4;
} }
else else
{ {
buf[0] = _B_NINT|4; int c, b;
buf[1] = val/0x1000000;
buf[2] = (val%0x1000000)/0x10000; buf[0] = _B_NINT;
buf[3] = (val%0x10000)/0x100;
buf[4] = val%0x100; for (c= sizeof(int); c != 0; c -= 1)
return 5; if (((val>>(8*(c-1)))%0x100) != 0)
break;
buf[0] |= c;
for (b = 1; c != 0; c--, b++)
{
buf[b] = (val >> (8*(c-1)))%0x100;
}
return b;
} }
} }
...@@ -195,28 +207,77 @@ objc_write_unsigned_int (struct objc_typed_stream* stream, unsigned int value) ...@@ -195,28 +207,77 @@ objc_write_unsigned_int (struct objc_typed_stream* stream, unsigned int value)
static __inline__ int static __inline__ int
__objc_code_int (unsigned char* buf, int val) __objc_code_int (unsigned char* buf, int val)
{ {
if (val >= 0) int sign = (val < 0);
return __objc_code_unsigned_int (buf, val); int size = __objc_code_unsigned_int (buf, sign ? -val : val);
if (sign)
buf[0] |= _B_SIGN;
return size;
}
if (val > -0x7f) int
return __objc_code_char (buf, val); objc_write_int (struct objc_typed_stream* stream, int value)
{
unsigned char buf[sizeof(int)+1];
int len = __objc_code_int (buf, value);
return (*stream->write)(stream->physical, buf, len);
}
static __inline__ int
__objc_code_unsigned_long (unsigned char* buf, unsigned long val)
{
if ((val&_B_VALUE) == val)
{
buf[0] = val|_B_SINT;
return 1;
}
else else
{ {
int len = __objc_code_unsigned_int (buf, -val); int c, b;
buf[0] |= _B_SIGN;
return len; buf[0] = _B_NINT;
for (c= sizeof(long); c != 0; c -= 1)
if (((val>>(8*(c-1)))%0x100) != 0)
break;
buf[0] |= c;
for (b = 1; c != 0; c--, b++)
{
buf[b] = (val >> (8*(c-1)))%0x100;
}
return b;
} }
} }
int int
objc_write_int (struct objc_typed_stream* stream, int value) objc_write_unsigned_long (struct objc_typed_stream* stream, unsigned long value)
{ {
unsigned char buf[sizeof(int)+1]; unsigned char buf[sizeof(unsigned long)+1];
int len = __objc_code_int (buf, value); int len = __objc_code_unsigned_long (buf, value);
return (*stream->write)(stream->physical, buf, len); return (*stream->write)(stream->physical, buf, len);
} }
static __inline__ int
__objc_code_long (unsigned char* buf, long val)
{
int sign = (val < 0);
int size = __objc_code_unsigned_long (buf, sign ? -val : val);
if (sign)
buf[0] |= _B_SIGN;
return size;
}
int
objc_write_long (struct objc_typed_stream* stream, long value)
{
unsigned char buf[sizeof(long)+1];
int len = __objc_code_long (buf, value);
return (*stream->write)(stream->physical, buf, len);
}
int int
objc_write_string (struct objc_typed_stream* stream, objc_write_string (struct objc_typed_stream* stream,
const unsigned char* string, unsigned int nbytes) const unsigned char* string, unsigned int nbytes)
...@@ -240,13 +301,13 @@ int ...@@ -240,13 +301,13 @@ int
objc_write_string_atomic (struct objc_typed_stream* stream, objc_write_string_atomic (struct objc_typed_stream* stream,
unsigned char* string, unsigned int nbytes) unsigned char* string, unsigned int nbytes)
{ {
unsigned int key; unsigned long key;
if ((key = (unsigned int)hash_value_for_key (stream->stream_table, string))) if ((key = PTR2LONG(hash_value_for_key (stream->stream_table, string))))
return objc_write_use_common (stream, key); return objc_write_use_common (stream, key);
else else
{ {
int length; int length;
hash_add (&stream->stream_table, (void*)key=(unsigned int)string, string); hash_add (&stream->stream_table, LONG2PTR(key=PTR2LONG(string)), string);
if ((length = objc_write_register_common (stream, key))) if ((length = objc_write_register_common (stream, key)))
return objc_write_string (stream, string, nbytes); return objc_write_string (stream, string, nbytes);
return length; return length;
...@@ -254,10 +315,10 @@ objc_write_string_atomic (struct objc_typed_stream* stream, ...@@ -254,10 +315,10 @@ objc_write_string_atomic (struct objc_typed_stream* stream,
} }
static int static int
objc_write_register_common (struct objc_typed_stream* stream, unsigned int key) objc_write_register_common (struct objc_typed_stream* stream, unsigned long key)
{ {
unsigned char buf[sizeof (unsigned int)+2]; unsigned char buf[sizeof (unsigned long)+2];
int len = __objc_code_unsigned_int (buf+1, key); int len = __objc_code_unsigned_long (buf+1, key);
if (len == 1) if (len == 1)
{ {
buf[0] = _B_RCOMM|0x01; buf[0] = _B_RCOMM|0x01;
...@@ -272,10 +333,10 @@ objc_write_register_common (struct objc_typed_stream* stream, unsigned int key) ...@@ -272,10 +333,10 @@ objc_write_register_common (struct objc_typed_stream* stream, unsigned int key)
} }
static int static int
objc_write_use_common (struct objc_typed_stream* stream, unsigned int key) objc_write_use_common (struct objc_typed_stream* stream, unsigned long key)
{ {
unsigned char buf[sizeof (unsigned int)+2]; unsigned char buf[sizeof (unsigned long)+2];
int len = __objc_code_unsigned_int (buf+1, key); int len = __objc_code_unsigned_long (buf+1, key);
if (len == 1) if (len == 1)
{ {
buf[0] = _B_UCOMM|0x01; buf[0] = _B_UCOMM|0x01;
...@@ -305,7 +366,7 @@ __inline__ int ...@@ -305,7 +366,7 @@ __inline__ int
__objc_write_object (struct objc_typed_stream* stream, id object) __objc_write_object (struct objc_typed_stream* stream, id object)
{ {
unsigned char buf = '\0'; unsigned char buf = '\0';
SEL write_sel = sel_get_uid ("write:"); SEL write_sel = sel_get_any_uid ("write:");
if (object) if (object)
{ {
__objc_write_extension (stream, _BX_OBJECT); __objc_write_extension (stream, _BX_OBJECT);
...@@ -320,12 +381,12 @@ __objc_write_object (struct objc_typed_stream* stream, id object) ...@@ -320,12 +381,12 @@ __objc_write_object (struct objc_typed_stream* stream, id object)
int int
objc_write_object_reference (struct objc_typed_stream* stream, id object) objc_write_object_reference (struct objc_typed_stream* stream, id object)
{ {
unsigned int key; unsigned long key;
if ((key = (unsigned int)hash_value_for_key (stream->object_table, object))) if ((key = PTR2LONG(hash_value_for_key (stream->object_table, object))))
return objc_write_use_common (stream, key); return objc_write_use_common (stream, key);
__objc_write_extension (stream, _BX_OBJREF); __objc_write_extension (stream, _BX_OBJREF);
return objc_write_unsigned_int (stream, (unsigned int)object); return objc_write_unsigned_long (stream, PTR2LONG (object));
} }
int int
...@@ -348,8 +409,8 @@ objc_write_root_object (struct objc_typed_stream* stream, id object) ...@@ -348,8 +409,8 @@ objc_write_root_object (struct objc_typed_stream* stream, id object)
int int
objc_write_object (struct objc_typed_stream* stream, id object) objc_write_object (struct objc_typed_stream* stream, id object)
{ {
unsigned int key; unsigned long key;
if ((key = (unsigned int)hash_value_for_key (stream->object_table, object))) if ((key = PTR2LONG(hash_value_for_key (stream->object_table, object))))
return objc_write_use_common (stream, key); return objc_write_use_common (stream, key);
else if (object == nil) else if (object == nil)
...@@ -358,20 +419,26 @@ objc_write_object (struct objc_typed_stream* stream, id object) ...@@ -358,20 +419,26 @@ objc_write_object (struct objc_typed_stream* stream, id object)
else else
{ {
int length; int length;
hash_add (&stream->object_table, (void*)key=(unsigned int)object, object); hash_add (&stream->object_table, LONG2PTR(key=PTR2LONG(object)), object);
if ((length = objc_write_register_common (stream, key))) if ((length = objc_write_register_common (stream, key)))
return __objc_write_object (stream, object); return __objc_write_object (stream, object);
return length; return length;
} }
} }
#ifdef __alpha__
extern int atoi (const char*);
extern size_t strlen(const char*);
extern size_t strcpy(char*, const char*);
#endif
__inline__ int __inline__ int
__objc_write_class (struct objc_typed_stream* stream, struct objc_class* class) __objc_write_class (struct objc_typed_stream* stream, struct objc_class* class)
{ {
__objc_write_extension (stream, _BX_CLASS); __objc_write_extension (stream, _BX_CLASS);
objc_write_string_atomic(stream, (char*)class->name, objc_write_string_atomic(stream, (char*)class->name,
strlen((char*)class->name)); strlen((char*)class->name));
return objc_write_unsigned_int (stream, CLS_GETNUMBER(class)); return objc_write_unsigned_long (stream, CLS_GETNUMBER(class));
} }
...@@ -379,13 +446,13 @@ static int ...@@ -379,13 +446,13 @@ static int
objc_write_class (struct objc_typed_stream* stream, objc_write_class (struct objc_typed_stream* stream,
struct objc_class* class) struct objc_class* class)
{ {
unsigned int key; unsigned long key;
if ((key = (unsigned int)hash_value_for_key (stream->stream_table, class))) if ((key = PTR2LONG(hash_value_for_key (stream->stream_table, class))))
return objc_write_use_common (stream, key); return objc_write_use_common (stream, key);
else else
{ {
int length; int length;
hash_add (&stream->stream_table, (void*)key=(unsigned int)class, class); hash_add (&stream->stream_table, LONG2PTR(key=PTR2LONG(class)), class);
if ((length = objc_write_register_common (stream, key))) if ((length = objc_write_register_common (stream, key)))
return __objc_write_class (stream, class); return __objc_write_class (stream, class);
return length; return length;
...@@ -405,13 +472,13 @@ int ...@@ -405,13 +472,13 @@ int
objc_write_selector (struct objc_typed_stream* stream, SEL selector) objc_write_selector (struct objc_typed_stream* stream, SEL selector)
{ {
const char* sel_name = sel_get_name (selector); const char* sel_name = sel_get_name (selector);
unsigned int key; unsigned long key;
if ((key = (unsigned int)hash_value_for_key (stream->stream_table, sel_name))) if ((key = PTR2LONG(hash_value_for_key (stream->stream_table, sel_name))))
return objc_write_use_common (stream, key); return objc_write_use_common (stream, key);
else else
{ {
int length; int length;
hash_add (&stream->stream_table, (void*)key=(unsigned int)sel_name, (char*)sel_name); hash_add (&stream->stream_table, LONG2PTR(key=PTR2LONG(sel_name)), (char*)sel_name);
if ((length = objc_write_register_common (stream, key))) if ((length = objc_write_register_common (stream, key)))
return __objc_write_selector (stream, selector); return __objc_write_selector (stream, selector);
return length; return length;
...@@ -552,6 +619,33 @@ objc_read_int (struct objc_typed_stream* stream, int* value) ...@@ -552,6 +619,33 @@ objc_read_int (struct objc_typed_stream* stream, int* value)
} }
__inline__ int __inline__ int
objc_read_long (struct objc_typed_stream* stream, long* value)
{
unsigned char buf[sizeof(long)+1];
int len;
if ((len = (*stream->read)(stream->physical, buf, 1)))
{
if ((buf[0] & _B_CODE) == _B_SINT)
(*value) = (buf[0] & _B_VALUE);
else
{
int pos = 1;
int nbytes = buf[0] & _B_NUMBER;
if (nbytes > sizeof (long))
__objc_fatal("expected long, got bigger");
len = (*stream->read)(stream->physical, buf+1, nbytes);
(*value) = 0;
while (pos <= nbytes)
(*value) = ((*value)*0x100) + buf[pos++];
if (buf[0] & _B_SIGN)
(*value) = -(*value);
}
}
return len;
}
__inline__ int
__objc_read_nbyte_uint (struct objc_typed_stream* stream, __objc_read_nbyte_uint (struct objc_typed_stream* stream,
unsigned int nbytes, unsigned int* val) unsigned int nbytes, unsigned int* val)
{ {
...@@ -587,6 +681,42 @@ objc_read_unsigned_int (struct objc_typed_stream* stream, ...@@ -587,6 +681,42 @@ objc_read_unsigned_int (struct objc_typed_stream* stream,
return len; return len;
} }
int
__objc_read_nbyte_ulong (struct objc_typed_stream* stream,
unsigned int nbytes, unsigned long* val)
{
int len, pos = 0;
unsigned char buf[sizeof(unsigned long)+1];
if (nbytes > sizeof (long))
__objc_fatal("expected long, got bigger");
len = (*stream->read)(stream->physical, buf, nbytes);
(*val) = 0;
while (pos < nbytes)
(*val) = ((*val)*0x100) + buf[pos++];
return len;
}
__inline__ int
objc_read_unsigned_long (struct objc_typed_stream* stream,
unsigned long* value)
{
unsigned char buf[sizeof(unsigned long)+1];
int len;
if ((len = (*stream->read)(stream->physical, buf, 1)))
{
if ((buf[0] & _B_CODE) == _B_SINT)
(*value) = (buf[0] & _B_VALUE);
else
len = __objc_read_nbyte_ulong (stream, (buf[0] & _B_VALUE), value);
}
return len;
}
__inline__ int __inline__ int
objc_read_string (struct objc_typed_stream* stream, objc_read_string (struct objc_typed_stream* stream,
char** string) char** string)
...@@ -595,11 +725,11 @@ objc_read_string (struct objc_typed_stream* stream, ...@@ -595,11 +725,11 @@ objc_read_string (struct objc_typed_stream* stream,
int len; int len;
if ((len = (*stream->read)(stream->physical, buf, 1))) if ((len = (*stream->read)(stream->physical, buf, 1)))
{ {
unsigned int key = 0; unsigned long key = 0;
if ((buf[0]&_B_CODE) == _B_RCOMM) /* register following */ if ((buf[0]&_B_CODE) == _B_RCOMM) /* register following */
{ {
len = __objc_read_nbyte_uint(stream, (buf[0] & _B_VALUE), &key); len = __objc_read_nbyte_ulong(stream, (buf[0] & _B_VALUE), &key);
len = (*stream->read)(stream->physical, buf, 1); len = (*stream->read)(stream->physical, buf, 1);
} }
...@@ -609,7 +739,7 @@ objc_read_string (struct objc_typed_stream* stream, ...@@ -609,7 +739,7 @@ objc_read_string (struct objc_typed_stream* stream,
int length = buf[0]&_B_VALUE; int length = buf[0]&_B_VALUE;
(*string) = (char*)__objc_xmalloc(length+1); (*string) = (char*)__objc_xmalloc(length+1);
if (key) if (key)
hash_add (&stream->stream_table, (void*)key, *string); hash_add (&stream->stream_table, LONG2PTR(key), *string);
len = (*stream->read)(stream->physical, *string, length); len = (*stream->read)(stream->physical, *string, length);
(*string)[length] = '\0'; (*string)[length] = '\0';
} }
...@@ -618,9 +748,9 @@ objc_read_string (struct objc_typed_stream* stream, ...@@ -618,9 +748,9 @@ objc_read_string (struct objc_typed_stream* stream,
case _B_UCOMM: case _B_UCOMM:
{ {
char *tmp; char *tmp;
len = __objc_read_nbyte_uint (stream, (buf[0] & _B_VALUE), &key); len = __objc_read_nbyte_ulong(stream, (buf[0] & _B_VALUE), &key);
tmp = hash_value_for_key (stream->stream_table, (void*)key); tmp = hash_value_for_key (stream->stream_table, LONG2PTR (key));
*string = __objc_xmalloc (strlen (tmp) + 1); *string = __objc_xmalloc (strlen(tmp) + 1);
strcpy (*string, tmp); strcpy (*string, tmp);
} }
break; break;
...@@ -632,7 +762,7 @@ objc_read_string (struct objc_typed_stream* stream, ...@@ -632,7 +762,7 @@ objc_read_string (struct objc_typed_stream* stream,
if (len) { if (len) {
(*string) = (char*)__objc_xmalloc(nbytes+1); (*string) = (char*)__objc_xmalloc(nbytes+1);
if (key) if (key)
hash_add (&stream->stream_table, (void*)key, *string); hash_add (&stream->stream_table, LONG2PTR(key), *string);
len = (*stream->read)(stream->physical, *string, nbytes); len = (*stream->read)(stream->physical, *string, nbytes);
(*string)[nbytes] = '\0'; (*string)[nbytes] = '\0';
} }
...@@ -655,12 +785,12 @@ objc_read_object (struct objc_typed_stream* stream, id* object) ...@@ -655,12 +785,12 @@ objc_read_object (struct objc_typed_stream* stream, id* object)
int len; int len;
if ((len = (*stream->read)(stream->physical, buf, 1))) if ((len = (*stream->read)(stream->physical, buf, 1)))
{ {
SEL read_sel = sel_get_uid ("read:"); SEL read_sel = sel_get_any_uid ("read:");
unsigned int key = 0; unsigned long key = 0;
if ((buf[0]&_B_CODE) == _B_RCOMM) /* register common */ if ((buf[0]&_B_CODE) == _B_RCOMM) /* register common */
{ {
len = __objc_read_nbyte_uint(stream, (buf[0] & _B_VALUE), &key); len = __objc_read_nbyte_ulong(stream, (buf[0] & _B_VALUE), &key);
len = (*stream->read)(stream->physical, buf, 1); len = (*stream->read)(stream->physical, buf, 1);
} }
...@@ -676,7 +806,7 @@ objc_read_object (struct objc_typed_stream* stream, id* object) ...@@ -676,7 +806,7 @@ objc_read_object (struct objc_typed_stream* stream, id* object)
/* register? */ /* register? */
if (key) if (key)
hash_add (&stream->object_table, (void*)key, *object); hash_add (&stream->object_table, LONG2PTR(key), *object);
/* send -read: */ /* send -read: */
if (__objc_responds_to (*object, read_sel)) if (__objc_responds_to (*object, read_sel))
...@@ -692,16 +822,16 @@ objc_read_object (struct objc_typed_stream* stream, id* object) ...@@ -692,16 +822,16 @@ objc_read_object (struct objc_typed_stream* stream, id* object)
{ {
if (key) if (key)
__objc_fatal("cannot register use upcode..."); __objc_fatal("cannot register use upcode...");
len = __objc_read_nbyte_uint(stream, (buf[0] & _B_VALUE), &key); len = __objc_read_nbyte_ulong(stream, (buf[0] & _B_VALUE), &key);
(*object) = hash_value_for_key (stream->object_table, (void*)key); (*object) = hash_value_for_key (stream->object_table, LONG2PTR(key));
} }
else if (buf[0] == (_B_EXT | _BX_OBJREF)) /* a forward reference */ else if (buf[0] == (_B_EXT | _BX_OBJREF)) /* a forward reference */
{ {
struct objc_list* other; struct objc_list* other;
len = objc_read_unsigned_int (stream, &key); len = objc_read_unsigned_long (stream, &key);
other = (struct objc_list*)hash_value_for_key (stream->object_refs, (void*)key); other = (struct objc_list*)hash_value_for_key (stream->object_refs, LONG2PTR(key));
hash_add (&stream->object_refs, (void*)key, (void*)list_cons(object, other)); hash_add (&stream->object_refs, LONG2PTR(key), (void*)list_cons(object, other));
} }
else if (buf[0] == (_B_EXT | _BX_OBJROOT)) /* a root object */ else if (buf[0] == (_B_EXT | _BX_OBJROOT)) /* a root object */
...@@ -725,18 +855,18 @@ objc_read_class (struct objc_typed_stream* stream, Class** class) ...@@ -725,18 +855,18 @@ objc_read_class (struct objc_typed_stream* stream, Class** class)
int len; int len;
if ((len = (*stream->read)(stream->physical, buf, 1))) if ((len = (*stream->read)(stream->physical, buf, 1)))
{ {
unsigned int key = 0; unsigned long key = 0;
if ((buf[0]&_B_CODE) == _B_RCOMM) /* register following */ if ((buf[0]&_B_CODE) == _B_RCOMM) /* register following */
{ {
len = __objc_read_nbyte_uint(stream, (buf[0] & _B_VALUE), &key); len = __objc_read_nbyte_ulong(stream, (buf[0] & _B_VALUE), &key);
len = (*stream->read)(stream->physical, buf, 1); len = (*stream->read)(stream->physical, buf, 1);
} }
if (buf[0] == (_B_EXT | _BX_CLASS)) if (buf[0] == (_B_EXT | _BX_CLASS))
{ {
char* class_name; char* class_name;
int version; unsigned long version;
/* get class */ /* get class */
len = objc_read_string (stream, &class_name); len = objc_read_string (stream, &class_name);
...@@ -745,9 +875,9 @@ objc_read_class (struct objc_typed_stream* stream, Class** class) ...@@ -745,9 +875,9 @@ objc_read_class (struct objc_typed_stream* stream, Class** class)
/* register */ /* register */
if (key) if (key)
hash_add (&stream->stream_table, (void*)key, *class); hash_add (&stream->stream_table, LONG2PTR(key), *class);
objc_read_unsigned_int(stream, &version); objc_read_unsigned_long(stream, &version);
hash_add (&stream->class_table, (*class)->name, (void*)version); hash_add (&stream->class_table, (*class)->name, (void*)version);
} }
...@@ -755,10 +885,10 @@ objc_read_class (struct objc_typed_stream* stream, Class** class) ...@@ -755,10 +885,10 @@ objc_read_class (struct objc_typed_stream* stream, Class** class)
{ {
if (key) if (key)
__objc_fatal("cannot register use upcode..."); __objc_fatal("cannot register use upcode...");
len = __objc_read_nbyte_uint(stream, (buf[0] & _B_VALUE), &key); len = __objc_read_nbyte_ulong(stream, (buf[0] & _B_VALUE), &key);
(*class) = hash_value_for_key (stream->stream_table, (void*)key); (*class) = hash_value_for_key (stream->stream_table, LONG2PTR(key));
if (!*class) if (!*class)
__objc_fatal("cannot find class for key %x", key); __objc_fatal("cannot find class for key %lu", key);
} }
else else
...@@ -774,11 +904,11 @@ objc_read_selector (struct objc_typed_stream* stream, SEL* selector) ...@@ -774,11 +904,11 @@ objc_read_selector (struct objc_typed_stream* stream, SEL* selector)
int len; int len;
if ((len = (*stream->read)(stream->physical, buf, 1))) if ((len = (*stream->read)(stream->physical, buf, 1)))
{ {
unsigned int key = 0; unsigned long key = 0;
if ((buf[0]&_B_CODE) == _B_RCOMM) /* register following */ if ((buf[0]&_B_CODE) == _B_RCOMM) /* register following */
{ {
len = __objc_read_nbyte_uint(stream, (buf[0] & _B_VALUE), &key); len = __objc_read_nbyte_ulong(stream, (buf[0] & _B_VALUE), &key);
len = (*stream->read)(stream->physical, buf, 1); len = (*stream->read)(stream->physical, buf, 1);
} }
...@@ -788,20 +918,20 @@ objc_read_selector (struct objc_typed_stream* stream, SEL* selector) ...@@ -788,20 +918,20 @@ objc_read_selector (struct objc_typed_stream* stream, SEL* selector)
/* get selector */ /* get selector */
len = objc_read_string (stream, &selector_name); len = objc_read_string (stream, &selector_name);
(*selector) = sel_get_uid(selector_name); (*selector) = sel_get_any_uid(selector_name);
free (selector_name); free (selector_name);
/* register */ /* register */
if (key) if (key)
hash_add (&stream->stream_table, (void*)key, *selector); hash_add (&stream->stream_table, LONG2PTR(key), (void*)*selector);
} }
else if ((buf[0]&_B_CODE) == _B_UCOMM) else if ((buf[0]&_B_CODE) == _B_UCOMM)
{ {
if (key) if (key)
__objc_fatal("cannot register use upcode..."); __objc_fatal("cannot register use upcode...");
len = __objc_read_nbyte_uint(stream, (buf[0] & _B_VALUE), &key); len = __objc_read_nbyte_ulong(stream, (buf[0] & _B_VALUE), &key);
(*selector) = hash_value_for_key (stream->stream_table, (void*)key); (*selector) = hash_value_for_key (stream->stream_table, LONG2PTR(key));
} }
else else
...@@ -810,96 +940,6 @@ objc_read_selector (struct objc_typed_stream* stream, SEL* selector) ...@@ -810,96 +940,6 @@ objc_read_selector (struct objc_typed_stream* stream, SEL* selector)
return len; return len;
} }
static int
objc_sizeof_type(const char* type)
{
switch(*type) {
case _C_ID: return sizeof(id);
break;
case _C_CLASS:
return sizeof(Class*);
break;
case _C_SEL:
return sizeof(SEL);
break;
case _C_CHR:
return sizeof(char);
break;
case _C_UCHR:
return sizeof(unsigned char);
break;
case _C_SHT:
return sizeof(short);
break;
case _C_USHT:
return sizeof(unsigned short);
break;
case _C_INT:
case _C_LNG:
return sizeof(int);
break;
case _C_UINT:
case _C_ULNG:
return sizeof(unsigned int);
break;
case _C_ATOM:
case _C_CHARPTR:
return sizeof(char*);
break;
default:
fprintf(stderr, "objc_sizeof_type: cannot parse typespec: %s\n", type);
abort();
}
}
static const char*
__objc_skip_type (const char* type)
{
switch (*type) {
case _C_ID:
case _C_CLASS:
case _C_SEL:
case _C_CHR:
case _C_UCHR:
case _C_CHARPTR:
case _C_ATOM:
case _C_SHT:
case _C_USHT:
case _C_INT:
case _C_UINT:
case _C_LNG:
case _C_ULNG:
case _C_FLT:
case _C_DBL:
return ++type;
break;
case _C_ARY_B:
while(isdigit(*++type));
type = __objc_skip_type(type);
if (*type == _C_ARY_E)
return ++type;
else
__objc_fatal("cannot parse typespec: %s", type);
break;
default:
fprintf(stderr, "__objc_skip_type: cannot parse typespec: %s\n", type);
abort();
}
}
/* /*
** USER LEVEL FUNCTIONS ** USER LEVEL FUNCTIONS
*/ */
...@@ -942,15 +982,21 @@ objc_write_type(TypedStream* stream, const char* type, const void* data) ...@@ -942,15 +982,21 @@ objc_write_type(TypedStream* stream, const char* type, const void* data)
break; break;
case _C_INT: case _C_INT:
case _C_LNG:
return objc_write_int(stream, *(int*)data); return objc_write_int(stream, *(int*)data);
break; break;
case _C_UINT: case _C_UINT:
case _C_ULNG:
return objc_write_unsigned_int(stream, *(unsigned int*)data); return objc_write_unsigned_int(stream, *(unsigned int*)data);
break; break;
case _C_LNG:
return objc_write_long(stream, *(long*)data);
break;
case _C_ULNG:
return objc_write_unsigned_long(stream, *(unsigned long*)data);
break;
case _C_CHARPTR: case _C_CHARPTR:
return objc_write_string (stream, *(char**)data, strlen(*(char**)data)); return objc_write_string (stream, *(char**)data, strlen(*(char**)data));
break; break;
...@@ -967,6 +1013,22 @@ objc_write_type(TypedStream* stream, const char* type, const void* data) ...@@ -967,6 +1013,22 @@ objc_write_type(TypedStream* stream, const char* type, const void* data)
} }
break; break;
case _C_STRUCT_B:
{
int acc_size = 0;
int align;
while (*type != _C_STRUCT_E && *type++ != '='); /* skip "<name>=" */
while (*type != _C_STRUCT_E);
{
align = objc_alignof_type (type); /* padd to alignment */
acc_size += ROUND (acc_size, align);
objc_write_type (stream, type, ((char*)data)+acc_size);
acc_size += objc_sizeof_type (type); /* add component size */
type = objc_skip_typespec (type); /* skip component */
}
return 1;
}
default: default:
fprintf(stderr, "objc_write_type: cannot parse typespec: %s\n", type); fprintf(stderr, "objc_write_type: cannot parse typespec: %s\n", type);
abort(); abort();
...@@ -1014,15 +1076,21 @@ objc_read_type(TypedStream* stream, const char* type, void* data) ...@@ -1014,15 +1076,21 @@ objc_read_type(TypedStream* stream, const char* type, void* data)
break; break;
case _C_INT: case _C_INT:
case _C_LNG:
return objc_read_int (stream, (int*)data); return objc_read_int (stream, (int*)data);
break; break;
case _C_UINT: case _C_UINT:
case _C_ULNG:
return objc_read_unsigned_int (stream, (unsigned int*)data); return objc_read_unsigned_int (stream, (unsigned int*)data);
break; break;
case _C_LNG:
return objc_read_long (stream, (long*)data);
break;
case _C_ULNG:
return objc_read_unsigned_long (stream, (unsigned long*)data);
break;
case _C_CHARPTR: case _C_CHARPTR:
case _C_ATOM: case _C_ATOM:
return objc_read_string (stream, (char**)data); return objc_read_string (stream, (char**)data);
...@@ -1036,6 +1104,22 @@ objc_read_type(TypedStream* stream, const char* type, void* data) ...@@ -1036,6 +1104,22 @@ objc_read_type(TypedStream* stream, const char* type, void* data)
} }
break; break;
case _C_STRUCT_B:
{
int acc_size = 0;
int align;
while (*type != _C_STRUCT_E && *type++ != '='); /* skip "<name>=" */
while (*type != _C_STRUCT_E);
{
align = objc_alignof_type (type); /* padd to alignment */
acc_size += ROUND (acc_size, align);
objc_read_type (stream, type, ((char*)data)+acc_size);
acc_size += objc_sizeof_type (type); /* add component size */
type = objc_skip_typespec (type); /* skip component */
}
return 1;
}
default: default:
fprintf(stderr, "objc_read_type: cannot parse typespec: %s\n", type); fprintf(stderr, "objc_read_type: cannot parse typespec: %s\n", type);
abort(); abort();
...@@ -1061,7 +1145,7 @@ objc_write_types (TypedStream* stream, const char* type, ...) ...@@ -1061,7 +1145,7 @@ objc_write_types (TypedStream* stream, const char* type, ...)
va_start(args, type); va_start(args, type);
for (c = type; *c; c = __objc_skip_type (c)) for (c = type; *c; c = objc_skip_typespec (c))
{ {
switch(*c) { switch(*c) {
case _C_ID: case _C_ID:
...@@ -1095,15 +1179,21 @@ objc_write_types (TypedStream* stream, const char* type, ...) ...@@ -1095,15 +1179,21 @@ objc_write_types (TypedStream* stream, const char* type, ...)
break; break;
case _C_INT: case _C_INT:
case _C_LNG:
res = objc_write_int(stream, *va_arg(args, int*)); res = objc_write_int(stream, *va_arg(args, int*));
break; break;
case _C_UINT: case _C_UINT:
case _C_ULNG:
res = objc_write_unsigned_int(stream, *va_arg(args, unsigned int*)); res = objc_write_unsigned_int(stream, *va_arg(args, unsigned int*));
break; break;
case _C_LNG:
res = objc_write_long(stream, *va_arg(args, long*));
break;
case _C_ULNG:
res = objc_write_unsigned_long(stream, *va_arg(args, unsigned long*));
break;
case _C_CHARPTR: case _C_CHARPTR:
{ {
char** str = va_arg(args, char**); char** str = va_arg(args, char**);
...@@ -1124,7 +1214,7 @@ objc_write_types (TypedStream* stream, const char* type, ...) ...@@ -1124,7 +1214,7 @@ objc_write_types (TypedStream* stream, const char* type, ...)
const char* t = c; const char* t = c;
while (isdigit(*++t)); while (isdigit(*++t));
res = objc_write_array (stream, t, len, va_arg(args, void*)); res = objc_write_array (stream, t, len, va_arg(args, void*));
t = __objc_skip_type (t); t = objc_skip_typespec (t);
if (*t != _C_ARY_E) if (*t != _C_ARY_E)
__objc_fatal("expected `]', got: %s", t); __objc_fatal("expected `]', got: %s", t);
} }
...@@ -1154,7 +1244,7 @@ objc_read_types(TypedStream* stream, const char* type, ...) ...@@ -1154,7 +1244,7 @@ objc_read_types(TypedStream* stream, const char* type, ...)
va_start(args, type); va_start(args, type);
for (c = type; *c; c = __objc_skip_type(c)) for (c = type; *c; c = objc_skip_typespec(c))
{ {
switch(*c) { switch(*c) {
case _C_ID: case _C_ID:
...@@ -1186,15 +1276,21 @@ objc_read_types(TypedStream* stream, const char* type, ...) ...@@ -1186,15 +1276,21 @@ objc_read_types(TypedStream* stream, const char* type, ...)
break; break;
case _C_INT: case _C_INT:
case _C_LNG:
res = objc_read_int(stream, va_arg(args, int*)); res = objc_read_int(stream, va_arg(args, int*));
break; break;
case _C_UINT: case _C_UINT:
case _C_ULNG:
res = objc_read_unsigned_int(stream, va_arg(args, unsigned int*)); res = objc_read_unsigned_int(stream, va_arg(args, unsigned int*));
break; break;
case _C_LNG:
res = objc_read_long(stream, va_arg(args, long*));
break;
case _C_ULNG:
res = objc_read_unsigned_long(stream, va_arg(args, unsigned long*));
break;
case _C_CHARPTR: case _C_CHARPTR:
case _C_ATOM: case _C_ATOM:
{ {
...@@ -1209,7 +1305,7 @@ objc_read_types(TypedStream* stream, const char* type, ...) ...@@ -1209,7 +1305,7 @@ objc_read_types(TypedStream* stream, const char* type, ...)
const char* t = c; const char* t = c;
while (isdigit(*++t)); while (isdigit(*++t));
res = objc_read_array (stream, t, len, va_arg(args, void*)); res = objc_read_array (stream, t, len, va_arg(args, void*));
t = __objc_skip_type (t); t = objc_skip_typespec (t);
if (*t != _C_ARY_E) if (*t != _C_ARY_E)
__objc_fatal("expected `]', got: %s", t); __objc_fatal("expected `]', got: %s", t);
} }
...@@ -1331,7 +1427,7 @@ static void __objc_finish_write_root_object(struct objc_typed_stream* stream) ...@@ -1331,7 +1427,7 @@ static void __objc_finish_write_root_object(struct objc_typed_stream* stream)
static void __objc_finish_read_root_object(struct objc_typed_stream* stream) static void __objc_finish_read_root_object(struct objc_typed_stream* stream)
{ {
node_ptr node; node_ptr node;
SEL awake_sel = sel_get_uid ("awake"); SEL awake_sel = sel_get_any_uid ("awake");
/* resolve object forward references */ /* resolve object forward references */
for (node = hash_next (stream->object_refs, NULL); node; for (node = hash_next (stream->object_refs, NULL); node;
...@@ -1379,8 +1475,6 @@ static void __objc_finish_read_root_object(struct objc_typed_stream* stream) ...@@ -1379,8 +1475,6 @@ static void __objc_finish_read_root_object(struct objc_typed_stream* stream)
TypedStream* TypedStream*
objc_open_typed_stream (FILE* physical, int mode) objc_open_typed_stream (FILE* physical, int mode)
{ {
int fflush(FILE*);
TypedStream* s = (TypedStream*)__objc_xmalloc(sizeof(TypedStream)); TypedStream* s = (TypedStream*)__objc_xmalloc(sizeof(TypedStream));
s->mode = mode; s->mode = mode;
...@@ -1483,13 +1577,12 @@ objc_flush_typed_stream (TypedStream* stream) ...@@ -1483,13 +1577,12 @@ objc_flush_typed_stream (TypedStream* stream)
(*stream->flush)(stream->physical); (*stream->flush)(stream->physical);
} }
int long
objc_get_stream_class_version (TypedStream* stream, Class* class) objc_get_stream_class_version (TypedStream* stream, Class* class)
{ {
if (stream->class_table) if (stream->class_table)
return (int) hash_value_for_key (stream->class_table, class->name); return PTR2LONG(hash_value_for_key (stream->class_table, class->name));
else else
return class_get_version (class); return class_get_version (class);
} }
#endif /* __alpha__ */
...@@ -132,6 +132,27 @@ objc_get_class (const char *name) ...@@ -132,6 +132,27 @@ objc_get_class (const char *name)
abort(); abort();
} }
/* This function provides a way to enumerate all the classes in the
executable. Pass *ENUM_STATE == NULL to start the enumeration. The
function will return 0 when there are no more classes.
For example:
id class;
void *es = NULL;
while ((class = objc_next_class(&es)))
... do something with class;
*/
Class*
objc_next_class(void **enum_state)
{
/* make sure the table is there */
assert(__objc_class_hash);
*(node_ptr*)enum_state =
hash_next(__objc_class_hash, *(node_ptr*)enum_state);
if (*(node_ptr*)enum_state)
return (*(node_ptr*)enum_state)->value;
return (Class*)0;
}
/* Resolve super/subclass links for all classes. The only thing we /* Resolve super/subclass links for all classes. The only thing we
can be sure of is that the class_pointer for class objects point can be sure of is that the class_pointer for class objects point
...@@ -217,6 +238,9 @@ void __objc_resolve_class_links() ...@@ -217,6 +238,9 @@ void __objc_resolve_class_links()
Class* Class*
class_pose_as (Class* impostor, Class* super_class) class_pose_as (Class* impostor, Class* super_class)
{ {
node_ptr node;
Class* class1;
if (!CLS_ISRESOLV (impostor)) if (!CLS_ISRESOLV (impostor))
__objc_resolve_class_links (); __objc_resolve_class_links ();
...@@ -230,19 +254,13 @@ class_pose_as (Class* impostor, Class* super_class) ...@@ -230,19 +254,13 @@ class_pose_as (Class* impostor, Class* super_class)
{ {
Class **subclass = &(super_class->subclass_list); Class **subclass = &(super_class->subclass_list);
BOOL super_is_base_class = NO;
/* move subclasses of super_class to impostor */ /* move subclasses of super_class to impostor */
while (*subclass) while (*subclass)
{ {
Class *nextSub = (*subclass)->sibling_class; Class *nextSub = (*subclass)->sibling_class;
/* this happens when super_class is a base class */ if (*subclass != impostor)
if (*subclass == CLASSOF (super_class))
{
super_is_base_class = YES;
}
else if (*subclass != impostor)
{ {
Class *sub = *subclass; Class *sub = *subclass;
...@@ -250,11 +268,18 @@ class_pose_as (Class* impostor, Class* super_class) ...@@ -250,11 +268,18 @@ class_pose_as (Class* impostor, Class* super_class)
sub->sibling_class = impostor->subclass_list; sub->sibling_class = impostor->subclass_list;
sub->super_class = impostor; sub->super_class = impostor;
impostor->subclass_list = sub; impostor->subclass_list = sub;
/* meta classes */ /* It will happen that SUB is not a class object if it is
CLASSOF (sub)->sibling_class = CLASSOF (impostor)->subclass_list; the top of the meta class hierachy chain. (root
CLASSOF (sub)->super_class = CLASSOF (impostor); meta-class objects inherit theit class object) If that is
CLASSOF (impostor)->subclass_list = CLASSOF (sub); the case... dont mess with the meta-meta class. */
if (CLS_ISCLASS (sub))
{
/* meta classes */
CLASSOF (sub)->sibling_class = CLASSOF (impostor)->subclass_list;
CLASSOF (sub)->super_class = CLASSOF (impostor);
CLASSOF (impostor)->subclass_list = CLASSOF (sub);
}
} }
*subclass = nextSub; *subclass = nextSub;
...@@ -267,66 +292,31 @@ class_pose_as (Class* impostor, Class* super_class) ...@@ -267,66 +292,31 @@ class_pose_as (Class* impostor, Class* super_class)
/* set impostor to have no sibling classes */ /* set impostor to have no sibling classes */
impostor->sibling_class = 0; impostor->sibling_class = 0;
CLASSOF (impostor)->sibling_class = 0; CLASSOF (impostor)->sibling_class = 0;
/* impostor has a sibling... */
if (super_is_base_class)
{
CLASSOF (super_class)->sibling_class = 0;
impostor->sibling_class = CLASSOF (super_class);
}
} }
/* check relationship of impostor and super_class */ /* check relationship of impostor and super_class is kept. */
assert (impostor->super_class == super_class); assert (impostor->super_class == super_class);
assert (CLASSOF (impostor)->super_class == CLASSOF (super_class)); assert (CLASSOF (impostor)->super_class == CLASSOF (super_class));
/* by now, the re-organization of the class hierachy /* This is how to update the lookup table. Regardless of
is done. We only need to update various tables. */ what the keys of the hashtable is, change all values that are
suprecalss into impostor. */
/* First, we change the names in the hash table.
This will change the behavior of objc_get_class () */
{
char* buffer = (char*) __objc_xmalloc(strlen (super_class->name) + 2);
strcpy (buffer+1, super_class->name);
buffer[0] = '*';
/* keep on prepending '*' until the name is unique */ for (node = hash_next (__objc_class_hash, NULL); node;
while (hash_value_for_key (__objc_class_hash, buffer)) node = hash_next (__objc_class_hash, node))
{ {
char *bbuffer = (char*) __objc_xmalloc (strlen (buffer)+2); class1 = (Class*)node->value;
if (class1 == super_class)
strcpy (bbuffer+1, buffer); {
bbuffer[0] = '*'; node->value = impostor; /* change hash table value */
free (buffer); }
buffer = bbuffer; }
}
hash_remove (__objc_class_hash, super_class->name);
hash_add (&__objc_class_hash, buffer, super_class);
hash_add (&__objc_class_hash, super_class->name, impostor);
/* Note that -name and +name will still respond with
the same strings as before. This way any
-isKindOfGivenName: will always work. */
}
/* next, we update the dispatch tables... */ /* next, we update the dispatch tables... */
{ __objc_update_dispatch_table_for_class (CLASSOF (impostor));
Class *subclass; __objc_update_dispatch_table_for_class (impostor);
for (subclass = impostor->subclass_list;
subclass; subclass = subclass->sibling_class)
{
/* we use the opportunity to check what we did */
assert (subclass->super_class == impostor);
assert (CLASSOF (subclass)->super_class == CLASSOF (impostor));
__objc_update_dispatch_table_for_class (CLASSOF (subclass));
__objc_update_dispatch_table_for_class (subclass);
}
}
return impostor; return impostor;
} }
...@@ -35,6 +35,10 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ ...@@ -35,6 +35,10 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
({ typeof(X) __x = (X), __y = (Y); \ ({ typeof(X) __x = (X), __y = (Y); \
(__x < __y ? __x : __y); }) (__x < __y ? __x : __y); })
#define ROUND(V, A) \
({ typeof(V) __v=(V); typeof(A) __a=(A); \
__a*((__v+__a-1)/__a); })
static inline int static inline int
atoi (const char* str) atoi (const char* str)
...@@ -121,8 +125,7 @@ objc_sizeof_type(const char* type) ...@@ -121,8 +125,7 @@ objc_sizeof_type(const char* type)
while (*type != _C_STRUCT_E); while (*type != _C_STRUCT_E);
{ {
align = objc_alignof_type (type); /* padd to alignment */ align = objc_alignof_type (type); /* padd to alignment */
if ((acc_size % align) != 0) acc_size += ROUND (acc_size, align);
acc_size += align - (acc_size % align);
acc_size += objc_sizeof_type (type); /* add component size */ acc_size += objc_sizeof_type (type); /* add component size */
type = objc_skip_typespec (type); /* skip component */ type = objc_skip_typespec (type); /* skip component */
} }
...@@ -244,11 +247,7 @@ objc_aligned_size (const char* type) ...@@ -244,11 +247,7 @@ objc_aligned_size (const char* type)
{ {
int size = objc_sizeof_type (type); int size = objc_sizeof_type (type);
int align = objc_alignof_type (type); int align = objc_alignof_type (type);
return ROUND (size, align);
if ((size % align) != 0)
return size + align - (size % align);
else
return size;
} }
/* /*
...@@ -262,10 +261,7 @@ objc_promoted_size (const char* type) ...@@ -262,10 +261,7 @@ objc_promoted_size (const char* type)
int size = objc_sizeof_type (type); int size = objc_sizeof_type (type);
int wordsize = sizeof (void*); int wordsize = sizeof (void*);
if ((size % wordsize) != 0) return ROUND (size, wordsize);
return size + wordsize - (size % wordsize);
else
return size;
} }
/* /*
......
...@@ -39,6 +39,8 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ ...@@ -39,6 +39,8 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#define EXPANSION(cache) \ #define EXPANSION(cache) \
((cache)->size * 2) ((cache)->size * 2)
void *__objc_xcalloc (size_t, size_t);
cache_ptr cache_ptr
hash_new (unsigned int size, hash_func_type hash_func, hash_new (unsigned int size, hash_func_type hash_func,
compare_func_type compare_func) compare_func_type compare_func)
......
...@@ -28,7 +28,7 @@ You should have received a copy of the GNU General Public License along with ...@@ -28,7 +28,7 @@ You should have received a copy of the GNU General Public License along with
/* The version number of this runtime. This must match the number /* The version number of this runtime. This must match the number
defined in gcc (objc-act.c) */ defined in gcc (objc-act.c) */
#define OBJC_VERSION 5 #define OBJC_VERSION 6
#define PROTOCOL_VERSION 2 #define PROTOCOL_VERSION 2
/* This list contains all modules currently loaded into the runtime */ /* This list contains all modules currently loaded into the runtime */
...@@ -49,6 +49,11 @@ static void __objc_class_add_protocols (Class*, struct objc_protocol_list*); ...@@ -49,6 +49,11 @@ static void __objc_class_add_protocols (Class*, struct objc_protocol_list*);
/* Is all categories/classes resolved? */ /* Is all categories/classes resolved? */
BOOL __objc_dangling_categories = NO; BOOL __objc_dangling_categories = NO;
extern SEL
__sel_register_typed_name (const char *name, const char *types,
struct objc_selector *orig);
/* This function is called by constructor functions generated for each /* This function is called by constructor functions generated for each
module compiled. (_GLOBAL_$I$...) The purpose of this function is to module compiled. (_GLOBAL_$I$...) The purpose of this function is to
gather the module pointers so that they may be processed by the gather the module pointers so that they may be processed by the
...@@ -70,7 +75,7 @@ __objc_exec_class (Module_t module) ...@@ -70,7 +75,7 @@ __objc_exec_class (Module_t module)
struct objc_list** cell; struct objc_list** cell;
/* The table of selector references for this module */ /* The table of selector references for this module */
SEL *selectors = symtab->refs; SEL selectors = symtab->refs;
/* dummy counter */ /* dummy counter */
int i; int i;
...@@ -91,6 +96,19 @@ __objc_exec_class (Module_t module) ...@@ -91,6 +96,19 @@ __objc_exec_class (Module_t module)
/* Save the module pointer for later processing. (not currently used) */ /* Save the module pointer for later processing. (not currently used) */
__objc_module_list = list_cons(module, __objc_module_list); __objc_module_list = list_cons(module, __objc_module_list);
/* Replace referenced selectors from names to SEL's. */
if (selectors)
{
for (i = 0; selectors[i].sel_id; ++i)
{
const char *name, *type;
name = (char*)selectors[i].sel_id;
type = (char*)selectors[i].sel_types;
__sel_register_typed_name (name, type,
(struct objc_selector*)&(selectors[i]));
}
}
/* Parse the classes in the load module and gather selector information. */ /* Parse the classes in the load module and gather selector information. */
DEBUG_PRINTF ("gathering selectors from module: %s\n", module->name); DEBUG_PRINTF ("gathering selectors from module: %s\n", module->name);
for (i = 0; i < symtab->cls_def_cnt; ++i) for (i = 0; i < symtab->cls_def_cnt; ++i)
...@@ -117,13 +135,6 @@ __objc_exec_class (Module_t module) ...@@ -117,13 +135,6 @@ __objc_exec_class (Module_t module)
__objc_init_protocols (class->protocols); __objc_init_protocols (class->protocols);
} }
/* Replace referenced selectors from names to SEL's. */
if (selectors)
{
for (i = 0; selectors[i]; ++i)
selectors[i] = sel_register_name ((const char *) selectors[i]);
}
/* Process category information from the module. */ /* Process category information from the module. */
for (i = 0; i < symtab->cat_def_cnt; ++i) for (i = 0; i < symtab->cat_def_cnt; ++i)
{ {
...@@ -166,7 +177,7 @@ __objc_exec_class (Module_t module) ...@@ -166,7 +177,7 @@ __objc_exec_class (Module_t module)
categories to objects. */ categories to objects. */
for (cell = &unclaimed_categories; for (cell = &unclaimed_categories;
*cell; *cell;
*cell && ((cell = &(*cell)->tail))) ({ if (*cell) cell = &(*cell)->tail; }))
{ {
Category_t category = (*cell)->head; Category_t category = (*cell)->head;
Class* class = objc_lookup_class (category->class_name); Class* class = objc_lookup_class (category->class_name);
...@@ -209,7 +220,7 @@ static void init_check_module_version(Module_t module) ...@@ -209,7 +220,7 @@ static void init_check_module_version(Module_t module)
if ((module->version != OBJC_VERSION) || (module->size != sizeof (Module))) if ((module->version != OBJC_VERSION) || (module->size != sizeof (Module)))
{ {
fprintf (stderr, "Module %s version %d doesn't match runtime %d\n", fprintf (stderr, "Module %s version %d doesn't match runtime %d\n",
module->name, module->version, OBJC_VERSION); module->name, (int)module->version, OBJC_VERSION);
if(module->version > OBJC_VERSION) if(module->version > OBJC_VERSION)
fprintf (stderr, "Runtime (libobjc.a) is out of date\n"); fprintf (stderr, "Runtime (libobjc.a) is out of date\n");
else if (module->version < OBJC_VERSION) else if (module->version < OBJC_VERSION)
...@@ -255,7 +266,7 @@ __objc_init_protocols (struct objc_protocol_list* protos) ...@@ -255,7 +266,7 @@ __objc_init_protocols (struct objc_protocol_list* protos)
{ {
fprintf (stderr, fprintf (stderr,
"Version %d doesn't match runtime protocol version %d\n", "Version %d doesn't match runtime protocol version %d\n",
((size_t)protos->list[i]->class_pointer), (int)((char*)protos->list[i]->class_pointer-(char*)0),
PROTOCOL_VERSION); PROTOCOL_VERSION);
abort (); abort ();
} }
......
...@@ -30,6 +30,12 @@ void objc_error(id object, const char* fmt, va_list); ...@@ -30,6 +30,12 @@ void objc_error(id object, const char* fmt, va_list);
void (*_objc_error)(id, const char*, va_list) = objc_error; void (*_objc_error)(id, const char*, va_list) = objc_error;
#ifdef __alpha__
#include <stdlib.h>
extern int write (int, const char*, int);
extern size_t strlen (const char*);
#endif
void void
objc_error(id object, const char* fmt, va_list ap) objc_error(id object, const char* fmt, va_list ap)
{ {
...@@ -40,7 +46,7 @@ objc_error(id object, const char* fmt, va_list ap) ...@@ -40,7 +46,7 @@ objc_error(id object, const char* fmt, va_list ap)
volatile void volatile void
objc_fatal(const char* msg) objc_fatal(const char* msg)
{ {
write(2, msg, (size_t)strlen((char*)msg)); write(2, msg, (int)strlen((const char*)msg));
abort(); abort();
} }
...@@ -65,8 +71,12 @@ __objc_xrealloc(void* mem, size_t size) ...@@ -65,8 +71,12 @@ __objc_xrealloc(void* mem, size_t size)
void* void*
__objc_xcalloc(size_t nelem, size_t size) __objc_xcalloc(size_t nelem, size_t size)
{ {
void* res = (void*)calloc(nelem, size); #ifdef __alpha__
extern bzero (void *, size_t);
#endif
void* res = (void*)malloc(nelem * size);
if(!res) if(!res)
objc_fatal("Virtual memory exhausted\n"); objc_fatal("Virtual memory exhausted\n");
bzero (res, nelem * size);
return res; return res;
} }
...@@ -44,8 +44,6 @@ struct objc_method_description ...@@ -44,8 +44,6 @@ struct objc_method_description
char *types; /* type encoding */ char *types; /* type encoding */
}; };
/* Filer types used to describe Ivars and Methods. */ /* Filer types used to describe Ivars and Methods. */
#define _C_ID '@' #define _C_ID '@'
#define _C_CLASS '#' #define _C_CLASS '#'
...@@ -92,7 +90,7 @@ extern BOOL objc_trace; ...@@ -92,7 +90,7 @@ extern BOOL objc_trace;
*/ */
typedef struct objc_symtab { typedef struct objc_symtab {
unsigned long sel_ref_cnt; /* Unknown. */ unsigned long sel_ref_cnt; /* Unknown. */
SEL *refs; /* Unknown. */ SEL refs; /* Unknown. */
unsigned short cls_def_cnt; /* Number of classes compiled unsigned short cls_def_cnt; /* Number of classes compiled
(defined) in the module. */ (defined) in the module. */
unsigned short cat_def_cnt; /* Number of categories unsigned short cat_def_cnt; /* Number of categories
...@@ -146,7 +144,7 @@ typedef struct objc_ivar_list { ...@@ -146,7 +144,7 @@ typedef struct objc_ivar_list {
const char* ivar_type; /* Description of the Ivar's const char* ivar_type; /* Description of the Ivar's
type. Useful for type. Useful for
debuggers. */ debuggers. */
int ivar_offset; /* Byte offset from the base int ivar_offset; /* Byte offset from the base
address of the instance address of the instance
structure to the variable. */ structure to the variable. */
...@@ -169,7 +167,7 @@ typedef struct objc_method_list { ...@@ -169,7 +167,7 @@ typedef struct objc_method_list {
struct objc_method_list* method_next; /* This variable is used to link struct objc_method_list* method_next; /* This variable is used to link
a method list to another. It a method list to another. It
is a singly linked list. */ is a singly linked list. */
int method_count; /* Number of methods defined in int method_count; /* Number of methods defined in
this structure. */ this structure. */
struct objc_method { struct objc_method {
SEL method_name; /* This variable is the method's SEL method_name; /* This variable is the method's
...@@ -303,12 +301,23 @@ Class* objc_get_class(const char *name); ...@@ -303,12 +301,23 @@ Class* objc_get_class(const char *name);
Class* objc_lookup_class(const char *name); Class* objc_lookup_class(const char *name);
Class* objc_next_class(void **enum_state);
const char *sel_get_name(SEL selector); const char *sel_get_name(SEL selector);
const char *sel_get_type(SEL selector);
SEL sel_get_uid(const char *name); SEL sel_get_uid(const char *name);
SEL sel_get_any_uid(const char *name);
SEL sel_get_typed_uid(const char *name, const char*);
SEL sel_register_name(const char *name); SEL sel_register_name(const char *name);
SEL sel_register_typed_name(const char *name, const char*type);
BOOL sel_is_mapped (SEL aSel); BOOL sel_is_mapped (SEL aSel);
extern id class_create_instance(Class* class); extern id class_create_instance(Class* class);
......
...@@ -40,12 +40,24 @@ typedef char BOOL; ...@@ -40,12 +40,24 @@ typedef char BOOL;
#define NO (BOOL)0 #define NO (BOOL)0
/* /*
** Definition of a selector. Selectors are really of type unsigned int. ** Definition of a selector. Selectors themselves are not unique, but
** The runtime does this mapping from SEL's to names internally in the ** the sel_id is a unique identifier.
** sel_... operations. You should never use the fact that it is actually
** an integer, since other Objective-C implementations use other conventions.
*/ */
typedef void* SEL; typedef const struct objc_selector
{
void *sel_id;
const char *sel_types;
} *SEL;
inline static BOOL
sel_eq (SEL s1, SEL s2)
{
if (s1 == 0 || s2 == 0)
return s1 == s2;
else
return s1->sel_id == s2->sel_id;
}
/* /*
** ObjC uses this typedef for untyped instances. ** ObjC uses this typedef for untyped instances.
...@@ -131,36 +143,8 @@ typedef union { ...@@ -131,36 +143,8 @@ typedef union {
} *arglist_t; /* argument frame */ } *arglist_t; /* argument frame */
#if defined(__OBJC__)
#include "objc/sarray.h"
/*
This is the function called when messages are send to nil. You may
set a breakpoint in your debugger at this function to catch messages
too nil.
*/
extern id nil_method(id rcv, SEL op, ...);
/*
The messager is inlined, thus it is defined here directly. The
inlining is quite time-consuming when optimizing. This will be
taken care of later by hand-coding the messager in the compiler.
*/
extern __inline__ IMP
objc_msg_lookup(id receiver, SEL op)
{
if(receiver)
return sarray_get(receiver->class_pointer->dtable, (size_t)(op));
else
return nil_method;
}
#else
IMP objc_msg_lookup(id receiver, SEL op); IMP objc_msg_lookup(id receiver, SEL op);
#endif
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
......
...@@ -43,7 +43,7 @@ class_create_instance(Class* class) ...@@ -43,7 +43,7 @@ class_create_instance(Class* class)
new = (*_objc_object_alloc)(class); new = (*_objc_object_alloc)(class);
if (new!=nil) if (new!=nil)
{ {
bzero (new, class->instance_size); memchr (new, 0, class->instance_size);
new->class_pointer = class; new->class_pointer = class;
} }
return new; return new;
......
...@@ -61,12 +61,14 @@ extern BOOL __objc_class_links_resolved; ...@@ -61,12 +61,14 @@ extern BOOL __objc_class_links_resolved;
extern int __objc_selector_max_index; extern int __objc_selector_max_index;
#ifdef DEBUG #ifdef DEBUG
#define DEBUG_PRINTF printf #define DEBUG_PRINTF(format, args...) printf (format, ## args)
#else #else
#define DEBUG_PRINTF #define DEBUG_PRINTF(format, args...)
#endif #endif
BOOL __objc_responds_to (id object, SEL sel); /* for internal use only! */ BOOL __objc_responds_to (id object, SEL sel); /* for internal use only! */
SEL __sel_register_typed_name (const char*, const char*,
struct objc_selector*);
#endif /* not __objc_runtime_INCLUDE_GNU */ #endif /* not __objc_runtime_INCLUDE_GNU */
......
...@@ -40,6 +40,11 @@ const char* __objc_sparse2_id = "2 level sparse indices"; ...@@ -40,6 +40,11 @@ const char* __objc_sparse2_id = "2 level sparse indices";
const char* __objc_sparse3_id = "3 level sparse indices"; const char* __objc_sparse3_id = "3 level sparse indices";
#endif #endif
#ifdef __alpha__
const void *memcpy (void*, const void*, size_t);
void free (const void*);
#endif
void void
sarray_at_put(struct sarray* array, sidx index, void* element) sarray_at_put(struct sarray* array, sidx index, void* element)
{ {
...@@ -117,7 +122,7 @@ sarray_at_put(struct sarray* array, sidx index, void* element) ...@@ -117,7 +122,7 @@ sarray_at_put(struct sarray* array, sidx index, void* element)
/* The bucket was previously empty (or something like that), */ /* The bucket was previously empty (or something like that), */
/* allocate a new. This is the effect of `lazy' allocation */ /* allocate a new. This is the effect of `lazy' allocation */
*the_bucket = (struct sbucket*)__objc_xmalloc(sizeof(struct sbucket)); *the_bucket = (struct sbucket*)__objc_xmalloc(sizeof(struct sbucket));
memcpy( *the_bucket,array->empty_bucket, sizeof(struct sbucket)); memcpy((void *) *the_bucket, (const void*)array->empty_bucket, sizeof(struct sbucket));
(*the_bucket)->version = array->version; (*the_bucket)->version = array->version;
nbuckets += 1; nbuckets += 1;
......
...@@ -31,7 +31,8 @@ You should have received a copy of the GNU General Public License along with ...@@ -31,7 +31,8 @@ You should have received a copy of the GNU General Public License along with
#define SELECTOR_HASH_SIZE 128 #define SELECTOR_HASH_SIZE 128
/* Tables mapping selector names to uid and opposite */ /* Tables mapping selector names to uid and opposite */
static struct sarray* __objc_selector_array = 0; /* uid -> name */ static struct sarray* __objc_selector_array = 0; /* uid -> sel */
static struct sarray* __objc_selector_names = 0; /* uid -> name */
static cache_ptr __objc_selector_hash = 0; /* name -> uid */ static cache_ptr __objc_selector_hash = 0; /* name -> uid */
static void register_selectors_from_list(MethodList_t); static void register_selectors_from_list(MethodList_t);
...@@ -42,6 +43,7 @@ int __objc_selector_max_index = 0; ...@@ -42,6 +43,7 @@ int __objc_selector_max_index = 0;
void __objc_init_selector_tables() void __objc_init_selector_tables()
{ {
__objc_selector_array = sarray_new (SELECTOR_HASH_SIZE, 0); __objc_selector_array = sarray_new (SELECTOR_HASH_SIZE, 0);
__objc_selector_names = sarray_new (SELECTOR_HASH_SIZE, 0);
__objc_selector_hash __objc_selector_hash
= hash_new (SELECTOR_HASH_SIZE, = hash_new (SELECTOR_HASH_SIZE,
(hash_func_type) hash_string, (hash_func_type) hash_string,
...@@ -78,16 +80,67 @@ register_selectors_from_list (MethodList_t method_list) ...@@ -78,16 +80,67 @@ register_selectors_from_list (MethodList_t method_list)
while (i < method_list->method_count) while (i < method_list->method_count)
{ {
Method_t method = &method_list->method_list[i]; Method_t method = &method_list->method_list[i];
method->method_name = sel_register_name ((char*)method->method_name); method->method_name
= sel_register_typed_name ((const char*)method->method_name,
method->method_types);
i += 1; i += 1;
} }
} }
/* return selector representing name */ /* return selector representing name */
SEL SEL
sel_get_typed_uid (const char *name, const char *types)
{
struct objc_list *l;
sidx i;
i = (sidx) hash_value_for_key (__objc_selector_hash, name);
if (i == 0)
return 0;
for (l = (struct objc_list*)sarray_get (__objc_selector_array, i);
l; l = l->tail)
{
SEL s = (SEL)l->head;
if (types == 0 || s->sel_types == 0)
{
if (s->sel_types == types)
{
return s;
}
}
else if (! strcmp (s->sel_types, types))
{
return s;
}
}
return 0;
}
/* return selector representing name */
SEL
sel_get_any_uid (const char *name)
{
struct objc_list *l;
sidx i;
i = (sidx) hash_value_for_key (__objc_selector_hash, name);
if (soffset_decode (i) == 0)
return 0;
l = (struct objc_list*)sarray_get (__objc_selector_array, i);
if (l == 0)
return 0;
return (SEL)l->head;
}
/* return selector representing name */
SEL
sel_get_uid (const char *name) sel_get_uid (const char *name)
{ {
return (SEL) hash_value_for_key (__objc_selector_hash, name); return sel_register_typed_name (name, 0);
} }
/* Get name of selector. If selector is unknown, the empty string "" /* Get name of selector. If selector is unknown, the empty string ""
...@@ -95,45 +148,123 @@ sel_get_uid (const char *name) ...@@ -95,45 +148,123 @@ sel_get_uid (const char *name)
const char* const char*
sel_get_name (SEL selector) sel_get_name (SEL selector)
{ {
if ((soffset_decode((sidx)selector) > 0) if ((soffset_decode((sidx)selector->sel_id) > 0)
&& (soffset_decode((sidx)selector) <= __objc_selector_max_index)) && (soffset_decode((sidx)selector->sel_id) <= __objc_selector_max_index))
return sarray_get (__objc_selector_array, (sidx) selector); return sarray_get (__objc_selector_array, (sidx) selector->sel_id);
else else
return NULL; return 0;
} }
BOOL BOOL
sel_is_mapped (SEL selector) sel_is_mapped (SEL selector)
{ {
unsigned int idx = soffset_decode ((sidx)selector); unsigned int idx = soffset_decode ((sidx)selector->sel_id);
return ((idx > 0) && (idx <= __objc_selector_max_index)); return ((idx > 0) && (idx <= __objc_selector_max_index));
} }
const char*
sel_get_type (SEL selector)
{
if (selector)
return selector->sel_types;
else
return 0;
}
/* The uninstalled dispatch table */ /* The uninstalled dispatch table */
extern struct sarray* __objc_uninstalled_dtable; extern struct sarray* __objc_uninstalled_dtable;
/* Store the passed selector name in the selector record and return its /* Store the passed selector name in the selector record and return its
selector value (value returned by sel_get_uid). */ selector value (value returned by sel_get_uid). */
SEL SEL
sel_register_name (const char *sel) __sel_register_typed_name (const char *name, const char *types,
struct objc_selector *orig)
{ {
SEL j; struct objc_selector* j;
sidx i; sidx i;
struct objc_list *l;
if ((j = sel_get_uid ((const char *) sel))) i = (sidx) hash_value_for_key (__objc_selector_hash, name);
return j; if (soffset_decode (i) != 0)
{
/* Save the selector name. */ for (l = (struct objc_list*)sarray_get (__objc_selector_array, i);
__objc_selector_max_index += 1; l; l = l->tail)
i = soffset_encode(__objc_selector_max_index); {
SEL s = (SEL)l->head;
if (types == 0 || s->sel_types == 0)
{
if (s->sel_types == types)
{
if (orig)
{
orig->sel_id = (void*)i;
return orig;
}
else
return s;
}
}
else if (strcmp (s->sel_types, types))
{
if (orig)
{
orig->sel_id = (void*)i;
return orig;
}
else
return s;
}
}
if (orig)
j = orig;
else
j = __objc_xmalloc (sizeof (struct objc_selector));
DEBUG_PRINTF ("Record selector %s as: %#x\n", sel, i); j->sel_id = (void*)i;
j->sel_types = (const char*)types;
l = (struct objc_list*)sarray_get (__objc_selector_array, i);
}
else
{
__objc_selector_max_index += 1;
i = soffset_encode(__objc_selector_max_index);
if (orig)
j = orig;
else
j = __objc_xmalloc (sizeof (struct objc_selector));
j->sel_id = (void*)i;
j->sel_types = (const char*)types;
l = 0;
}
sarray_at_put_safe (__objc_selector_array, i, (void *) sel); DEBUG_PRINTF ("Record selector %s[%s] as: %ld\n", name, types,
hash_add (&__objc_selector_hash, (void *) sel, (void *) i); soffset_decode (i));
{
int is_new = (l == 0);
l = list_cons ((void*)j, l);
sarray_at_put_safe (__objc_selector_names, i, (void *) name);
sarray_at_put_safe (__objc_selector_array, i, (void *) l);
if (is_new)
hash_add (&__objc_selector_hash, (void *) name, (void *) i);
}
sarray_realloc(__objc_uninstalled_dtable, __objc_selector_max_index+1); sarray_realloc(__objc_uninstalled_dtable, __objc_selector_max_index+1);
return (SEL) i; return (SEL) j;
}
SEL
sel_register_name (const char *name)
{
return __sel_register_typed_name (name, 0, 0);
}
SEL
sel_register_typed_name (const char *name, const char *type)
{
return __sel_register_typed_name (name, type, 0);
} }
...@@ -24,10 +24,21 @@ You should have received a copy of the GNU General Public License along with ...@@ -24,10 +24,21 @@ You should have received a copy of the GNU General Public License along with
however invalidate any other reasons why the executable file might be however invalidate any other reasons why the executable file might be
covered by the GNU General Public License. */ covered by the GNU General Public License. */
#include "../tconfig.h"
#include "runtime.h" #include "runtime.h"
#include "sarray.h" #include "sarray.h"
#include "encoding.h" #include "encoding.h"
/* this is how we hack STRUCT_VALUE to be 1 or 0 */
#define gen_rtx(args...) 1
#define rtx int
#if STRUCT_VALUE == 0
#define INVISIBLE_STRUCT_RETURN 1
#else
#define INVISIBLE_STRUCT_RETURN 0
#endif
/* The uninstalled dispatch table */ /* The uninstalled dispatch table */
struct sarray* __objc_uninstalled_dtable = 0; struct sarray* __objc_uninstalled_dtable = 0;
...@@ -38,7 +49,14 @@ static void __objc_install_dispatch_table_for_class (Class*); ...@@ -38,7 +49,14 @@ 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);
static id __objc_missing_method(id, SEL, ...); static id __objc_word_forward(id, SEL, ...);
typedef struct { id many[8]; } __big;
#if INVISIBLE_STRUCT_RETURN
static __big
#else
static id
#endif
__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);
static Method_t search_for_method_in_list(MethodList_t list, SEL op); static Method_t search_for_method_in_list(MethodList_t list, SEL op);
id nil_method(id, SEL, ...); id nil_method(id, SEL, ...);
...@@ -53,16 +71,34 @@ nil_method(id receiver, SEL op, ...) ...@@ -53,16 +71,34 @@ nil_method(id receiver, SEL op, ...)
__inline__ IMP __inline__ IMP
get_imp (Class* class, SEL sel) get_imp (Class* class, SEL sel)
{ {
void* res = sarray_get (class->dtable, (size_t) sel); IMP impl;
void* res = sarray_get (class->dtable, (size_t) sel->sel_id);
if(res == __objc_init_install_dtable) if(res == __objc_init_install_dtable)
__objc_install_dispatch_table_for_class (class); {
return sarray_get (class->dtable, (size_t) sel); __objc_install_dispatch_table_for_class (class);
res = sarray_get (class->dtable, (size_t) sel->sel_id);
}
if (res == 0)
{
const char *t = sel->sel_types;
if (t && (*t == '[' || *t == '(' || *t == '{'))
res = (IMP)__objc_block_forward;
else
res = (IMP)__objc_word_forward;
}
return res;
} }
__inline__ BOOL __inline__ BOOL
__objc_responds_to (id object, SEL sel) __objc_responds_to (id object, SEL sel)
{ {
return get_imp (object->class_pointer, sel) != __objc_missing_method; void* res = sarray_get (object->class_pointer->dtable, (size_t) sel->sel_id);
if(res == __objc_init_install_dtable)
{
__objc_install_dispatch_table_for_class (object->class_pointer);
res = sarray_get (object->class_pointer->dtable, (size_t) sel->sel_id);
}
return (res != 0);
} }
/* This is the lookup function. All entries in the table are either a /* This is the lookup function. All entries in the table are either a
...@@ -72,8 +108,20 @@ __objc_responds_to (id object, SEL sel) ...@@ -72,8 +108,20 @@ __objc_responds_to (id object, SEL sel)
__inline__ IMP __inline__ IMP
objc_msg_lookup(id receiver, SEL op) objc_msg_lookup(id receiver, SEL op)
{ {
IMP result;
if(receiver) if(receiver)
return sarray_get(receiver->class_pointer->dtable, (sidx)op); {
result = sarray_get(receiver->class_pointer->dtable, (sidx)op->sel_id);
if (result == 0)
{
const char *t = op->sel_types;
if (t && (*t == '[' || *t == '(' || *t == '{'))
result = (IMP)__objc_block_forward;
else
result = (IMP)__objc_word_forward;
}
return result;
}
else else
return nil_method; return nil_method;
} }
...@@ -87,6 +135,8 @@ objc_msg_lookup_super (Super_t super, SEL sel) ...@@ -87,6 +135,8 @@ objc_msg_lookup_super (Super_t super, SEL sel)
return nil_method; return nil_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)
{ {
...@@ -141,8 +191,8 @@ static void __objc_init_install_dtable(id receiver, SEL op) ...@@ -141,8 +191,8 @@ static void __objc_init_install_dtable(id receiver, SEL op)
/* 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);
if(op != sel_get_uid ("initialize")) if (strcmp (sel_get_name (op), "initialize"))
__objc_send_initialize((Class*)receiver); __objc_send_initialize((Class*)receiver);
else else
CLS_SETINITIALIZED((Class*)receiver); CLS_SETINITIALIZED((Class*)receiver);
...@@ -155,7 +205,10 @@ allready_initialized: ...@@ -155,7 +205,10 @@ allready_initialized:
args = __builtin_apply_args(); args = __builtin_apply_args();
result = __builtin_apply((apply_t)imp, args, 96); result = __builtin_apply((apply_t)imp, args, 96);
__builtin_return (result); if (result)
__builtin_return (result);
else
return;
} }
...@@ -170,8 +223,6 @@ void __objc_install_premature_dtable(Class* class) ...@@ -170,8 +223,6 @@ void __objc_install_premature_dtable(Class* class)
/* Send +initialize to class if not already done */ /* Send +initialize to class if not already done */
static void __objc_send_initialize(Class* class) static void __objc_send_initialize(Class* class)
{ {
Method_t m;
/* 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));
...@@ -199,7 +250,7 @@ static void __objc_send_initialize(Class* class) ...@@ -199,7 +250,7 @@ static void __objc_send_initialize(Class* class)
Method_t method = &method_list->method_list[i]; Method_t method = &method_list->method_list[i];
if (method->method_name == op) if (method->method_name->sel_id == op->sel_id)
(*method->method_imp)((id) class, op); (*method->method_imp)((id) class, op);
} }
...@@ -231,8 +282,7 @@ __objc_install_dispatch_table_for_class (Class* class) ...@@ -231,8 +282,7 @@ __objc_install_dispatch_table_for_class (Class* class)
/* Allocate dtable if nessecary */ /* Allocate dtable if nessecary */
if (super == 0) if (super == 0)
{ {
class->dtable = sarray_new (__objc_selector_max_index, class->dtable = sarray_new (__objc_selector_max_index, 0);
__objc_missing_method);
} }
else else
class->dtable = sarray_lazy_copy (super->dtable); class->dtable = sarray_lazy_copy (super->dtable);
...@@ -244,7 +294,7 @@ __objc_install_dispatch_table_for_class (Class* class) ...@@ -244,7 +294,7 @@ __objc_install_dispatch_table_for_class (Class* class)
{ {
Method_t method = &(mlist->method_list[counter]); Method_t method = &(mlist->method_list[counter]);
sarray_at_put_safe (class->dtable, sarray_at_put_safe (class->dtable,
(sidx) method->method_name, (sidx) method->method_name->sel_id,
method->method_imp); method->method_imp);
counter -= 1; counter -= 1;
} }
...@@ -254,7 +304,6 @@ __objc_install_dispatch_table_for_class (Class* class) ...@@ -254,7 +304,6 @@ __objc_install_dispatch_table_for_class (Class* class)
void __objc_update_dispatch_table_for_class (Class* class) void __objc_update_dispatch_table_for_class (Class* class)
{ {
Class* next; Class* next;
struct sarray* save;
/* not yet installed -- skip it */ /* not yet installed -- skip it */
if (class->dtable == __objc_uninstalled_dtable) if (class->dtable == __objc_uninstalled_dtable)
...@@ -297,10 +346,12 @@ class_add_method_list (Class* class, MethodList_t list) ...@@ -297,10 +346,12 @@ class_add_method_list (Class* class, MethodList_t list)
if (method->method_name) /* Sometimes these are NULL */ if (method->method_name) /* Sometimes these are NULL */
{ {
/* This is where selector names are transmogriffed to SEL's */ /* This is where selector names are transmogriffed to SEL's */
method->method_name = sel_register_name ((char*)method->method_name); method->method_name =
sel_register_typed_name ((const char*)method->method_name,
method->method_types);
if (search_for_method_in_list (class->methods, method->method_name) if (search_for_method_in_list (class->methods, method->method_name)
&& method->method_name != initialize_sel) && method->method_name->sel_id != initialize_sel->sel_id)
{ {
/* Duplication. Print a error message an change the method name /* Duplication. Print a error message an change the method name
to NULL. */ to NULL. */
...@@ -375,7 +426,7 @@ search_for_method_in_list (MethodList_t list, SEL op) ...@@ -375,7 +426,7 @@ search_for_method_in_list (MethodList_t list, SEL op)
Method_t method = &method_list->method_list[i]; Method_t method = &method_list->method_list[i];
if (method->method_name) if (method->method_name)
if (method->method_name == op) if (method->method_name->sel_id == op->sel_id)
return method; return method;
} }
...@@ -387,40 +438,71 @@ search_for_method_in_list (MethodList_t list, SEL op) ...@@ -387,40 +438,71 @@ search_for_method_in_list (MethodList_t list, SEL op)
return NULL; return NULL;
} }
static retval_t __objc_forward (id object, SEL sel, arglist_t args);
static id
__objc_word_forward (id rcv, SEL op, ...)
{
void *args, *res;
args = __builtin_apply_args ();
res = __objc_forward (rcv, op, args);
if (res)
__builtin_return (res);
else
return res;
}
#if INVISIBLE_STRUCT_RETURN
static __big
#else
static id
#endif
__objc_block_forward (id rcv, SEL op, ...)
{
void *args, *res;
args = __builtin_apply_args ();
res = __objc_forward (rcv, op, args);
if (res)
__builtin_return (res);
}
/* This fuction is installed in the dispatch table for all methods which are /* This fuction is installed in the dispatch table for all methods which are
not implemented. Thus, it is called when a selector is not recognized. */ not implemented. Thus, it is called when a selector is not recognized. */
static id static retval_t
__objc_missing_method (id object, SEL sel, ...) __objc_forward (id object, SEL sel, arglist_t args)
{ {
IMP imp; IMP imp;
SEL frwd_sel; static SEL frwd_sel = 0;
SEL err_sel; SEL err_sel;
/* first try if the object understands forward:: */ /* first try if the object understands forward:: */
frwd_sel = sel_get_uid("forward::"); if (!frwd_sel)
imp = get_imp(object->class_pointer, frwd_sel); frwd_sel = sel_get_any_uid("forward::");
if(imp != __objc_missing_method)
if (__objc_responds_to (object, frwd_sel))
{ {
void *result, *args = __builtin_apply_args(); imp = get_imp(object->class_pointer, frwd_sel);
result = (*imp)(object, frwd_sel, sel, args); return (*imp)(object, frwd_sel, sel, args);
__builtin_return(result);
} }
/* If the object recognizes the doesNotRecognize: method then we're going /* If the object recognizes the doesNotRecognize: method then we're going
to send it. */ to send it. */
err_sel = sel_get_uid ("doesNotRecognize:"); err_sel = sel_get_any_uid ("doesNotRecognize:");
imp = get_imp (object->class_pointer, err_sel); if (__objc_responds_to (object, err_sel))
if (imp != __objc_missing_method)
{ {
imp = get_imp (object->class_pointer, err_sel);
return (*imp) (object, err_sel, sel); return (*imp) (object, err_sel, sel);
} }
/* 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 ((char*)sel_get_name (sel)) size_t strlen (const char*);
+ strlen ((char*)object->class_pointer->name)]; char msg[256 + strlen ((const char*)sel_get_name (sel))
+ 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)
...@@ -428,10 +510,12 @@ __objc_missing_method (id object, SEL sel, ...) ...@@ -428,10 +510,12 @@ __objc_missing_method (id object, SEL sel, ...)
: "instance" ), : "instance" ),
object->class_pointer->name, sel_get_name (sel)); object->class_pointer->name, sel_get_name (sel));
err_sel = sel_get_uid ("error:"); err_sel = sel_get_any_uid ("error:");
imp = get_imp (object->class_pointer, err_sel); if (__objc_responds_to (object, err_sel))
if (imp != __objc_missing_method) {
return (*imp) (object, sel_get_uid ("error:"), msg); imp = get_imp (object->class_pointer, err_sel);
return (*imp) (object, sel_get_any_uid ("error:"), msg);
}
/* The object doesn't respond to doesNotRecognize: or error:; Therefore, /* The object doesn't respond to doesNotRecognize: or error:; Therefore,
a default action is taken. */ a default action is taken. */
...@@ -451,12 +535,12 @@ void __objc_print_dtable_stats() ...@@ -451,12 +535,12 @@ void __objc_print_dtable_stats()
#endif #endif
); );
printf("arrays: %d = %d bytes\n", narrays, narrays*sizeof(struct sarray)); printf("arrays: %d = %ld bytes\n", narrays, (int)narrays*sizeof(struct sarray));
total += narrays*sizeof(struct sarray); total += narrays*sizeof(struct sarray);
printf("buckets: %d = %d bytes\n", nbuckets, nbuckets*sizeof(struct sbucket)); printf("buckets: %d = %ld bytes\n", nbuckets, (int)nbuckets*sizeof(struct sbucket));
total += nbuckets*sizeof(struct sbucket); total += nbuckets*sizeof(struct sbucket);
printf("idxtables: %d = %d bytes\n", idxsize, idxsize*sizeof(void*)); printf("idxtables: %d = %ld bytes\n", idxsize, (int)idxsize*sizeof(void*));
total += idxsize*sizeof(void*); total += idxsize*sizeof(void*);
printf("-----------------------------------\n"); printf("-----------------------------------\n");
printf("total: %d bytes\n", total); printf("total: %d bytes\n", total);
......
...@@ -30,8 +30,6 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ ...@@ -30,8 +30,6 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "objc/hash.h" #include "objc/hash.h"
#include <stdio.h> #include <stdio.h>
#ifndef __alpha__ /* alpha is currently not supported */
typedef int (*objc_typed_read_func)(void*, char*, int); typedef int (*objc_typed_read_func)(void*, char*, int);
typedef int (*objc_typed_write_func)(void*, const char*, int); typedef int (*objc_typed_write_func)(void*, const char*, int);
typedef int (*objc_typed_flush_func)(void*); typedef int (*objc_typed_flush_func)(void*);
...@@ -100,7 +98,7 @@ int objc_read_types (TypedStream* stream, const char* type, ...); ...@@ -100,7 +98,7 @@ int objc_read_types (TypedStream* stream, const char* type, ...);
int objc_write_object_reference (TypedStream* stream, id object); int objc_write_object_reference (TypedStream* stream, id object);
int objc_write_root_object (TypedStream* stream, id object); int objc_write_root_object (TypedStream* stream, id object);
int objc_get_stream_class_version (TypedStream* stream, Class* class); long objc_get_stream_class_version (TypedStream* stream, Class* class);
/* /*
...@@ -130,6 +128,4 @@ void objc_close_typed_stream (TypedStream* stream); ...@@ -130,6 +128,4 @@ void objc_close_typed_stream (TypedStream* stream);
BOOL objc_end_of_typed_stream (TypedStream* stream); BOOL objc_end_of_typed_stream (TypedStream* stream);
void objc_flush_typed_stream (TypedStream* stream); void objc_flush_typed_stream (TypedStream* stream);
#endif /* __alpha__ */
#endif /* not __typedstream_INCLUDE_GNU */ #endif /* not __typedstream_INCLUDE_GNU */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment