-c $(GCC_CFLAGS) $(SUBDIR_INCLUDES) $<
.m.o:
- $(GCC_FOR_TARGET) $(OPTIMIZE) -fgnu-runtime \
+ $(GCC_FOR_TARGET) $(OPTIMIZE) -fgnu-runtime \
-c $(GCC_CFLAGS) $(SUBDIR_INCLUDES) $<
# If we were not invoked from the parent dir,
# ranlib is run in the parent directory's makefile.
OBJC_H = hash.h list.h sarray.h objc.h \
- objc-api.h cache.h \
- Object.h Protocol.h mutex.h
+ objc-api.h \
+ Object.h Protocol.h mutex.h \
+ typedstream.h
# copy objc headers to installation include directory
-copy-headers: $(OBJC_H)
+copy-headers:
-rm -fr $(incinstalldir)/objc
-mkdir $(incinstalldir)/objc
for file in $(OBJC_H); do \
done
sendmsg.o: sendmsg.c fflags
- $(GCC_FOR_TARGET) `cat fflags` -c $(GCC_CFLAGS) $(SUBDIR_INCLUDES) $(srcdir)/objc/sendmsg.c
+ $(GCC_FOR_TARGET) `cat fflags` -c $(GCC_CFLAGS) $(SUBDIR_INCLUDES) $(srcdir)/objc/sendmsg.c
## Next to are for heuristics on forwarding mechanism...
xforward: xforward.c
#ifndef __object_INCLUDE_GNU
#define __object_INCLUDE_GNU
-#ifndef __objc_INCLUDE_GNU
-
-/* This is the minimal set of definitions, which may be sufficient
- for simple programs not interacting heavily with the runtime */
-
-typedef char BOOL;
-#define YES (BOOL)1
-#define NO (BOOL)0
-
-typedef void* SEL;
-
-typedef struct objc_object {
- struct objc_class* class_pointer;
-} *id;
-
-typedef id (*IMP)(id, SEL, ...);
-
-typedef struct objc_class Class;
-typedef struct objc_class MetaClass;
-
-#define nil (id)0 /* id of Nil instance */
-#define Nil (Class*)0 /* id of Nil class */
-typedef char *STR; /* String alias */
-
-@class Protocol;
-typedef struct objc_typed_stream TypedStream;
-typedef void* arglist_t;
-
-#endif /* not __objc_INCLUDE_GNU */
+#include <objc/objc.h>
+#include <objc/typedstream.h>
/*
* All classes are derived from Object. As such,
}
}
- return NO;
+ if ([self superClass])
+ return [[self superClass] conformsTo: aProtocol];
+ else
+ return NO;
}
- (IMP)methodFor:(SEL)aSel
#ifndef __alpha__
#include "runtime.h"
+#include "typedstream.h"
#define __objc_fatal(format, args...) \
{ fprintf(stderr, "archining: "); \
case _B_SSTR:
{
int length = buf[0]&_B_VALUE;
- (*string) = (char*)malloc(length+1);
+ (*string) = (char*)__objc_xmalloc(length+1);
if (key)
hash_add (&stream->stream_table, (void*)key, *string);
len = (*stream->read)(stream->physical, *string, length);
unsigned int nbytes = buf[0]&_B_VALUE;
len = __objc_read_nbyte_uint(stream, nbytes, &nbytes);
if (len) {
- (*string) = (char*)malloc(nbytes);
+ (*string) = (char*)__objc_xmalloc(nbytes);
if (key)
hash_add (&stream->stream_table, (void*)key, *string);
len = (*stream->read)(stream->physical, *string, buf[0]&_B_VALUE);
{
int fflush(FILE*);
- TypedStream* s = (TypedStream*)malloc(sizeof(TypedStream));
+ TypedStream* s = (TypedStream*)__objc_xmalloc(sizeof(TypedStream));
s->mode = mode;
s->physical = physical;
new_class->instance_size = super_class->instance_size;
new_class->ivars = super_class->ivars;
new_class->methods = impostor->methods;
-#ifdef OBJC_SPARSE_LOOKUP
new_class->dtable = impostor->dtable;
-#else
- new_class->cache = impostor->cache;
-#endif
/* Create the impostor meta class. */
new_meta_class->class_pointer = super_class->class_pointer->class_pointer;
new_meta_class->instance_size = super_class->class_pointer->instance_size;
new_meta_class->ivars = super_class->class_pointer->ivars;
new_meta_class->methods = impostor->class_pointer->methods;
-#ifdef OBJC_SPARSE_LOOKUP
new_meta_class->dtable = impostor->class_pointer->dtable;
-#else
- new_meta_class->cache = impostor->class_pointer->cache;
-#endif
/* Now change super/subclass links of all related classes. This is rather
complex, since we have both super_class link, and subclass_list for the
return new_class;
}
-#ifdef OBJC_HASH_LOOKUP
-__objc_class_hash_tables_size ()
-{
- node_ptr node;
- Class* class1;
- int total = 0;
-
- for (node = hash_next (__objc_class_hash, NULL); node;
- node = hash_next (__objc_class_hash, node))
- {
- Class* class1 = node->value;
- total += (class1->cache->mask)*sizeof(struct objc_bucket);
- total += sizeof(struct objc_cache);
- }
-
- return total;
-}
-#endif
#ifndef __hash_INCLUDE_GNU
#define __hash_INCLUDE_GNU
-#ifdef IN_GCC
-#include "gstddef.h"
-#else
#include <stddef.h>
-#endif
/*
* This data structure is used to hold items
void objc_error(id object, const char* fmt, va_list);
void (*_objc_error)(id, const char*, va_list) = objc_error;
-/* id (*_objc_object_alloc)(Class*) = 0; */
-/* id (*_objc_object_dispose)(id) = 0; */
-/* id (*_objc_object_copy)(id) = 0; */
void
objc_error(id object, const char* fmt, va_list ap)
#include "objc/hash.h"
#include <stdio.h>
+/* For functions which return Method_t */
+#define METHOD_NULL (Method_t)0
+ /* Boolean typedefs */
+/*
+** Method descriptor returned by introspective Object methods.
+** This is really just the first part of the more complete objc_method
+** structure defined below and used internally by the runtime.
+*/
+struct objc_method_description
+{
+ SEL name; /* this is a selector, not a string */
+ char *types; /* type encoding */
+};
+
+
+
+/* Filer types used to describe Ivars and Methods. */
+#define _C_ID '@'
+#define _C_CLASS '#'
+#define _C_SEL ':'
+#define _C_CHR 'c'
+#define _C_UCHR 'C'
+#define _C_SHT 's'
+#define _C_USHT 'S'
+#define _C_INT 'i'
+#define _C_UINT 'I'
+#define _C_LNG 'l'
+#define _C_ULNG 'L'
+#define _C_FLT 'f'
+#define _C_DBL 'd'
+#define _C_BFLD 'b'
+#define _C_VOID 'v'
+#define _C_UNDEF '?'
+#define _C_PTR '^'
+#define _C_CHARPTR '*'
+#define _C_ATOM '%'
+#define _C_ARY_B '['
+#define _C_ARY_E ']'
+#define _C_UNION_B '('
+#define _C_UNION_E ')'
+#define _C_STRUCT_B '{'
+#define _C_STRUCT_E '}'
+
+
+
+/*
+** Set this variable nonzero to print a line describing each
+** message that is sent. (this is currently disabled)
+*/
+extern BOOL objc_trace;
+
+
+/*
+** Whereas a Module (defined further down) is the root (typically) of a file,
+** a Symtab is the root of the class and category definitions within the
+** module.
+**
+** A Symtab contains a variable length array of pointers to classes and
+** categories defined in the module.
+*/
+typedef struct objc_symtab {
+ unsigned long sel_ref_cnt; /* Unknown. */
+ SEL *refs; /* Unknown. */
+ unsigned short cls_def_cnt; /* Number of classes compiled
+ (defined) in the module. */
+ unsigned short cat_def_cnt; /* Number of categories
+ compiled (defined) in the
+ module. */
+ void *defs[1]; /* Variable array of pointers.
+ cls_def_cnt of type Class*
+ followed by cat_def_cnt of
+ type Category_t. */
+} Symtab, *Symtab_t;
+
+
+/*
+** The compiler generates one of these structures for each module that
+** composes the executable (eg main.m).
+**
+** This data structure is the root of the definition tree for the module.
+**
+** A collect program runs between ld stages and creates a ObjC ctor array.
+** That array holds a pointer to each module structure of the executable.
+*/
+typedef struct objc_module {
+ unsigned long version; /* Compiler revision. */
+ unsigned long size; /* sizeof(Module). */
+ const char* name; /* Name of the file where the
+ module was generated. The
+ name includes the path. */
+ Symtab_t symtab; /* Pointer to the Symtab of
+ the module. The Symtab
+ holds an array of pointers to
+ the classes and categories
+ defined in the module. */
+} Module, *Module_t;
+
+
+/*
+** The compiler generates one of these structures for a class that has
+** instance variables defined in its specification.
+*/
+typedef struct objc_ivar* Ivar_t;
+typedef struct objc_ivar_list {
+ int ivar_count; /* Number of structures (Ivar)
+ contained in the list. One
+ structure per instance
+ variable defined in the
+ class. */
+ struct objc_ivar {
+ const char* ivar_name; /* Name of the instance
+ variable as entered in the
+ class definition. */
+ const char* ivar_type; /* Description of the Ivar's
+ type. Useful for
+ debuggers. */
+ int ivar_offset; /* Byte offset from the base
+ address of the instance
+ structure to the variable. */
+
+ } ivar_list[1]; /* Variable length
+ structure. */
+} IvarList, *IvarList_t;
+
+
+/*
+** The compiler generates one (or more) of these structures for a class that
+** has methods defined in its specification.
+**
+** The implementation of a class can be broken into separate pieces in a file
+** and categories can break them across modules. To handle this problem is a
+** singly linked list of methods.
+*/
+typedef struct objc_method Method;
+typedef Method* Method_t;
+typedef struct objc_method_list {
+ struct objc_method_list* method_next; /* This variable is used to link
+ a method list to another. It
+ is a singly linked list. */
+ int method_count; /* Number of methods defined in
+ this structure. */
+ struct objc_method {
+ SEL method_name; /* This variable is the method's
+ name. It is a char*.
+ The unique integer passed to
+ objc_msg_send is a char* too.
+ It is compared against
+ method_name using strcmp. */
+ const char* method_types; /* Description of the method's
+ parameter list. Useful for
+ debuggers. */
+ IMP method_imp; /* Address of the method in the
+ executable. */
+ } method_list[1]; /* Variable length
+ structure. */
+} MethodList, *MethodList_t;
+
+struct objc_protocol_list {
+ struct objc_protocol_list *next;
+ int count;
+ Protocol *list[1];
+};
+
+/*
+** This is used to assure consistent access to the info field of
+** classes
+*/
+#ifndef HOST_BITS_PER_LONG
+#define HOST_BITS_PER_LONG (sizeof(long)*8)
+#endif
+
+#define __CLS_INFO(cls) ((cls)->info)
+#define __CLS_ISINFO(cls, mask) ((__CLS_INFO(cls)&mask)==mask)
+#define __CLS_SETINFO(cls, mask) (__CLS_INFO(cls) |= mask)
+
+/* The structure is of type MetaClass* */
+#define _CLS_META 0x2L
+#define CLS_ISMETA(cls) ((cls)&&__CLS_ISINFO(cls, _CLS_META))
+
+
+/* The structure is of type Class* */
+#define _CLS_CLASS 0x1L
+#define CLS_ISCLASS(cls) ((cls)&&__CLS_ISINFO(cls, _CLS_CLASS))
+
+/*
+** The class is initialized within the runtime. This means that
+** it has had correct super and sublinks assigned
+*/
+#define _CLS_RESOLV 0x8L
+#define CLS_ISRESOLV(cls) __CLS_ISINFO(cls, _CLS_RESOLV)
+#define CLS_SETRESOLV(cls) __CLS_SETINFO(cls, _CLS_RESOLV)
+
+/*
+** The class has been send a +initialize message or a such is not
+** defined for this class
+*/
+#define _CLS_INITIALIZED 0x04L
+#define CLS_ISINITIALIZED(cls) __CLS_ISINFO(cls, _CLS_INITIALIZED)
+#define CLS_SETINITIALIZED(cls) __CLS_SETINFO(cls, _CLS_INITIALIZED)
+
+/*
+** The class number of this class. This must be the same for both the
+** class and it's meta class object
+*/
+#define CLS_GETNUMBER(cls) (__CLS_INFO(cls) >> (HOST_BITS_PER_LONG/2))
+#define CLS_SETNUMBER(cls, num) \
+ ({ assert(CLS_GETNUMBER(cls)==0); \
+ __CLS_SETINFO(cls, (((unsigned long)num) << (HOST_BITS_PER_LONG/2))); })
+
+/*
+** The compiler generates one of these structures for each category. A class
+** may have many categories and contain both instance and factory methods.
+*/
+typedef struct objc_category {
+ const char* category_name; /* Name of the category. Name
+ contained in the () of the
+ category definition. */
+ const char* class_name; /* Name of the class to which
+ the category belongs. */
+ MethodList_t instance_methods; /* Linked list of instance
+ methods defined in the
+ category. NULL indicates no
+ instance methods defined. */
+ MethodList_t class_methods; /* Linked list of factory
+ methods defined in the
+ category. NULL indicates no
+ class methods defined. */
+ struct objc_protocol_list *protocols; /* List of Protocols
+ conformed to */
+} Category, *Category_t;
+
+/*
+** Structure used when a message is send to a class's super class. The
+** compiler generates one of these structures and passes it to
+** objc_msg_super.
+*/
+typedef struct objc_super {
+ id self; /* Id of the object sending
+ the message. */
+ Class* class; /* Object's super class. */
+} Super, *Super_t;
+
+IMP objc_msg_lookup_super(Super_t super, SEL sel);
+
+retval_t objc_msg_sendv(id, SEL, size_t, arglist_t);
+
+
+
static const ARGSIZE = 96; /* for `method_get_argsize()' */
/*
BOOL sel_is_mapped (SEL aSel);
-extern inline id
-class_create_instance(Class* class)
-{
- id new = nil;
- if (CLS_ISCLASS(class))
- new = (_objc_object_alloc
- ?(*_objc_object_alloc)(class)
- :(id)malloc(class->instance_size));
- if (new!=nil)
- new->class_pointer = class;
- return new;
-}
+extern id class_create_instance(Class* class);
static inline const char *
class_get_class_name(Class* class)
IMP get_imp (Class* class, SEL sel);
-extern inline id
-object_copy(id object)
-{
- if ((object!=nil)&&CLS_ISCLASS(object->class_pointer))
- {
- if (_objc_object_copy)
- return (*_objc_object_copy)(object);
- else
- {
- id copy = class_create_instance(object->class_pointer);
- if (copy!=nil)
- memcpy(copy, object, (size_t)object->class_pointer->instance_size);
- return copy;
- }
- return nil;
- }
-}
+id object_copy(id object);
-extern inline id
-object_dispose(id object)
-{
- if ((object!=nil)&&CLS_ISCLASS(object->class_pointer))
- {
- if (_objc_object_dispose)
- (*_objc_object_dispose)(object);
- else
- free(object);
- }
- return nil;
-}
+id object_dispose(id object);
static inline Class*
object_get_class(id object)
return CLS_ISMETA((Class*)object);
}
+#endif /* not __objc_api_INCLUDE_GNU */
-/* Archiving stuff */
-
-#ifndef __alpha__
-
-typedef int (*objc_typed_read_func)(void*, char*, int);
-typedef int (*objc_typed_write_func)(void*, const char*, int);
-typedef int (*objc_typed_flush_func)(void*);
-typedef int (*objc_typed_eof_func)(void*);
-
-#define OBJC_READONLY 0x01
-#define OBJC_WRITEONLY 0x02
-
-#define OBJC_MANAGED_STREAM 0x01
-#define OBJC_FILE_STREAM 0x02
-#define OBJC_MEMORY_STREAM 0x04
-
-#define OBJC_TYPED_STREAM_VERSION 0x01
-
-struct objc_typed_stream {
- void* physical;
- cache_ptr object_table; /* read/written objects */
- cache_ptr stream_table; /* other read/written but shared things.. */
- cache_ptr class_table; /* class version mapping */
- cache_ptr object_refs; /* forward references */
- int mode; /* OBJC_READONLY or OBJC_WRITEONLY */
- int type; /* MANAGED, FILE, MEMORY etc bit string */
- int version; /* version used when writing */
- int writing_root_p;
- objc_typed_read_func read;
- objc_typed_write_func write;
- objc_typed_eof_func eof;
- objc_typed_flush_func flush;
-};
-
-/* opcode masks */
-#define _B_VALUE 0x1fU
-#define _B_CODE 0xe0U
-#define _B_SIGN 0x10U
-#define _B_NUMBER 0x0fU
-
-/* standard opcodes */
-#define _B_INVALID 0x00U
-#define _B_SINT 0x20U
-#define _B_NINT 0x40U
-#define _B_SSTR 0x60U
-#define _B_NSTR 0x80U
-#define _B_RCOMM 0xa0U
-#define _B_UCOMM 0xc0U
-#define _B_EXT 0xe0U
-
-/* eXtension opcodes */
-#define _BX_OBJECT 0x00U
-#define _BX_CLASS 0x01U
-#define _BX_SEL 0x02U
-#define _BX_OBJREF 0x03U
-#define _BX_OBJROOT 0x04U
-#define _BX_EXT 0x1fU
-
-/*
-** Read and write objects as specified by TYPE. All the `last'
-** arguments are pointers to the objects to read/write.
-*/
-
-int objc_write_type (TypedStream* stream, const char* type, const void* data);
-int objc_read_type (TypedStream* stream, const char* type, void* data);
-
-int objc_write_types (TypedStream* stream, const char* type, ...);
-int objc_read_types (TypedStream* stream, const char* type, ...);
-
-int objc_write_object_reference (TypedStream* stream, id object);
-int objc_write_root_object (TypedStream* stream, id object);
-
-int objc_get_stream_class_version (TypedStream* stream, Class* class);
-
-
-/*
-** Convenience funtions
-*/
-
-int objc_write_array (TypedStream* stream, const char* type,
- int count, const void* data);
-int objc_read_array (TypedStream* stream, const char* type,
- int count, void* data);
-
-int objc_write_object (TypedStream* stream, id object);
-
-/*
-** Open a typed stream for reading or writing. MODE may be either of
-** OBJC_READONLY or OBJC_WRITEONLY.
-*/
-
-TypedStream* objc_open_typed_stream (FILE* physical, int mode);
-TypedStream* objc_open_typed_stream_for_file (const char* file_name, int mode);
-
-void objc_close_typed_stream (TypedStream* stream);
-BOOL objc_end_of_typed_stream (TypedStream* stream);
-void objc_flush_typed_stream (TypedStream* stream);
-#endif /* __alpha__ */
-#endif /* not __objc_api_INCLUDE_GNU */
#ifndef __objc_INCLUDE_GNU
#define __objc_INCLUDE_GNU
-#ifdef IN_GCC
-#include "config.h"
-#include "gstddef.h"
-#else
-#include <stddef.h>
+#ifdef __cplusplus
+extern "C" {
#endif
-extern size_t strlen(char*);
-extern void* malloc(size_t);
-extern void* calloc(size_t, size_t);
-extern void* realloc(const void*, size_t);
-extern void free(const void*);
+#include <stddef.h>
/*
-** Hash-cache or sparse arrays?
-*/
-#define OBJC_SPARSE_LOOKUP /* use sparse-arrays for lookup */
-/* #define OBJC_HASH_LOOKUP */ /* use hash-cache for lookup */
-
-#ifdef OBJC_SPARSE_LOOKUP
-extern const char* __objc_sparse_lookup_id;
-#endif
-
-#ifdef OBJC_HASH_LOOKUP
-extern const char* __objc_hash_lookup_id;
-#endif
-
-#ifndef __object_INCLUDE_GNU
-
+** Definition of the boolean type.
+*/
typedef char BOOL;
#define YES (BOOL)1
#define NO (BOOL)0
struct objc_class* class_pointer;
} *id;
+/*
+** Definition of method type. When retrieving the implementation of a
+** method, this is type of the pointer returned
+*/
typedef id (*IMP)(id, SEL, ...);
/*
-** The compiler generates one of these structures for each class.
-**
-** This structure is the definition for meta classes. By definition a meta
-** class is the class's class. Its most relevant contribution is that its
-** method list contain the class's factory methods.
-**
-** This structure is generated by the compiler in the executable and used by
-** the run-time during normal messaging operations. Therefore some members
-** change type. The compiler generates "char* const" and places a string in
-** the following member variables: class_pointer and super_class.
+** More simple types...
*/
-typedef struct objc_class MetaClass;
-typedef struct objc_class Class;
-
#define nil (id)0 /* id of Nil instance */
#define Nil (Class*)0 /* id of Nil class */
typedef char *STR; /* String alias */
-#endif /* __object_INCLUDE_GNU */
-
-/* For functions which return Method_t */
-#define METHOD_NULL (Method_t)0
- /* Boolean typedefs */
-/*
-** Method descriptor returned by introspective Object methods.
-** This is really just the first part of the more complete objc_method
-** structure defined below and used internally by the runtime.
-*/
-struct objc_method_description
-{
- SEL name; /* this is a selector, not a string */
- char *types; /* type encoding */
-};
-
-
-
-/* Filer types used to describe Ivars and Methods. */
-#define _C_ID '@'
-#define _C_CLASS '#'
-#define _C_SEL ':'
-#define _C_CHR 'c'
-#define _C_UCHR 'C'
-#define _C_SHT 's'
-#define _C_USHT 'S'
-#define _C_INT 'i'
-#define _C_UINT 'I'
-#define _C_LNG 'l'
-#define _C_ULNG 'L'
-#define _C_FLT 'f'
-#define _C_DBL 'd'
-#define _C_BFLD 'b'
-#define _C_VOID 'v'
-#define _C_UNDEF '?'
-#define _C_PTR '^'
-#define _C_CHARPTR '*'
-#define _C_ATOM '%'
-#define _C_ARY_B '['
-#define _C_ARY_E ']'
-#define _C_UNION_B '('
-#define _C_UNION_E ')'
-#define _C_STRUCT_B '{'
-#define _C_STRUCT_E '}'
-
-
-
-/*
-** Set this variable nonzero to print a line describing each
-** message that is sent.
-*/
-extern BOOL objc_trace;
-
-
-/*
-** Whereas a Module (defined further down) is the root (typically) of a file,
-** a Symtab is the root of the class and category definitions within the
-** module.
-**
-** A Symtab contains a variable length array of pointers to classes and
-** categories defined in the module.
-*/
-typedef struct objc_symtab {
- unsigned long sel_ref_cnt; /* Unknown. */
- SEL *refs; /* Unknown. */
- unsigned short cls_def_cnt; /* Number of classes compiled
- (defined) in the module. */
- unsigned short cat_def_cnt; /* Number of categories
- compiled (defined) in the
- module. */
- void *defs[1]; /* Variable array of pointers.
- cls_def_cnt of type Class*
- followed by cat_def_cnt of
- type Category_t. */
-} Symtab, *Symtab_t;
-
-
-/*
-** The compiler generates one of these structures for each module that
-** composes the executable (eg main.m).
-**
-** This data structure is the root of the definition tree for the module.
-**
-** A collect program runs between ld stages and creates a ObjC ctor array.
-** That array holds a pointer to each module structure of the executable.
-*/
-typedef struct objc_module {
- unsigned long version; /* Compiler revision. */
- unsigned long size; /* sizeof(Module). */
- const char* name; /* Name of the file where the
- module was generated. The
- name includes the path. */
- Symtab_t symtab; /* Pointer to the Symtab of
- the module. The Symtab
- holds an array of pointers to
- the classes and categories
- defined in the module. */
-} Module, *Module_t;
-
-
-/*
-** The compiler generates one of these structures for a class that has
-** instance variables defined in its specification.
-*/
-typedef struct objc_ivar* Ivar_t;
-typedef struct objc_ivar_list {
- int ivar_count; /* Number of structures (Ivar)
- contained in the list. One
- structure per instance
- variable defined in the
- class. */
- struct objc_ivar {
- const char* ivar_name; /* Name of the instance
- variable as entered in the
- class definition. */
- const char* ivar_type; /* Description of the Ivar's
- type. Useful for
- debuggers. */
- int ivar_offset; /* Byte offset from the base
- address of the instance
- structure to the variable. */
-
- } ivar_list[1]; /* Variable length
- structure. */
-} IvarList, *IvarList_t;
-
-
-/*
-** The compiler generates one (or more) of these structures for a class that
-** has methods defined in its specification.
-**
-** The implementation of a class can be broken into separate pieces in a file
-** and categories can break them across modules. To handle this problem is a
-** singly linked list of methods.
-*/
-typedef struct objc_method Method;
-typedef Method* Method_t;
-typedef struct objc_method_list {
- struct objc_method_list* method_next; /* This variable is used to link
- a method list to another. It
- is a singly linked list. */
- int method_count; /* Number of methods defined in
- this structure. */
- struct objc_method {
- SEL method_name; /* This variable is the method's
- name. It is a char*.
- The unique integer passed to
- objc_msg_send is a char* too.
- It is compared against
- method_name using strcmp. */
- const char* method_types; /* Description of the method's
- parameter list. Useful for
- debuggers. */
- IMP method_imp; /* Address of the method in the
- executable. */
- } method_list[1]; /* Variable length
- structure. */
-} MethodList, *MethodList_t;
-
-
-#include "objc/sarray.h"
-
-#ifdef OBJC_HASH_LOOKUP
-
-/*
-** This data structure is used for the hash lookup mechanism. When
-** enabled, the runtime keeps a such cache of buckets for each class.
-*/
-typedef struct objc_cache* Cache_t;
-typedef struct objc_bucket* Bucket_t;
-typedef struct objc_bucket Bucket;
-struct objc_cache {
- unsigned int mask; /* total = mask+1 */
- unsigned int occupied;
- struct objc_bucket {
- SEL method_selector;
- IMP method_imp;
- } buckets[1];
-} Cache;
-
-#endif
-
/*
** The compiler generates one of these structures for each class.
**
** change type. The compiler generates "char* const" and places a string in
** the following member variables: super_class.
*/
+typedef struct objc_class MetaClass;
+typedef struct objc_class Class;
struct objc_class {
MetaClass* class_pointer; /* Pointer to the class's
meta class. */
The sum of the class definition
and all super class
definitions. */
- IvarList_t ivars; /* Pointer to a structure that
+ struct objc_ivar_list* ivars; /* Pointer to a structure that
describes the instance
variables in the class
definition. NULL indicates
no instance variables. Does
not include super class
variables. */
- MethodList_t methods; /* Linked list of instance
+ struct objc_method_list* methods; /* Linked list of instance
methods defined for the
class. */
-#ifdef OBJC_HASH_LOOKUP
- Cache_t cache; /* Pointer to method cache */
-#else
struct sarray * dtable; /* Pointer to instance
method dispatch table. */
-#endif
-
struct objc_class* subclass_list; /* Subclasses */
struct objc_class* sibling_class;
struct objc_protocol_list *protocols; /* Protocols conformed to */
-
};
-#ifndef __object_INCLUDE_GNU
-/* Protocol support */
-
#ifndef __OBJC__
typedef struct objc_protocol {
char *protocol_name;
@class Protocol;
#endif
-#endif
-
-struct objc_protocol_list {
- struct objc_protocol_list *next;
- int count;
- Protocol *list[1];
-};
-
-/*
-** This is used to assure consistent access to the info field of
-** classes
-*/
-#ifndef HOST_BITS_PER_LONG
-#define HOST_BITS_PER_LONG (sizeof(long)*8)
-#endif
-
-#define __CLS_INFO(cls) ((cls)->info)
-#define __CLS_ISINFO(cls, mask) ((__CLS_INFO(cls)&mask)==mask)
-#define __CLS_SETINFO(cls, mask) (__CLS_INFO(cls) |= mask)
-
-/* The structure is of type MetaClass* */
-#define _CLS_META 0x2L
-#define CLS_ISMETA(cls) ((cls)&&__CLS_ISINFO(cls, _CLS_META))
-
-
-/* The structure is of type Class* */
-#define _CLS_CLASS 0x1L
-#define CLS_ISCLASS(cls) ((cls)&&__CLS_ISINFO(cls, _CLS_CLASS))
-
-/*
-** The class is initialized within the runtime. This means that
-** it has had correct super and sublinks assigned
-*/
-#define _CLS_RESOLV 0x8L
-#define CLS_ISRESOLV(cls) __CLS_ISINFO(cls, _CLS_RESOLV)
-#define CLS_SETRESOLV(cls) __CLS_SETINFO(cls, _CLS_RESOLV)
-
-/*
-** The class has been send a +initialize message or a such is not
-** defined for this class
-*/
-#define _CLS_INITIALIZED 0x04L
-#define CLS_ISINITIALIZED(cls) __CLS_ISINFO(cls, _CLS_INITIALIZED)
-#define CLS_SETINITIALIZED(cls) __CLS_SETINFO(cls, _CLS_INITIALIZED)
-
-/*
-** The class number of this class. This must be the same for both the
-** class and it's meta class object
-*/
-#define CLS_GETNUMBER(cls) (__CLS_INFO(cls) >> (HOST_BITS_PER_LONG/2))
-#define CLS_SETNUMBER(cls, num) \
- ({ assert(CLS_GETNUMBER(cls)==0); \
- __CLS_SETINFO(cls, (((unsigned long)num) << (HOST_BITS_PER_LONG/2))); })
-
-/*
-** The compiler generates one of these structures for each category. A class
-** may have many categories and contain both instance and factory methods.
-*/
-typedef struct objc_category {
- const char* category_name; /* Name of the category. Name
- contained in the () of the
- category definition. */
- const char* class_name; /* Name of the class to which
- the category belongs. */
- MethodList_t instance_methods; /* Linked list of instance
- methods defined in the
- category. NULL indicates no
- instance methods defined. */
- MethodList_t class_methods; /* Linked list of factory
- methods defined in the
- category. NULL indicates no
- class methods defined. */
- struct objc_protocol_list *protocols; /* List of Protocols
- conformed to */
-} Category, *Category_t;
-
-/*
-** Well...
-*/
-
-#ifndef __object_INCLUDE_GNU
-typedef struct objc_typed_stream TypedStream;
-#endif
-
-/*
-** Structure used when a message is send to a class's super class. The
-** compiler generates one of these structures and passes it to
-** objc_msg_super.
-*/
-typedef struct objc_super {
- id self; /* Id of the object sending
- the message. */
- Class* class; /* Object's super class. */
-} Super, *Super_t;
-
-IMP objc_msg_lookup_super(Super_t super, SEL sel);
-
typedef void* retval_t; /* return value */
typedef void(*apply_t)(void); /* function pointer */
-#ifndef __object_INCLUDE_GNU
-
#if defined(REG_ARGS) || defined(STACK_ARGS)
typedef struct {
typedef void* arglist_t;
#endif
-#endif /* not __object_INCLUDE_GNU */
-retval_t objc_msg_sendv(id, SEL, size_t, arglist_t);
+#if defined(__OBJC__)
-#ifdef __OBJC__
+#include "objc/sarray.h"
static id nil_method(id rcv, SEL op, ...) { return rcv; }
-#ifdef OBJC_HASH_LOOKUP
-
-#include "objc/cache.h"
-
-extern __inline__ IMP
-objc_msg_lookup(id receiver, SEL op)
-{
- if(receiver)
- return cache_get(receiver->class_pointer, op);
- else
- return nil_method;
-}
-
-#else /* not OBJC_HASH_LOOKUP => OBJC_SPARSE_LOOKUP */
-
extern __inline__ IMP
objc_msg_lookup(id receiver, SEL op)
{
else
return nil_method;
}
-#endif /* not OBJC_HASH_LOOKUP */
#else
- IMP objc_msg_lookup(id, SEL);
+
+IMP objc_msg_lookup(id receiver, SEL op);
+
#endif
+#ifdef __cplusplus
+}
+#endif
#endif /* not __objc_INCLUDE_GNU */
id
class_create_instance(Class* class)
{
- id res = (*_objc_object_alloc)(class);
- res->class_pointer = class;
- return res;
+ id new = nil;
+ if (CLS_ISCLASS(class))
+ new = (*_objc_object_alloc)(class);
+ if (new!=nil)
+ new->class_pointer = class;
+ return new;
}
-id
+id
object_copy(id object)
{
- return (*_objc_object_copy)(object);
+ if ((object!=nil)&&CLS_ISCLASS(object->class_pointer))
+ return (*_objc_object_copy)(object);
+ else
+ return nil;
}
-id
+id
object_dispose(id object)
{
- return (*_objc_object_dispose)(object);
+ if ((object!=nil)&&CLS_ISCLASS(object->class_pointer))
+ {
+ if (_objc_object_dispose)
+ (*_objc_object_dispose)(object);
+ else
+ free(object);
+ }
+ return nil;
}
id __objc_object_alloc(Class* class)
#define __objc_runtime_INCLUDE_GNU
#include <stdio.h>
-#include <memory.h>
#include <ctype.h>
-#include "gstdarg.h" /* for varargs and va_list's */
-#include "gstddef.h" /* so noone else will get system versions */
+#include "stdarg.h" /* for varargs and va_list's */
+#include "stddef.h" /* so noone else will get system versions */
#include "assert.h"
#include "objc/objc.h" /* core data types */
#include "objc/sarray.h"
#include <stdio.h>
#include "assert.h"
-#include <memory.h>
int nbuckets = 0;
int nindices = 0;
extern const char* __objc_sparse3_id;
#endif
-#ifdef IN_GCC
-#include "gstddef.h"
-#else
#include <stddef.h>
-#endif
extern int nbuckets; /* for stats */
extern int nindices;
return ((idx > 0) && (idx <= __objc_selector_max_index));
}
-#ifdef OBJC_SPARSE_LOOKUP
/* The uninstalled dispatch table */
extern struct sarray* __objc_uninstalled_dtable;
-#endif
/* Store the passed selector name in the selector record and return its
selector value (value returned by sel_get_uid). */
sarray_at_put_safe (__objc_selector_array, i, (void *) sel);
hash_add (&__objc_selector_hash, (void *) sel, (void *) i);
-#ifdef OBJC_SPARSE_LOOKUP
sarray_realloc(__objc_uninstalled_dtable, __objc_selector_max_index+1);
-#endif
return (SEL) i;
}
covered by the GNU General Public License. */
#include "runtime.h"
+#include "sarray.h"
-#ifdef OBJC_SPARSE_LOOKUP
-const char* __objc_sparse_lookup_id = "Method lookup uses sparse arrays";
-#endif
-
-#ifdef OBJC_HASH_LOOKUP
-const char* __objc_hash_lookup_id = "Method lookup uses hash caching";
-#endif
-
-#ifdef OBJC_HASH_LOOKUP
-#include "objc/cache.h"
-#endif
-
-#ifdef OBJC_SPARSE_LOOKUP
/* The uninstalled dispatch table */
struct sarray* __objc_uninstalled_dtable = 0;
-#endif
/* Send +initialize to class */
static void __objc_send_initialize(Class*);
static void __objc_install_dispatch_table_for_class (Class*);
/* Forward declare some functions */
-#ifdef OBJC_SPARSE_LOOKUP
static void __objc_init_install_dtable(id, SEL);
-#endif
static id __objc_missing_method(id, 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);
__inline__ IMP
get_imp (Class* class, SEL sel)
{
-#ifdef OBJC_SPARSE_LOOKUP
void* res = sarray_get (class->dtable, (size_t) sel);
if(res == __objc_init_install_dtable)
__objc_install_dispatch_table_for_class (class);
return sarray_get (class->dtable, (size_t) sel);
-#else
- return cache_get (class, sel);
-#endif
}
__inline__ BOOL
objc_msg_lookup(id receiver, SEL op)
{
if(receiver)
-#ifdef OBJC_HASH_LOOKUP
- return cache_get(receiver->class_pointer, op);
-#else
return sarray_get(receiver->class_pointer->dtable, (sidx)op);
-#endif
else
return nil_method;
}
void __objc_init_dispatch_tables()
{
-#ifdef OBJC_SPARSE_LOOKUP
__objc_uninstalled_dtable
= sarray_new(200, __objc_init_install_dtable);
-#endif
}
-#ifdef OBJC_SPARSE_LOOKUP
/* This one is a bit hairy. This function is installed in the
premature dispatch table, and thus called once for each class,
namely when the very first message is send to it. */
__builtin_return (result);
}
-#endif
/* Install dummy table for class which causes the first message to
that class (or instances hereof) to be initialized properly */
void __objc_install_premature_dtable(Class* class)
{
-#ifdef OBJC_SPARSE_LOOKUP
assert(__objc_uninstalled_dtable);
class->dtable = __objc_uninstalled_dtable;
-#else
- class->cache = (Cache_t)__objc_xcalloc(1, sizeof(Cache));
-#endif
}
/* Send +initialize to class if not already done */
static void
__objc_install_dispatch_table_for_class (Class* class)
{
-#ifdef OBJC_SPARSE_LOOKUP
Class* super;
MethodList_t mlist;
int counter;
counter -= 1;
}
}
-#endif
}
void __objc_update_dispatch_table_for_class (Class* class)
{
Class* next;
-#ifdef OBJC_SPARSE_LOOKUP
struct sarray* save;
-#else
- Cache_t save;
-#endif
/* not yet installed -- skip it */
-#ifdef OBJC_SPARSE_LOOKUP
if (class->dtable == __objc_uninstalled_dtable)
-#else
- if (class->cache->mask == 0)
-#endif
return;
-#ifdef OBJC_SPARSE_LOOKUP
save = class->dtable;
__objc_install_premature_dtable (class);
sarray_free (save);
-#else
- save = class->cache;
- __objc_install_premature_dtable (class);
- free(save);
-
-#endif
if (class->subclass_list) /* Traverse subclasses */
for (next = class->subclass_list; next; next = next->sibling_class)
{
int total = 0;
printf("memory usage: (%s)\n",
-#ifdef OBJC_SPARSE_LOOKUP
#ifdef OBJC_SPARSE2
"2-level sparse arrays"
#else
"3-level sparse arrays"
#endif
-#else
- "hash-cache"
-#endif
);
-#ifdef OBJC_SPARSE_LOOKUP
printf("arrays: %d = %d bytes\n", narrays, narrays*sizeof(struct sarray));
total += narrays*sizeof(struct sarray);
-#ifdef OBJC_SPARSE3
- printf("indices: %d = %d bytes\n", nindices, nindices*sizeof(struct sindex));
- total += nindices*sizeof(struct sindex);
-#endif
printf("buckets: %d = %d bytes\n", nbuckets, nbuckets*sizeof(struct sbucket));
total += nbuckets*sizeof(struct sbucket);
printf("idxtables: %d = %d bytes\n", idxsize, idxsize*sizeof(void*));
total += idxsize*sizeof(void*);
-#else /* HASH_LOOKUP */
- total = __objc_class_hash_tables_size ();
-#endif
printf("-----------------------------------\n");
printf("total: %d bytes\n", total);
printf("===================================\n");
}
-#ifdef OBJC_HASH_LOOKUP
-static Cache_t __objc_cache_insert(Cache_t cache, SEL op, IMP imp);
-
-static Cache_t
-__objc_double_cache(Cache_t cache)
-{
- int i;
- Cache_t newc = (Cache_t)__objc_xcalloc(1, sizeof(Cache)
- +(sizeof(Cache)*2*(cache->mask+1)));
- newc->occupied = cache->occupied;
- newc->mask = ((cache->mask)<<1) | 1;
- for(i=0; i <= cache->mask; i++)
- newc = __objc_cache_insert(newc,
- cache->buckets[i].method_selector,
- cache->buckets[i].method_imp);
- free(cache);
- return newc;
-}
-
-
-static Cache_t
-__objc_cache_insert(Cache_t cache, SEL op, IMP imp)
-{
- int index = ((size_t)op)&(cache)->mask;
-
- if(op == 0)
- return cache;
-
- do
- {
- if((cache)->buckets[index].method_selector == 0)
- {
- (cache)->buckets[index].method_selector = op;
- (cache)->buckets[index].method_imp = imp;
- (cache)->occupied += 1;
- return cache;
- }
- }
- while (--index >= 0);
-
- cache = __objc_double_cache(cache);
- return __objc_cache_insert(cache, op, imp);
-}
-
-void*
-__objc_cache_miss(Class* class, SEL op)
-{
- Method_t m;
- Cache_t cache = class->cache;
-
- if(!CLS_ISRESOLV(class))
- __objc_resolve_class_links();
-
- m = search_for_method_in_hierarchy(class, op);
-
- if(!CLS_ISINITIALIZED(class))
- if(CLS_ISMETA(class))
- __objc_send_initialize(objc_get_class(class->name));
- else
- __objc_send_initialize(class);
-
- if(m == NULL)
- return __objc_missing_method;
-
- if((cache->occupied+2)*2 > cache->mask)
- class->cache = __objc_double_cache(cache);
-
- class->cache = __objc_cache_insert(class->cache, op, m->method_imp);
- return m->method_imp;
-}
-
-#endif